test(codemode): add promise conformance corpus

This commit is contained in:
Aiden Cline 2026-07-09 16:14:23 -05:00
parent 02ce4a330f
commit 367db9d2e6
3 changed files with 696 additions and 146 deletions

View file

@ -0,0 +1,696 @@
/*
* Portions adapted from Test262 at revision 250f204f23a9249ff204be2baec29600faae7b75.
* Every test names its upstream source; test.failing cases are executable conformance
* targets for intended Promise behavior that CodeMode does not implement yet.
*
* Copyright 2014 Cubane Canada, Inc. All rights reserved.
* Copyright 2015 Microsoft Corporation. All rights reserved.
* Copyright 2016 Microsoft, Inc. All rights reserved.
* Copyright 2017 Caitlin Potter. All rights reserved.
* Copyright (C) 2016-2020 the V8 project authors. All rights reserved.
* Copyright (C) 2018-2020 Rick Waldron. All rights reserved.
* Copyright (C) 2019 Leo Balter. All rights reserved.
* Test262 portions are governed by the BSD license in LICENSE.test262.
*/
import { describe, expect, test } from "bun:test"
import { Effect } from "effect"
import { CodeMode } from "../src/index.js"
const execute = (code: string) =>
Effect.runPromise(CodeMode.execute({ code, tools: {}, limits: { timeoutMs: 1_000 } }))
const value = async (code: string) => {
const result = await execute(code)
if (!result.ok) throw new Error(`expected success, got ${result.error.kind}: ${result.error.message}`)
return result.value
}
describe("Test262 Promise statics", () => {
test("statics are callable and return promises", async () => {
// Sources:
// test/built-ins/Promise/all/S25.4.4.1_A1.1_T1.js
// test/built-ins/Promise/allSettled/is-function.js
// test/built-ins/Promise/allSettled/returns-promise.js
// test/built-ins/Promise/race/S25.4.4.3_A1.1_T1.js
// test/built-ins/Promise/resolve/S25.4.4.5_A1.1_T1.js
// test/built-ins/Promise/reject/S25.4.4.4_A1.1_T1.js
expect(
await value(`
const values = [
Promise.all([]),
Promise.allSettled([]),
Promise.race([undefined]),
Promise.resolve(),
Promise.reject(),
]
const callable = [
typeof Promise.all,
typeof Promise.allSettled,
typeof Promise.race,
typeof Promise.resolve,
typeof Promise.reject,
]
try { await values[4] } catch {}
return [callable, values.map((item) => item instanceof Promise)]
`),
).toEqual([
["function", "function", "function", "function", "function"],
[true, true, true, true, true],
])
})
test("Promise.all returns fresh arrays for empty and settled inputs", async () => {
// Sources:
// test/built-ins/Promise/all/S25.4.4.1_A2.1_T1.js
// test/built-ins/Promise/all/S25.4.4.1_A2.3_T1.js
// test/built-ins/Promise/all/S25.4.4.1_A2.3_T2.js
// test/built-ins/Promise/all/S25.4.4.1_A2.3_T3.js
// test/built-ins/Promise/all/S25.4.4.1_A7.1_T1.js
expect(
await value(`
const input = []
const emptyPromise = Promise.all(input)
const empty = await emptyPromise
const onePromise = Promise.all([Promise.resolve(3)])
const one = await onePromise
return [
emptyPromise instanceof Promise,
empty instanceof Array,
empty.length,
empty !== input,
onePromise instanceof Promise,
one instanceof Array,
one.length,
one[0],
]
`),
).toEqual([true, true, 0, true, true, true, 1, 3])
})
test("Promise.all adopts values and preserves input order and identity", async () => {
// Sources:
// test/built-ins/Promise/all/resolve-non-thenable.js
// test/built-ins/Promise/all/S25.4.4.1_A8.2_T1.js
// test/built-ins/Promise/all/S25.4.4.1_A8.2_T2.js
const result = await value(`
const first = { id: 1 }
const second = { id: 2 }
const values = await Promise.all([Promise.resolve(3), first, Promise.resolve(second)])
const observe = async (promise) => {
try { await promise; return "fulfilled" } catch (reason) { return reason }
}
return [
values.length,
values[0],
values[1] === first,
values[2] === second,
await observe(Promise.all([Promise.reject(1), Promise.resolve(2)])),
await observe(Promise.all([Promise.resolve(1), Promise.reject(2)])),
]
`)
expect(result).toEqual([3, 3, true, true, 1, 2])
})
test("Promise.allSettled returns fresh arrays and ordered outcome records", async () => {
// Sources:
// test/built-ins/Promise/allSettled/resolves-empty-array.js
// test/built-ins/Promise/allSettled/resolves-to-array.js
// test/built-ins/Promise/allSettled/resolved-all-fulfilled.js
// test/built-ins/Promise/allSettled/resolved-all-rejected.js
// test/built-ins/Promise/allSettled/resolved-all-mixed.js
// test/built-ins/Promise/allSettled/resolve-non-thenable.js
expect(
await value(`
const input = []
const empty = await Promise.allSettled(input)
const reason = { id: 4 }
const object = { id: 5 }
const outcomes = await Promise.allSettled([
Promise.resolve(1),
Promise.reject(2),
3,
Promise.reject(reason),
object,
])
return [
empty instanceof Array,
empty.length,
empty !== input,
outcomes,
outcomes[4].value === object,
outcomes.map((item) => Object.keys(item)),
]
`),
).toEqual([
true,
0,
true,
[
{ status: "fulfilled", value: 1 },
{ status: "rejected", reason: 2 },
{ status: "fulfilled", value: 3 },
{ status: "rejected", reason: { id: 4 } },
{ status: "fulfilled", value: { id: 5 } },
],
true,
[
["status", "value"],
["status", "reason"],
["status", "value"],
["status", "reason"],
["status", "value"],
],
])
})
test("Promise.race preserves fulfillment, rejection, and iterable order", async () => {
// Sources:
// test/built-ins/Promise/race/S25.4.4.3_A6.2_T1.js
// test/built-ins/Promise/race/S25.4.4.3_A7.1_T1.js
// test/built-ins/Promise/race/S25.4.4.3_A7.2_T1.js
// test/built-ins/Promise/race/S25.4.4.3_A7.3_T1.js
// test/built-ins/Promise/race/S25.4.4.3_A7.3_T2.js
expect(
await value(`
const observe = async (promise) => {
try { return ["fulfilled", await promise] } catch (reason) { return ["rejected", reason] }
}
return await Promise.all([
observe(Promise.race([23])),
observe(Promise.race([Promise.reject(7)])),
observe(Promise.race([Promise.resolve(1), Promise.resolve(2)])),
observe(Promise.race([Promise.reject(3), Promise.resolve(4)])),
])
`),
).toEqual([
["fulfilled", 23],
["rejected", 7],
["fulfilled", 1],
["rejected", 3],
])
})
test("combinators consume supported string iterables", async () => {
// Sources:
// test/built-ins/Promise/all/iter-arg-is-string-resolve.js
// test/built-ins/Promise/allSettled/iter-arg-is-string-resolve.js
// test/built-ins/Promise/race/iter-arg-is-string-resolve.js
expect(
await value(`
return [
await Promise.all("abc"),
await Promise.allSettled("ab"),
await Promise.race("abc"),
]
`),
).toEqual([
["a", "b", "c"],
[
{ status: "fulfilled", value: "a" },
{ status: "fulfilled", value: "b" },
],
"a",
])
})
test("Promise.resolve adopts values and preserves sandbox-promise identity", async () => {
// Sources:
// test/built-ins/Promise/resolve/S25.4.4.5_A2.1_T1.js
// test/built-ins/Promise/resolve/resolve-non-obj.js
// test/built-ins/Promise/resolve/resolve-non-thenable.js
expect(
await value(`
const object = { id: 1 }
const promise = Promise.resolve(1)
return [
await Promise.resolve(23),
await Promise.resolve(Promise.resolve(24)),
(await Promise.resolve(object)) === object,
[promise].includes(Promise.resolve(promise)),
]
`),
).toEqual([23, 24, true, true])
})
test("Promise.reject preserves primitive and object reasons", async () => {
// Sources:
// test/built-ins/Promise/reject/S25.4.4.4_A2.1_T1.js
const result = await value(`
const object = { reason: true }
const reasons = [undefined, null, false, true, 0, "", 42, object]
const observe = async (reason) => {
try { await Promise.reject(reason); return false } catch (caught) { return caught === reason }
}
return await Promise.all(reasons.map(observe))
`)
expect(result).toEqual([true, true, true, true, true, true, true, true])
})
})
describe("Test262 async functions and await", () => {
test("declaration, expression, and arrow forms return promises", async () => {
// Sources:
// test/language/statements/async-function/declaration-returns-promise.js
// test/language/expressions/async-function/expression-returns-promise.js
// test/language/expressions/async-arrow-function/arrow-returns-promise.js
expect(
await value(`
async function declaration() { return 1 }
const expression = async function() { return 2 }
const arrow = async () => 3
const promises = [declaration(), expression(), arrow()]
return [promises.map((item) => item instanceof Promise), await Promise.all(promises)]
`),
).toEqual([[true, true, true], [1, 2, 3]])
})
test("async bodies adopt returns and reject throws before and after await", async () => {
// Sources:
// test/language/statements/async-function/evaluation-body.js
// test/language/statements/async-function/evaluation-body-that-returns.js
// test/language/statements/async-function/evaluation-body-that-returns-after-await.js
// test/language/statements/async-function/evaluation-body-that-throws.js
// test/language/statements/async-function/evaluation-body-that-throws-after-await.js
expect(
await value(`
const order = []
const plain = async () => { order.push("body"); return 42 }
const afterAwait = async () => { await Promise.resolve(); return 43 }
const throwsBefore = async () => { throw 1 }
const throwsAfter = async () => { await Promise.resolve(); throw 2 }
const observe = async (promise) => {
try { return ["fulfilled", await promise] } catch (reason) { return ["rejected", reason] }
}
const first = plain()
return [
order,
await observe(first),
await observe(afterAwait()),
await observe(throwsBefore()),
await observe(throwsAfter()),
]
`),
).toEqual([
["body"],
["fulfilled", 42],
["fulfilled", 43],
["rejected", 1],
["rejected", 2],
])
})
test("default-parameter throws reject instead of escaping the call", async () => {
// Source: test/language/statements/async-function/evaluation-default-that-throws.js
expect(
await value(`
const fail = () => { throw new Error("default") }
const run = async (value = fail()) => value
let returned = false
try {
const promise = run()
returned = promise instanceof Promise
await promise
return [returned, "fulfilled"]
} catch (error) {
return [returned, error.message]
}
`),
).toEqual([true, "default"])
})
test("async try/finally completion records override earlier completion", async () => {
// Sources: the try-{return,throw,reject}-finally-{return,throw,reject}.js matrix under
// test/language/statements/async-function, test/language/expressions/async-function,
// and test/language/expressions/async-arrow-function.
expect(
await value(`
const observe = async (promise) => {
try { return ["fulfilled", await promise] } catch (reason) { return ["rejected", reason] }
}
const returnReturn = async () => { try { return "early" } finally { return await Promise.resolve("override") } }
const returnThrow = async () => { try { return "early" } finally { throw "override" } }
const returnReject = async () => { try { return "early" } finally { await Promise.reject("override") } }
const throwReturn = async () => { try { throw "early" } finally { return await Promise.resolve("override") } }
const throwThrow = async () => { try { throw "early" } finally { throw "override" } }
const throwReject = async () => { try { throw "early" } finally { await Promise.reject("override") } }
const rejectReturn = async () => { try { await Promise.reject("early") } finally { return await Promise.resolve("override") } }
const rejectThrow = async () => { try { await Promise.reject("early") } finally { throw "override" } }
const rejectReject = async () => { try { await Promise.reject("early") } finally { await Promise.reject("override") } }
return await Promise.all([
observe(returnReturn()), observe(returnThrow()), observe(returnReject()),
observe(throwReturn()), observe(throwThrow()), observe(throwReject()),
observe(rejectReturn()), observe(rejectThrow()), observe(rejectReject()),
])
`),
).toEqual([
["fulfilled", "override"],
["rejected", "override"],
["rejected", "override"],
["fulfilled", "override"],
["rejected", "override"],
["rejected", "override"],
["fulfilled", "override"],
["rejected", "override"],
["rejected", "override"],
])
})
test("await preserves an object whose then property is not callable", async () => {
// Source: test/language/expressions/await/await-awaits-thenable-not-callable.js
expect(
await value(`
const thenable = { then: 42 }
return (await thenable) === thenable
`),
).toBe(true)
})
})
describe("Test262 expected Promise conformance", () => {
for (const name of ["all", "allSettled", "race"] as const) {
test.failing(`Promise.${name} rejects invalid input with TypeError`, async () => {
// Sources:
// test/built-ins/Promise/all/S25.4.4.1_A3.1_T1.js
// test/built-ins/Promise/all/S25.4.4.1_A3.1_T2.js
// test/built-ins/Promise/allSettled/iter-arg-is-number-reject.js
// test/built-ins/Promise/race/iter-arg-is-number-reject.js
expect(
await value(`
try {
const promise = Promise.${name}(42)
const returned = promise instanceof Promise
await promise
return [returned, "fulfilled"]
} catch (error) {
return [true, error.name]
}
`),
).toEqual([true, "TypeError"])
})
}
test.failing("Promise.all consumes sparse positions as undefined", async () => {
// Source: test/built-ins/Array/from/from-array.js (array iterator hole behavior)
expect(
await value(`
const input = []
input[1] = 1
const result = await Promise.all(input)
return [result.length, result[0] === undefined, result[1]]
`),
).toEqual([2, true, 1])
})
test.failing("Promise.allSettled consumes sparse positions as undefined", async () => {
// Source: test/built-ins/Array/from/from-array.js (array iterator hole behavior)
expect(
await value(`
const input = []
input[1] = 1
const result = await Promise.allSettled(input)
return [result.length, result[0].status, result[0].value === undefined, result[1]]
`),
).toEqual([2, "fulfilled", true, { status: "fulfilled", value: 1 }])
})
test.failing("Promise.race consumes a sparse first position as undefined", async () => {
// Source: test/built-ins/Array/from/from-array.js (array iterator hole behavior)
expect(
await value(`
const input = []
input[1] = 1
return (await Promise.race(input)) === undefined
`),
).toBe(true)
})
test.failing("Promise.all settles after reactions attached to its inputs", async () => {
// Sources:
// test/built-ins/Promise/all/S25.4.4.1_A7.2_T1.js
// test/built-ins/Promise/all/S25.4.4.1_A8.1_T1.js
expect(
await value(`
const sequence = [1]
const input = Promise.resolve(1)
const aggregate = Promise.all([input])
aggregate.then(() => sequence.push(4))
input.then(() => sequence.push(3)).then(() => sequence.push(5))
sequence.push(2)
await aggregate
await Promise.resolve()
return sequence
`),
).toEqual([1, 2, 3, 4, 5])
})
test.failing("Promise.allSettled settles after reactions attached to its inputs", async () => {
// Sources:
// test/built-ins/Promise/allSettled/resolved-sequence.js
// test/built-ins/Promise/allSettled/resolved-sequence-extra-ticks.js
// test/built-ins/Promise/allSettled/resolved-sequence-mixed.js
// test/built-ins/Promise/allSettled/resolved-sequence-with-rejections.js
expect(
await value(`
const sequence = [1]
const input = Promise.resolve(1)
const aggregate = Promise.allSettled([input])
aggregate.then(() => sequence.push(4))
input.then(() => sequence.push(3)).then(() => sequence.push(5))
sequence.push(2)
await aggregate
await Promise.resolve()
return sequence
`),
).toEqual([1, 2, 3, 4, 5])
})
test.failing("Promise.race settles in a reaction after its winning input", async () => {
// Sources:
// test/built-ins/Promise/race/S25.4.4.3_A6.1_T1.js
// test/built-ins/Promise/race/resolved-sequence-extra-ticks.js
expect(
await value(`
const sequence = [1]
const race = Promise.race([1])
race.then(() => sequence.push(4))
Promise.resolve().then(() => sequence.push(3)).then(() => sequence.push(5))
sequence.push(2)
await race
await Promise.resolve()
return sequence
`),
).toEqual([1, 2, 3, 4, 5])
})
test.failing("then reactions route and propagate fulfillment and rejection", async () => {
// Sources:
// test/built-ins/Promise/prototype/then/prfm-fulfilled.js
// test/built-ins/Promise/prototype/then/prfm-rejected.js
// test/built-ins/Promise/prototype/then/rxn-handler-identity.js
// test/built-ins/Promise/prototype/then/rxn-handler-thrower.js
// test/built-ins/Promise/prototype/then/rxn-handler-fulfilled-return-normal.js
// test/built-ins/Promise/prototype/then/rxn-handler-fulfilled-return-abrupt.js
// test/built-ins/Promise/prototype/then/rxn-handler-rejected-return-normal.js
// test/built-ins/Promise/prototype/then/rxn-handler-rejected-return-abrupt.js
expect(
await value(`
const observe = async (promise) => {
try { return ["fulfilled", await promise] } catch (reason) { return ["rejected", reason] }
}
return await Promise.all([
observe(Promise.resolve(1).then((value) => value + 1)),
observe(Promise.reject(2).then(undefined, (reason) => reason + 1)),
observe(Promise.resolve(3).then(undefined)),
observe(Promise.reject(4).then(undefined)),
observe(Promise.resolve(5).then(() => { throw 6 })),
observe(Promise.reject(7).then(undefined, () => { throw 8 })),
])
`),
).toEqual([
["fulfilled", 2],
["fulfilled", 3],
["fulfilled", 3],
["rejected", 4],
["rejected", 6],
["rejected", 8],
])
})
test.failing("then reactions preserve breadth-first queue order", async () => {
// Source: test/built-ins/Promise/prototype/then/S25.4.4_A1.1_T1.js
expect(
await value(`
const sequence = [1]
const promise = Promise.resolve()
const first = promise.then(() => sequence.push(3)).then(() => sequence.push(5)).then(() => sequence.push(7))
const second = promise.then(() => sequence.push(4)).then(() => sequence.push(6)).then(() => sequence.push(8))
sequence.push(2)
await Promise.all([first, second])
return sequence
`),
).toEqual([1, 2, 3, 4, 5, 6, 7, 8])
})
test.failing("then rejects direct self-resolution for fulfilled and rejected sources", async () => {
// Sources:
// test/built-ins/Promise/prototype/then/resolve-settled-fulfilled-self.js
// test/built-ins/Promise/prototype/then/resolve-settled-rejected-self.js
// test/built-ins/Promise/prototype/then/resolve-pending-fulfilled-self.js
// test/built-ins/Promise/prototype/then/resolve-pending-rejected-self.js
expect(
await value(`
const observe = async (promise) => {
try { await promise; return "fulfilled" } catch (reason) { return reason.name }
}
let fulfilled
let rejected
fulfilled = Promise.resolve().then(() => fulfilled)
rejected = Promise.reject().then(undefined, () => rejected)
return await Promise.all([observe(fulfilled), observe(rejected)])
`),
).toEqual(["TypeError", "TypeError"])
})
test.failing("catch delegates rejection handling and preserves fulfillment", async () => {
// Sources:
// test/built-ins/Promise/prototype/catch/S25.4.5.1_A2.1_T1.js
// test/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T1.js
// test/built-ins/Promise/prototype/catch/S25.4.5.1_A3.1_T2.js
expect(
await value(`
return [
await Promise.resolve(1).catch(() => 2),
await Promise.reject(3).catch((reason) => reason + 1),
]
`),
).toEqual([1, 4])
})
test.failing("finally preserves or replaces the original settlement", async () => {
// Sources:
// test/built-ins/Promise/prototype/finally/resolution-value-no-override.js
// test/built-ins/Promise/prototype/finally/rejection-reason-no-fulfill.js
// test/built-ins/Promise/prototype/finally/rejection-reason-override-with-throw.js
expect(
await value(`
const observe = async (promise) => {
try { return ["fulfilled", await promise] } catch (reason) { return ["rejected", reason] }
}
return await Promise.all([
observe(Promise.resolve(1).finally(() => 2)),
observe(Promise.reject(3).finally(() => 4)),
observe(Promise.reject(5).finally(() => { throw 6 })),
])
`),
).toEqual([
["fulfilled", 1],
["rejected", 3],
["rejected", 6],
])
})
test.failing("await always resumes in a later reaction and interleaves async functions", async () => {
// Sources:
// test/language/expressions/await/async-await-interleaved.js
// test/language/expressions/await/await-non-promise.js
expect(
await value(`
const sequence = []
const first = async () => { sequence.push("first:1"); await 0; sequence.push("first:2") }
const second = async () => { sequence.push("second:1"); await 0; sequence.push("second:2") }
await Promise.all([first(), second()])
return sequence
`),
).toEqual(["first:1", "second:1", "first:2", "second:2"])
})
test.failing("an async function rejects when it resolves with its own promise", async () => {
// Adapted from the self-resolution requirement represented by:
// test/built-ins/Promise/resolve-self.js
// test/built-ins/Promise/resolve/S25.4.4.5_A4.1_T1.js
expect(
await value(`
let promise
const run = async () => {
await Promise.resolve()
return promise
}
promise = run()
try {
await promise
return "fulfilled"
} catch (error) {
return error.name
}
`),
).toBe("TypeError")
})
test.failing("Promise.resolve recursively assimilates callable thenables", async () => {
// Source: test/built-ins/Promise/resolve/resolve-thenable.js
expect(
await value(`
const value = { id: 1 }
const nested = { then: (resolve) => resolve(value) }
const thenable = { then: (resolve) => resolve(nested) }
return (await Promise.resolve(thenable)) === value
`),
).toBe(true)
})
test.failing("Promise combinators assimilate callable thenable inputs", async () => {
// Sources:
// test/built-ins/Promise/all/reject-immed.js
// test/built-ins/Promise/all/reject-ignored-immed.js
// test/built-ins/Promise/allSettled/reject-ignored-immed.js
// test/built-ins/Promise/race/resolve-thenable.js
expect(
await value(`
const fulfills = { then: (resolve) => resolve(1) }
const rejects = { then: (_, reject) => reject(2) }
const resolvesFirst = { then: (resolve, reject) => { resolve(3); reject(4) } }
const observe = async (promise) => {
try { return ["fulfilled", await promise] } catch (reason) { return ["rejected", reason] }
}
return [
await observe(Promise.all([fulfills, rejects])),
await Promise.allSettled([fulfills, resolvesFirst]),
await observe(Promise.race([rejects])),
]
`),
).toEqual([
["rejected", 2],
[
{ status: "fulfilled", value: 1 },
{ status: "fulfilled", value: 3 },
],
["rejected", 2],
])
})
test.failing("await assimilates callable thenables", async () => {
// Source: test/language/expressions/await/await-awaits-thenables.js
expect(
await value(`
const thenable = { then: (resolve) => resolve(42) }
return await thenable
`),
).toBe(42)
})
test.failing("await rejects when a callable thenable throws", async () => {
// Source: test/language/expressions/await/await-awaits-thenables-that-throw.js
expect(
await value(`
const error = { id: 1 }
const thenable = { then: () => { throw error } }
try {
await thenable
return false
} catch (caught) {
return caught === error
}
`),
).toBe(true)
})
})

