mirror of
https://github.com/anomalyco/opencode.git
synced 2026-09-04 19:24:31 +00:00
Replace record-keyed tools and the separate namespace-description map with an OpenAI-style array of named tools and namespaces. Namespace descriptions are optional, namespaces may nest, and duplicate or dotted names are rejected.
355 lines
17 KiB
TypeScript
355 lines
17 KiB
TypeScript
/*
|
|
* Portions adapted from Test262 at revision 250f204f23a9249ff204be2baec29600faae7b75:
|
|
* - test/built-ins/Array/prototype/includes/samevaluezero.js
|
|
* - test/built-ins/Array/prototype/includes/using-fromindex.js
|
|
* - test/built-ins/Array/prototype/join/S15.4.4.5_A3.1_T1.js
|
|
* - test/built-ins/Array/prototype/join/S15.4.4.5_A3.2_T1.js
|
|
* - test/built-ins/Array/prototype/slice/S15.4.4.10_A1.2_T2.js
|
|
* - test/built-ins/Array/prototype/concat/S15.4.4.4_A1_T1.js
|
|
* - test/built-ins/Array/prototype/concat/S15.4.4.4_A1_T2.js
|
|
* - test/built-ins/Array/prototype/concat/S15.4.4.4_A1_T3.js
|
|
* - test/built-ins/Array/prototype/indexOf/fromindex-zero-conversion.js
|
|
* - test/built-ins/Array/prototype/indexOf/length-zero-returns-minus-one.js
|
|
* - test/built-ins/Array/prototype/lastIndexOf/fromindex-zero-conversion.js
|
|
* - test/built-ins/Array/prototype/lastIndexOf/length-zero-returns-minus-one.js
|
|
* - test/built-ins/Array/prototype/at/returns-item.js
|
|
* - test/built-ins/Array/prototype/at/returns-item-relative-index.js
|
|
* - test/built-ins/Array/prototype/at/returns-undefined-for-out-of-range-index.js
|
|
* - test/built-ins/Array/prototype/flat/null-undefined-elements.js
|
|
* - test/built-ins/Array/prototype/flat/positive-infinity.js
|
|
* - test/built-ins/Array/prototype/reverse/S15.4.4.8_A1_T1.js
|
|
* - test/built-ins/Array/prototype/toReversed/immutable.js
|
|
* - test/built-ins/Array/prototype/toReversed/zero-or-one-element.js
|
|
* - test/built-ins/Array/prototype/with/immutable.js
|
|
* - test/built-ins/Array/prototype/with/index-negative.js
|
|
* - test/built-ins/Array/prototype/push/S15.4.4.7_A1_T1.js
|
|
* - test/built-ins/Array/prototype/pop/S15.4.4.6_A1.1_T1.js
|
|
* - test/built-ins/Array/prototype/shift/S15.4.4.9_A1.1_T1.js
|
|
* - test/built-ins/Array/prototype/unshift/S15.4.4.13_A1_T1.js
|
|
* - test/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T1.js
|
|
* - test/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T1.js
|
|
* - test/built-ins/Array/prototype/splice/called_with_one_argument.js
|
|
* - test/built-ins/Array/prototype/toSpliced/holes-not-preserved.js
|
|
* - test/built-ins/Array/prototype/toSpliced/immutable.js
|
|
* - test/built-ins/Array/prototype/toSpliced/start-and-deleteCount-undefineds.js
|
|
* - test/built-ins/Array/prototype/toSpliced/start-and-deleteCount-missing.js
|
|
* - test/built-ins/Array/prototype/toSpliced/start-undefined-and-deleteCount-missing.js
|
|
* - test/built-ins/Array/prototype/fill/fill-values.js
|
|
* - test/built-ins/Array/prototype/fill/fill-values-custom-start-and-end.js
|
|
* - test/built-ins/Array/prototype/fill/return-this.js
|
|
* - test/built-ins/Array/prototype/copyWithin/non-negative-target-start-and-end.js
|
|
* - test/built-ins/Array/prototype/copyWithin/return-this.js
|
|
* - test/built-ins/Array/prototype/keys/iteration.js
|
|
* - test/built-ins/Array/prototype/values/iteration.js
|
|
* - test/built-ins/Array/prototype/entries/iteration.js
|
|
* - test/built-ins/Array/isArray/15.4.3.2-0-3.js
|
|
* - test/built-ins/Array/isArray/15.4.3.2-0-4.js
|
|
* - test/built-ins/Array/from/from-array.js
|
|
* - test/built-ins/Array/from/from-string.js
|
|
* - test/built-ins/Array/from/array-like-has-length-but-no-indexes-with-values.js
|
|
* - test/built-ins/Array/of/creates-a-new-array-from-arguments.js
|
|
*
|
|
* Copyright (C) 2015 André Bargull. All rights reserved.
|
|
* Copyright (C) 2015 the V8 project authors. All rights reserved.
|
|
* Copyright (C) 2016 the V8 project authors. All rights reserved.
|
|
* Copyright (C) 2018 Shilpi Jain and Michael Ficarra. All rights reserved.
|
|
* Copyright (C) 2020 Alexey Shvayka. All rights reserved.
|
|
* Copyright (C) 2020 Rick Waldron. All rights reserved.
|
|
* Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
|
* Copyright (c) 2012 Ecma International. All rights reserved.
|
|
* Copyright (c) 2014 Hank Yates. All rights reserved.
|
|
* Copyright (c) 2015 the V8 project authors. All rights reserved.
|
|
* Copyright (c) 2021 Rick Waldron. All rights reserved.
|
|
* Copyright 2009 the Sputnik authors. All rights reserved.
|
|
* Copyright 2015 Microsoft Corporation. All rights reserved.
|
|
* Copyright 2016 The V8 project authors. All rights reserved.
|
|
* Test262 portions are governed by the BSD license in LICENSE.test262.
|
|
* The toSpliced hole case omits the source test's inherited Array.prototype element because CodeMode does not expose
|
|
* prototype mutation; it retains the source test's hole-densification assertions.
|
|
*/
|
|
import { describe, expect, test } from "bun:test"
|
|
import { Effect } from "effect"
|
|
import { CodeMode } from "../src/index.js"
|
|
|
|
const value = async (code: string) => {
|
|
const result = await Effect.runPromise(CodeMode.execute({ code }))
|
|
if (!result.ok) throw new Error(`expected success, got ${result.error.kind}: ${result.error.message}`)
|
|
return result.value
|
|
}
|
|
|
|
const cases = [
|
|
{
|
|
path: "test/built-ins/Array/prototype/includes/samevaluezero.js",
|
|
code: `const input = [42, 0, 1, NaN]; return [input.includes(42), input.includes("42"), input.includes([42]), input.includes(true), input.includes(NaN), input.includes(0), input.includes(-0), input.includes(null), input.includes("")]`,
|
|
expected: [true, false, false, false, true, true, true, false, false],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/includes/using-fromindex.js",
|
|
code: `const input = ["a", "b", "c"]; return [input.includes("a", 0), input.includes("a", 1), input.includes("a", -4), input.includes("a", -3), input.includes("a", -2), input.includes("b", 0), input.includes("b", 1), input.includes("b", 2), input.includes("b", -3), input.includes("b", -2), input.includes("b", -1), input.includes("c", 0), input.includes("c", 2), input.includes("c", 3), input.includes("c", -3), input.includes("c", -1)]`,
|
|
expected: [true, false, true, true, false, true, true, false, true, true, false, true, true, false, true, true],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/join/S15.4.4.5_A3.1_T1.js",
|
|
code: `return [[0, 1, 2, 3].join("&"), [0, 1, 2, 3].join("")]`,
|
|
expected: ["0&1&2&3", "0123"],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/join/S15.4.4.5_A3.2_T1.js",
|
|
code: `return [
|
|
["", "", ""].join(""),
|
|
["&", "&", "&"].join("&"),
|
|
[true, true, true].join(),
|
|
[null, null, null].join(),
|
|
[undefined, undefined, undefined].join(),
|
|
[Infinity, Infinity, Infinity].join(),
|
|
[NaN, NaN, NaN].join(),
|
|
]`,
|
|
expected: ["", "&&&&&", "true,true,true", ",,", ",,", "Infinity,Infinity,Infinity", "NaN,NaN,NaN"],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/slice/S15.4.4.10_A1.2_T2.js",
|
|
code: `return [0, 1, 2, 3, 4].slice(-1, 5)`,
|
|
expected: [4],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/concat/S15.4.4.4_A1_T1.js",
|
|
code: `return [].concat([0, 1], [2, 3, 4])`,
|
|
expected: [0, 1, 2, 3, 4],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/concat/S15.4.4.4_A1_T2.js",
|
|
code: `const object = { value: 1 }; const result = [0].concat(object, [1, 2], -1, true, "NaN"); return [result, result[1] === object]`,
|
|
expected: [[0, { value: 1 }, 1, 2, -1, true, "NaN"], true],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/concat/S15.4.4.4_A1_T3.js",
|
|
code: `const input = [0, 1]; const result = input.concat(); return [result, result !== input]`,
|
|
expected: [[0, 1], true],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/indexOf/fromindex-zero-conversion.js",
|
|
code: `const result = [true].indexOf(true, -0); return [result, 1 / result === Infinity]`,
|
|
expected: [0, true],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/indexOf/length-zero-returns-minus-one.js",
|
|
code: `return [].indexOf(1)`,
|
|
expected: -1,
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/lastIndexOf/fromindex-zero-conversion.js",
|
|
code: `const result = [true].lastIndexOf(true, -0); return [result, 1 / result === Infinity]`,
|
|
expected: [0, true],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/lastIndexOf/length-zero-returns-minus-one.js",
|
|
code: `return [].lastIndexOf(1)`,
|
|
expected: -1,
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/at/returns-item.js",
|
|
code: `const input = [1, 2, 3, 4, undefined, 5]; return [input.at(0), input.at(1), input.at(2), input.at(3), input.at(4) === undefined, input.at(5)]`,
|
|
expected: [1, 2, 3, 4, true, 5],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/at/returns-item-relative-index.js",
|
|
code: `const input = [1, 2, 3, 4, undefined, 5]; return [input.at(0), input.at(-1), input.at(-2) === undefined, input.at(-3), input.at(-4)]`,
|
|
expected: [1, 5, true, 4, 3],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/at/returns-undefined-for-out-of-range-index.js",
|
|
code: `const input = []; return [input.at(-2) === undefined, input.at(0) === undefined, input.at(1) === undefined]`,
|
|
expected: [true, true, true],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/flat/null-undefined-elements.js",
|
|
code: `const result = [1, [null, [undefined]]].flat(2); return [result.length, result[0], result[1] === null, result[2] === undefined]`,
|
|
expected: [3, 1, true, true],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/flat/positive-infinity.js",
|
|
code: `return [1, [2, [3, [4]]]].flat(Infinity)`,
|
|
expected: [1, 2, 3, 4],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/reverse/S15.4.4.8_A1_T1.js",
|
|
code: `const empty = []; const one = [1]; const input = [1, 2]; const emptyResult = empty.reverse(); const oneResult = one.reverse(); const result = input.reverse(); return [emptyResult === empty, oneResult === one, result === input, input]`,
|
|
expected: [true, true, true, [2, 1]],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/toReversed/immutable.js",
|
|
code: `const input = [0, 1, 2]; const result = input.toReversed(); return [input, result !== input]`,
|
|
expected: [[0, 1, 2], true],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/toReversed/zero-or-one-element.js",
|
|
code: `const zero = []; const one = [1]; const zeroResult = zero.toReversed(); const oneResult = one.toReversed(); return [zeroResult, oneResult, zeroResult !== zero, oneResult !== one]`,
|
|
expected: [[], [1], true, true],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/with/immutable.js",
|
|
code: `const input = [0, 1, 2]; const result = input.with(1, 3); return [input, result !== input, input.with(1, 1) !== input]`,
|
|
expected: [[0, 1, 2], true, true],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/with/index-negative.js",
|
|
code: `const input = [0, 1, 2]; return [input.with(-1, 4), input.with(-3, 4)]`,
|
|
expected: [
|
|
[0, 1, 4],
|
|
[4, 1, 2],
|
|
],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/push/S15.4.4.7_A1_T1.js",
|
|
code: `const input = []; return [input.push(1), input.push(), input.push(-1), input]`,
|
|
expected: [1, 1, 2, [1, -1]],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/pop/S15.4.4.6_A1.1_T1.js",
|
|
code: `const input = []; return [input.pop() === undefined, input.length]`,
|
|
expected: [true, 0],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/shift/S15.4.4.9_A1.1_T1.js",
|
|
code: `const input = []; return [input.shift() === undefined, input.length]`,
|
|
expected: [true, 0],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/unshift/S15.4.4.13_A1_T1.js",
|
|
code: `const input = []; return [input.unshift(1), input[0], input.unshift(), input.unshift(-1), input]`,
|
|
expected: [1, 1, 1, 2, [-1, 1]],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/splice/S15.4.4.12_A1.1_T1.js",
|
|
code: `const input = [0, 1, 2, 3]; const removed = input.splice(0, 3); return [input, removed]`,
|
|
expected: [[3], [0, 1, 2]],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/splice/S15.4.4.12_A1.2_T1.js",
|
|
code: `const input = [0, 1]; const removed = input.splice(-2, -1); return [input, removed]`,
|
|
expected: [[0, 1], []],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/splice/called_with_one_argument.js",
|
|
code: `const input = ["first", "second", "third"]; const removed = input.splice(1); return [input, removed]`,
|
|
expected: [["first"], ["second", "third"]],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/toSpliced/immutable.js",
|
|
code: `const input = [2, 0, 1]; const inserted = input.toSpliced(0, 0, -1); const replaced = input.toSpliced(0, 1, -1); return [input, inserted, replaced, inserted !== input, replaced !== input]`,
|
|
expected: [[2, 0, 1], [-1, 2, 0, 1], [-1, 0, 1], true, true],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/toSpliced/start-and-deleteCount-missing.js",
|
|
code: `const input = ["first", "second", "third"]; const result = input.toSpliced(); return [result, result !== input]`,
|
|
expected: [["first", "second", "third"], true],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/toSpliced/start-undefined-and-deleteCount-missing.js",
|
|
code: `return ["first", "second", "third"].toSpliced(undefined)`,
|
|
expected: [],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/toSpliced/start-and-deleteCount-undefineds.js",
|
|
code: `const input = ["first", "second", "third"]; const result = input.toSpliced(undefined, undefined); return [result, result !== input]`,
|
|
expected: [["first", "second", "third"], true],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/toSpliced/holes-not-preserved.js",
|
|
code: `const input = [0, , 2, , 4]; const result = input.toSpliced(0, 0, -1); return [result, 2 in result, 4 in result]`,
|
|
expected: [[-1, 0, null, 2, null, 4], true, true],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/fill/fill-values-custom-start-and-end.js",
|
|
code: `const input = [0, 0, 0, 0, 0]; input.fill(8, -3, 4); const sparse = []; sparse[4] = 0; sparse.fill(8, 1, 3); return [[0, 0, 0].fill(8, 1, 2), input, [0, 0, 0, 0, 0].fill(8, -2, -1), [0, 0, 0, 0, 0].fill(8, -1, -3), [0 in sparse, sparse[1], sparse[2], 3 in sparse, sparse[4]]]`,
|
|
expected: [
|
|
[0, 8, 0],
|
|
[0, 0, 8, 8, 0],
|
|
[0, 0, 0, 8, 0],
|
|
[0, 0, 0, 0, 0],
|
|
[false, 8, 8, false, 0],
|
|
],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/fill/return-this.js",
|
|
code: `const input = []; return input.fill(1) === input`,
|
|
expected: true,
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/fill/fill-values.js",
|
|
code: `const omitted = [0, 0].fill(); return [[].fill(8), omitted.map((value) => value === undefined), [0, 0, 0].fill(8)]`,
|
|
expected: [[], [true, true], [8, 8, 8]],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/copyWithin/non-negative-target-start-and-end.js",
|
|
code: `return [[0, 1, 2, 3].copyWithin(0, 0, 0), [0, 1, 2, 3].copyWithin(0, 0, 2), [0, 1, 2, 3].copyWithin(0, 1, 2), [0, 1, 2, 3].copyWithin(1, 0, 2), [0, 1, 2, 3, 4, 5].copyWithin(1, 3, 5)]`,
|
|
expected: [
|
|
[0, 1, 2, 3],
|
|
[0, 1, 2, 3],
|
|
[1, 1, 2, 3],
|
|
[0, 0, 1, 3],
|
|
[0, 3, 4, 3, 4, 5],
|
|
],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/copyWithin/return-this.js",
|
|
code: `const input = [0, 1, 2, 3]; const result = input.copyWithin(1, 0, 2); return [input, result === input]`,
|
|
expected: [[0, 0, 1, 3], true],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/keys/iteration.js",
|
|
code: `return ["a", "b", "c"].keys()`,
|
|
expected: [0, 1, 2],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/values/iteration.js",
|
|
code: `return ["a", "b", "c"].values()`,
|
|
expected: ["a", "b", "c"],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/prototype/entries/iteration.js",
|
|
code: `return ["a", "b"].entries()`,
|
|
expected: [
|
|
[0, "a"],
|
|
[1, "b"],
|
|
],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/isArray/15.4.3.2-0-3.js",
|
|
code: `return [Array.isArray([]), Array.isArray([1]), Array.isArray(Array.of(1))]`,
|
|
expected: [true, true, true],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/isArray/15.4.3.2-0-4.js",
|
|
code: `return [Array.isArray(42), Array.isArray({}), Array.isArray(null), Array.isArray("array")]`,
|
|
expected: [false, false, false, false],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/from/from-array.js",
|
|
code: `const input = [0, "foo", undefined, Infinity]; const result = Array.from(input); return [result.length, result[0], result[1], result[2] === undefined, result[3] === Infinity, result !== input, result instanceof Array]`,
|
|
expected: [4, 0, "foo", true, true, true, true],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/from/from-string.js",
|
|
code: `return Array.from("Test")`,
|
|
expected: ["T", "e", "s", "t"],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/from/array-like-has-length-but-no-indexes-with-values.js",
|
|
code: `const result = Array.from({ length: 5 }); const mapped = result.map(() => 1); return [result.length, result.map((value) => value === undefined), mapped.length, mapped]`,
|
|
expected: [5, [true, true, true, true, true], 5, [1, 1, 1, 1, 1]],
|
|
},
|
|
{
|
|
path: "test/built-ins/Array/of/creates-a-new-array-from-arguments.js",
|
|
code: `const mixed = Array.of(undefined, false, null, undefined); return [Array.of("Mike", "Rick", "Leo"), mixed.length, mixed[0] === undefined, mixed[1], mixed[2], mixed[3] === undefined, Array.of()]`,
|
|
expected: [["Mike", "Rick", "Leo"], 4, true, false, null, true, []],
|
|
},
|
|
] as const
|
|
|
|
describe("Test262 Array core adaptations", () => {
|
|
for (const item of cases) {
|
|
test(item.path, async () => {
|
|
expect(await value(item.code)).toEqual(item.expected)
|
|
})
|
|
}
|
|
})
|