View file

@ -1,77 +0,0 @@
# Test262 Array Coverage
The Array tests adapt Test262 at revision `250f204f23a9249ff204be2baec29600faae7b75`. They cover CodeMode's 35
exposed instance methods and three static methods using actual arrays, accepted argument types, deterministic behavior,
and CodeMode's materialized collection conventions. Each executable case names its exact upstream source path.
`LICENSE.test262` contains the upstream BSD terms.
This is coverage of CodeMode's bounded Array surface, not a claim of ECMAScript or Test262 conformance. One upstream
file may contain both adapted and inapplicable assertions, so a cited source means only that the represented assertions
were adapted.
## Inventory
The 38 relevant upstream API directories contain 2,837 files. The executable suite adapts assertions from 83 distinct
sources.
| API | Upstream files | Adapted sources |
| ------------------------------- | -------------: | --------------: |
| `Array.prototype.map` | 216 | 3 |
| `Array.prototype.filter` | 242 | 3 |
| `Array.prototype.find` | 23 | 4 |
| `Array.prototype.findIndex` | 23 | 3 |
| `Array.prototype.findLast` | 24 | 3 |
| `Array.prototype.findLastIndex` | 24 | 3 |
| `Array.prototype.some` | 219 | 2 |
| `Array.prototype.every` | 218 | 2 |
| `Array.prototype.includes` | 30 | 2 |
| `Array.prototype.join` | 23 | 2 |
| `Array.prototype.reduce` | 260 | 3 |
| `Array.prototype.reduceRight` | 260 | 3 |
| `Array.prototype.flatMap` | 24 | 2 |
| `Array.prototype.forEach` | 190 | 2 |
| `Array.prototype.sort` | 54 | 3 |
| `Array.prototype.toSorted` | 21 | 4 |
| `Array.prototype.slice` | 71 | 1 |
| `Array.prototype.concat` | 69 | 3 |
| `Array.prototype.indexOf` | 201 | 2 |
| `Array.prototype.lastIndexOf` | 198 | 2 |
| `Array.prototype.at` | 13 | 3 |
| `Array.prototype.flat` | 19 | 2 |
| `Array.prototype.reverse` | 18 | 1 |
| `Array.prototype.toReversed` | 17 | 2 |
| `Array.prototype.with` | 21 | 2 |
| `Array.prototype.push` | 24 | 1 |
| `Array.prototype.pop` | 23 | 1 |
| `Array.prototype.shift` | 20 | 1 |
| `Array.prototype.unshift` | 22 | 1 |
| `Array.prototype.splice` | 81 | 3 |
| `Array.prototype.fill` | 22 | 3 |
| `Array.prototype.copyWithin` | 39 | 2 |
| `Array.prototype.keys` | 12 | 1 |
| `Array.prototype.values` | 12 | 1 |
| `Array.prototype.entries` | 12 | 1 |
| `Array.from` | 47 | 3 |
| `Array.isArray` | 29 | 2 |
| `Array.of` | 16 | 1 |
## Exclusions
Assertions are not adapted when they test behavior outside CodeMode's documented Array surface:
- Function metadata, property descriptors, constructibility, prototype mutation, species constructors, or cross-realm
identity.
- Generic receivers, detached methods, `.call`, `.apply`, boxed values, custom coercion objects, Symbols, BigInts,
proxies, accessors, frozen arrays, typed arrays, or ArrayBuffers.
- `Array.from` mappers, custom iterables, constructor substitution, and iterator-closing behavior.
- Native iterator identity, `.next()`, completion records, or live iterator mutation. CodeMode deliberately materializes
`keys`, `values`, and `entries` as arrays.
- Sparse-array assertions that depend on literal elisions or inherited indexed properties. CodeMode's confined data
model does not preserve those prototype and hole semantics at every boundary.
- Argument coercions outside the accepted schema-like surface. Numeric positions must be numbers and `join` separators
must be strings.
- Exact native error brands where CodeMode exposes a safe runtime error instead.
- Async/effectful callbacks, circular-data rejection, sandbox-value identity, diagnostics, and host-boundary behavior.
Those remain covered by CodeMode-specific tests.
Handwritten tests remain where they specify CodeMode behavior rather than ordinary ECMAScript Array semantics.

View file

@ -1,69 +0,0 @@
# Test262 String Coverage
The String tests adapt Test262 at revision `250f204f23a9249ff204be2baec29600faae7b75`. They cover CodeMode's 32
exposed instance methods and two static methods using primitive receivers, accepted argument types, and deterministic
behavior. Each executable case names its exact upstream source path. `LICENSE.test262` contains the upstream BSD terms.
This is coverage of CodeMode's bounded String surface, not a claim of ECMAScript or Test262 conformance. One upstream
file may contain both adapted and inapplicable assertions, so a cited source means only that the represented assertions
were adapted.
## Inventory
The relevant upstream directories contain 1,048 files: 1,009 core built-in files, 29 Annex B files for exposed methods,
and 10 Intl `localeCompare` files. The executable suite adapts assertions from 298 distinct sources.
| API | Upstream files | Adapted sources |
| --- | ---: | ---: |
| `String.fromCharCode` | 17 | 6 |
| `String.fromCodePoint` | 11 | 4 |
| `String.prototype.at` | 11 | 5 |
| `String.prototype.charAt` | 30 | 9 |
| `String.prototype.charCodeAt` | 25 | 4 |
| `String.prototype.codePointAt` | 16 | 6 |
| `String.prototype.concat` | 22 | 1 |
| `String.prototype.endsWith` | 27 | 13 |
| `String.prototype.includes` | 27 | 12 |
| `String.prototype.indexOf` | 47 | 8 |
| `String.prototype.lastIndexOf` | 25 | 1 |
| `String.prototype.localeCompare` | 23 | 1 |
| `String.prototype.match` | 52 | 9 |
| `String.prototype.matchAll` | 26 | 1 |
| `String.prototype.normalize` | 14 | 3 |
| `String.prototype.padEnd` | 13 | 4 |
| `String.prototype.padStart` | 13 | 4 |
| `String.prototype.repeat` | 16 | 4 |
| `String.prototype.replace` | 56 | 16 |
| `String.prototype.replaceAll` | 46 | 12 |
| `String.prototype.search` | 44 | 10 |
| `String.prototype.slice` | 38 | 11 |
| `String.prototype.split` | 121 | 50 |
| `String.prototype.startsWith` | 21 | 7 |
| `String.prototype.substr` | 15 | 6 |
| `String.prototype.substring` | 46 | 12 |
| `String.prototype.toLowerCase` | 30 | 5 |
| `String.prototype.toString` | 7 | 1 |
| `String.prototype.toUpperCase` | 26 | 3 |
| `String.prototype.trim` | 129 | 66 |
| `String.prototype.trimEnd` | 23 | 2 |
| `String.prototype.trimLeft` | 4 | 0 |
| `String.prototype.trimRight` | 4 | 0 |
| `String.prototype.trimStart` | 23 | 2 |
## Exclusions
Assertions are not adapted when they test behavior outside CodeMode's documented String surface:
- Function metadata, property descriptors, constructibility, prototype mutation, or cross-realm identity.
- The `trimLeft`/`trimRight` Test262 files assert prototype function identity, which CodeMode does not expose. Their
supported call behavior remains covered by CodeMode-specific tests.
- Boxed strings, generic receivers, custom coercion objects, Symbols, BigInts, or argument types CodeMode rejects.
- Symbol-based RegExp dispatch, custom matchers, species constructors, or iterator protocol details. CodeMode materializes
`matchAll` results instead of exposing iterators.
- Locale selection and options. CodeMode deliberately uses the host default locale and ignores those arguments.
- Test262 harness behavior or setup syntax unavailable in the confined interpreter.
- Function-replacer behavior that is covered by CodeMode-specific tests for sequential callbacks, async tool calls,
result coercion, diagnostics, and sandbox boundaries.
- Assertions requiring an exact native error type when CodeMode deliberately exposes only its safe runtime error.
Handwritten tests remain where they specify CodeMode behavior rather than ordinary ECMAScript String semantics.