mirror of
https://gitee.com/zhangsken/opencode.git
synced 2026-10-16 10:30:01 +08:00
658 lines
54 KiB
Markdown
658 lines
54 KiB
Markdown
# CodeMode Interpreter Support
|
|
|
|
This is the checkable support matrix for CodeMode's confined JavaScript interpreter. It tracks the language and
|
|
standard-library surface that programs can use today, plus concrete gaps that may be implemented later.
|
|
|
|
- `[x]` means the feature is implemented at the scope described here.
|
|
- `[ ]` means a concrete compatibility gap remains.
|
|
- Checked items do not promise complete ECMAScript edge-case parity; known differences are stated explicitly.
|
|
- Intentional boundaries are not listed as compatibility work.
|
|
|
|
When behavior changes, update this file and the tests in the same change. The implementation and tests remain the
|
|
ultimate source of truth. Upstream test262 files run verbatim from `test/test262`; a failing file is listed in
|
|
`test/test262/skipped.txt` and its gap is an unchecked item here (see `test/test262/README.md`).
|
|
|
|
## Source and execution model
|
|
|
|
- [x] JavaScript parsed with the latest syntax accepted by Acorn, then restricted by the interpreter allowlist.
|
|
TypeScript-only syntax is rejected rather than stripped before execution.
|
|
- [x] Top-level `await` and `return` through the program's implicit async-function scope.
|
|
- [x] Explicit `return`, final top-level expression as a REPL-style result, and `null` when no value is produced.
|
|
- [x] The host boundary is `JSON.stringify` plus a short table. The program result and tool arguments cross as
|
|
what `JSON.stringify` would serialize: `toJSON` is honored, functions and `undefined` properties vanish,
|
|
`undefined` array elements and non-finite numbers become `null`, a cyclic value throws the same `TypeError`,
|
|
and Map, RegExp, and generators serialize as `{}`. A bare `undefined` result is `null`.
|
|
Tool results come back the way `JSON.parse(JSON.stringify(result))` would. The table, where a value cannot
|
|
be JSON but what the program meant is clear: a promise is awaited (a rejection fails the program), a Set
|
|
crosses as an array, a URLSearchParams as its query string, an Error as `{ name, message, ...own enumerable }`, a
|
|
Uint8Array is rejected with a hint to encode as text, and own `__proto__` keys are dropped so merging tool
|
|
inputs or results cannot replace a prototype. In-program `JSON.stringify` keeps JS behavior except for the
|
|
Error form and a promise, which is a `TypeError` with an await hint rather than a silent `{}`.
|
|
- [x] Live Date, RegExp, Map, Set, URL, URLSearchParams, Headers, and Uint8Array values inside CodeMode.
|
|
- [x] Tool calls through the host-provided `tools` tree only.
|
|
- [x] The global `search(...)` built-in: synchronous tool discovery that counts as an admitted tool call and is
|
|
shadowable by program declarations like other globals.
|
|
- [x] Cooperative timeout, an optional total tool-call limit, output bounding, and unrestricted tool-call concurrency.
|
|
- [x] The timeout fires between interpreter steps, so one built-in is bounded in what it may build: strings up to
|
|
2^24 characters (`repeat`, `pad*`, `concat`, `join`, `+`, template literals, `JSON.stringify`), arrays up to
|
|
10,000,000 elements (`Array(n)`, `length =`, `Array.from`, `split`, `matchAll`, `concat`, `flat`; below the JS
|
|
maximum of 2^32 - 1), and 10,000 pending promises at once. Exceeding one throws a `RangeError`. A single regular
|
|
expression match can still run long on a pathological pattern; the host regex engine has no interrupt hook.
|
|
- [x] A trailing comma after a rest parameter is a syntax error, with or without `"use strict"`.
|
|
- [x] A program that begins with `"use strict"` rejects `yield` as an identifier and duplicate parameter names at
|
|
parse time. Without it, `yield` is an ordinary binding.
|
|
- [x] Duplicate parameter names in non-strict code bind the last parameter, as in JS (`function f(a, a)` called
|
|
with `(1, 2)` sees `a === 2`).
|
|
|
|
## Values and literals
|
|
|
|
- [x] `null`, `undefined`, booleans, finite and non-finite numbers, and strings.
|
|
- [x] Array literals, including holes and spread from arrays, strings, Maps, Sets, URLSearchParams, Headers, custom
|
|
synchronous iterators, and synchronous generators.
|
|
- [x] Object literals with shorthand, computed string/number keys, and spread following ToObject: data objects and
|
|
arrays copy own enumerable keys, strings copy index keys, and other values contribute nothing.
|
|
- [x] Template literals with interpolation.
|
|
- [x] Tagged templates: a tag applied to a template literal is called as `tag(strings, ...values)`, with the tag read
|
|
like a callee so a member tag keeps its receiver. `strings` is an array of the cooked text with a read-only `raw`
|
|
array of the source text; an invalid escape such as `\unicode` cooks to `undefined`. One template object per
|
|
site, as in JS, but it is not frozen: `strings[0] = "x"` succeeds here where JS throws.
|
|
- [x] Regular-expression literals.
|
|
- [x] `NaN` and `Infinity` globals.
|
|
- [ ] BigInt literals and in-interpreter BigInt arithmetic; BigInt remains invalid at JSON-like host boundaries.
|
|
- [ ] Arbitrary Symbol primitive values and symbol-keyed properties. The confined `Symbol.iterator` and
|
|
`Symbol.asyncIterator` keys are available only for the iterator protocols.
|
|
- [ ] Getter and setter definitions in object literals.
|
|
|
|
## Bindings and destructuring
|
|
|
|
- [x] `const`, `let`, and `var` declarations.
|
|
- [x] Object and array destructuring in declarations, parameters, assignment expressions, and `for...of` bindings.
|
|
- [x] Nested patterns, defaults, elisions, and rest elements.
|
|
- [x] Assignment to identifiers, plain-object fields, non-negative integer array indexes, and writable URL
|
|
fields.
|
|
- [x] Direct function declarations are hoisted in program and block statement lists.
|
|
- [x] Parameter defaults observe a temporal dead zone for later parameters.
|
|
- [x] `var` is function-scoped and hoisted: names declared anywhere in a function or program body, including loop
|
|
heads, blocks, `switch` cases, and `try`/`catch`, read as `undefined` before their statement runs; redeclaration
|
|
assigns the one binding; a same-named parameter keeps its argument; closures in parameter defaults see outer
|
|
names rather than body `var`s.
|
|
- [x] Predeclare `let` and `const` bindings in every lexical scope, including program/block bodies, switch bodies, and
|
|
loop headers, so reads before initialization and self- or cross-referential initializers observe the JavaScript
|
|
temporal dead zone.
|
|
- [x] Function declarations are hoisted across all cases of a `switch`, like any other statement list.
|
|
- [x] Computed object destructuring keys such as `const { [field]: value } = record`.
|
|
- [x] Object destructuring from arrays, such as `const { length } = values`.
|
|
- [x] Array binding and assignment destructuring from strings, Maps, Sets, URLSearchParams, custom synchronous
|
|
iterators, and synchronous generators, including stepwise elisions/rest and `IteratorClose` on early completion
|
|
or binding/default failure.
|
|
- [x] Object destructuring from primitives follows ToObject: `const { length } = "abc"` is `3`, `const { toFixed } = 1`
|
|
finds the built-in, `const {} = 1` is a no-op, and a rest element copies a string's indexes (`{ 1: "y", 2: "z" }`).
|
|
Only `null` and `undefined` sources throw (`Cannot destructure null as it is null.`).
|
|
- [x] Destructuring reads through the prototype chain like member access: `const { constructor } = error` and
|
|
`const { slice } = values` find the inherited built-in.
|
|
- [x] Any assignment target as a `for...in` head, like `for...of`: `for (x.y in obj)`, `for (a[i++] in obj)`, and
|
|
destructuring patterns.
|
|
|
|
## Statements and control flow
|
|
|
|
- [x] Blocks and empty statements.
|
|
- [x] `if`/`else` and conditional expressions.
|
|
- [x] `switch`, including default clauses and fallthrough.
|
|
- [x] `for`, `while`, and `do...while`.
|
|
- [x] `for...of` over arrays, strings, Maps, Sets, URLSearchParams, Headers, Uint8Arrays, built-in iterators, custom
|
|
synchronous iterators, and confined synchronous generators. Abrupt completion invokes the iterator's optional `return()`.
|
|
- [x] `for...in` over own keys of plain objects, arrays, strings, and tool references. `null`, `undefined`, and other
|
|
non-objects iterate nothing. An un-awaited promise throws rather than iterating.
|
|
- [ ] `for...in` over inherited enumerable keys (`Object.create(proto)`), and skipping keys deleted during the loop.
|
|
- [x] Unlabeled `break` and `continue`.
|
|
- [x] `try`, `catch`, optional catch bindings, and `finally`.
|
|
- [x] `throw` with arbitrary values.
|
|
- [x] Labeled statements, labeled `break`, and labeled `continue`.
|
|
- [x] `for await...of` over the supported synchronous collections and custom iterator objects using
|
|
`Symbol.asyncIterator` or the `Symbol.iterator` fallback. Each iterator step is sequential, yielded promises and
|
|
plain values from synchronous collections and sync iterators are awaited before binding, and abrupt loop
|
|
completion invokes the iterator's optional `return()`. Custom async iterators control their yielded values, as in
|
|
JavaScript; only their `next()` results are awaited. Confined sync and async generators are iterable here.
|
|
|
|
## Functions and callbacks
|
|
|
|
- [x] Function declarations, function expressions, and arrow functions.
|
|
- [x] Synchronous and `async` functions. A line break between `function` and the name is allowed, as in JavaScript;
|
|
a line break between `async` and `function` is not an async function.
|
|
- [x] Closures, recursion, default parameters, rest parameters, and destructured parameters.
|
|
- [x] A call depth limit of 10000: deeper nesting throws a catchable `RangeError: Maximum call stack size exceeded`
|
|
at the overflowing call instead of running until the timeout. Callbacks invoked by built-ins count below the
|
|
call that invoked the built-in, and a resumed `await` starts from depth 0 as in JS, so long async chains such
|
|
as recursive pagination are unaffected.
|
|
- [x] Expression and block function bodies.
|
|
- [x] User callbacks for the supported Array, Map, Set, URLSearchParams, sort, string-replacement, and `Array.from`
|
|
mapper APIs, with one shared acceptance rule everywhere including promise reactions.
|
|
- [x] `Boolean`, `Number`, `String`, `parseInt`, `parseFloat`, `isFinite`, `isNaN`, and URI helpers as callbacks.
|
|
- [x] Built-in method references as callbacks, such as `values.map(Math.abs)`, `records.map(JSON.stringify)`,
|
|
`items.forEach(console.log)`, and `Promise.resolve(-1).then(Math.abs)`. Extra callback arguments a built-in
|
|
does not consume are ignored, like JS, and consumed arguments coerce, like JS (`"3.7".replace(/\d\.\d/,
|
|
Math.floor)` is `"3"`). A detached method loses its receiver, as in JS: `values.filter("abc".includes)` is a `TypeError`
|
|
because `includes` is called without a string `this`.
|
|
- [x] Constructors work as callbacks with JS call semantics: `Error` types construct (`messages.map(Error)`),
|
|
and new-requiring constructors (`Map`, `Set`, `URL`, `URLSearchParams`, `Headers`, `Promise`) throw a `TypeError`,
|
|
like JS.
|
|
- [x] Tool references and detached `Promise` statics are rejected as callbacks with a hint to wrap them in an
|
|
arrow function.
|
|
- [x] Promise-returning string replacers are coerced synchronously to `"[object Promise]"`, like JavaScript; they are
|
|
not automatically awaited.
|
|
- [x] `this` in non-arrow functions is the call's receiver: `obj.m()` and `obj["m"]()` see `obj`, a bare or detached
|
|
call (`f()`, `const m = obj.m; m()`, `(0, obj.m)()`) sees `undefined`, as in strict JS. Arrows read the enclosing
|
|
function's `this`. Program code has no receiver, so top-level `this` is `undefined`, as in a module.
|
|
- [x] `arguments` in non-arrow functions: an unmapped ordinary object with the call's arguments as indexed
|
|
properties and a hidden `length`; iterable, so spread, `for...of`, and `Array.from` work. It is not an Array
|
|
(`JSON.stringify` gives `{"0":1}`, `String` gives `[object Arguments]`). A parameter named `arguments` shadows
|
|
it; arrows read the enclosing function's; it is only created for functions whose body mentions it. `callee`
|
|
and `caller` are absent rather than poisoned.
|
|
- [ ] Array methods on `arguments` and other array-likes (`Array.prototype.slice.call(arguments, 1)`); use
|
|
`[...arguments]` or a rest parameter meanwhile.
|
|
- [x] `Function.prototype.call`, `apply`, and `bind` on program functions and built-ins:
|
|
`Array.prototype.push.call(arr, 1)`, `Math.max.apply(null, values)`, `fn.bind(obj, first)`. `apply` accepts an
|
|
array, an array-like object (its `length` clamped and capped like `Array.from`), or `null`/`undefined`. A
|
|
bound function is named `bound f`, has its remaining `length`, and is not constructible.
|
|
- [x] `JSON.parse` revivers and `JSON.stringify` function replacers see the holder object as `this`.
|
|
- [x] The optional `thisArg` of the Array, Uint8Array, and `Array.from` callback methods and of Map, Set,
|
|
URLSearchParams, and Headers `forEach` is the callback's `this`: `[1, 2].forEach(function () { this.n++ }, c)`
|
|
increments `c.n` twice. Arrows ignore it, as in JS; `reduce`/`reduceRight` take an initial value instead.
|
|
- [ ] User-defined constructor calls.
|
|
- [ ] Classes and private fields.
|
|
- [x] Functions are objects: they hold own properties (`fn.count = 1`), enumerate them, and expose read-only `name`
|
|
and `length`. Names follow JavaScript's NamedEvaluation: declarations, named expressions, bindings,
|
|
assignments, object literal keys, and destructuring or parameter defaults.
|
|
- [x] Built-in functions are objects too, with `name` and `length` (`Math.max.length === 2`,
|
|
`Array.prototype.push.name === "push"`).
|
|
- [x] A named function expression's name is bound read-only inside its own body; assigning to it throws a
|
|
`TypeError`, as in strict mode.
|
|
- [x] Redeclaring a function in the same scope, or alongside a `var`, is allowed: the last declaration wins.
|
|
- [x] Generator functions have their own `prototype` (inheriting the shared generator prototype), so
|
|
`g() instanceof g` holds. Plain functions have none, since they cannot construct.
|
|
- [ ] `GeneratorFunction.prototype`: every function, generator or not, inherits directly from `Function.prototype`,
|
|
and a generator whose `prototype` was replaced by a non-object still creates from the shared generator prototype.
|
|
- [x] Generator and async generator functions bind parameters (defaults, destructuring) at the call and defer only the
|
|
body to the first `next()`, so a bad argument throws synchronously from the call site, as in JS.
|
|
- [x] Synchronous and async generator declarations/expressions, `yield`, and `yield*`, including lazy bodies,
|
|
`next(value)`, `return(value)`, `throw(value)`, exhaustion, promise adoption, async request ordering,
|
|
`try`/`catch`/`finally`, and sync/async iterator symbols. Async `yield*` awaits values while adapting a sync
|
|
iterator but preserves values supplied by a manually implemented async iterator. Generator values are opaque
|
|
runtime references.
|
|
- [x] Synchronous generators and custom synchronous iterators are consumed stepwise by array/argument spread, array
|
|
destructuring, `Array.from`, Map/Set/URLSearchParams construction, `Object.fromEntries`, Object/Map `groupBy`,
|
|
Promise combinators, `AggregateError`, and `Math.sumPrecise`. Mapper/grouping callbacks interleave with iterator
|
|
steps; synchronous consumers preserve yielded promise objects rather than awaiting them. Async generators are
|
|
rejected by every synchronous consumer.
|
|
- [x] Synchronous iterator acquisition and result validation follow `IteratorClose` boundaries: consumer errors and
|
|
intentional early stops invoke `return()`, acquisition/`next()` failures do not, and an original consumer error
|
|
wins over a cleanup failure. A generator's `return()` is an intentional stop, so a `return()` that throws or
|
|
yields a non-object surfaces from it as a `TypeError`. Async iterator consumption remains limited to `for await...of` and async `yield*`.
|
|
- [x] Portable generator protocol coverage is adapted from pinned Test262 cases for suspended-start, suspended-yield,
|
|
and completed states; sync and async `next`/`return`/`throw`; finally yields and completion overrides; rejected
|
|
yielded promises; mixed async request queues; sync and async `yield*` forwarding; malformed methods/results;
|
|
and declaration, expression, and object-method forms with closure and parameter behavior. The adapted suite
|
|
deliberately skips Test262 variants whose observation mechanism requires unsupported getter definitions,
|
|
proxies, prototype inspection or mutation, classes, or arbitrary symbols. It also skips tests
|
|
asserting exact promise reaction-turn counts beyond the observable ordering guarantee documented below. These
|
|
are interpreter-surface boundaries, not claims that the corresponding full Test262 families pass unchanged.
|
|
|
|
## Expressions and operators
|
|
|
|
- [x] Property access with dot or computed bracket syntax.
|
|
- [x] Optional property access and optional calls.
|
|
- [x] Function/tool calls and spread arguments.
|
|
- [x] Sequence expressions (the comma operator).
|
|
- [x] `await` for CodeMode promises and callable thenables; a plain value passes through unchanged, though every
|
|
`await` still defers its continuation one reaction turn.
|
|
- [x] `new` for Array, Object, Error types, Date, RegExp, Map, Set, URL, URLSearchParams, Headers, and Promise. `new`
|
|
on any other value throws a catchable `TypeError` naming the callee: other built-in functions such as `Number`
|
|
say `new` is unsupported and point at the plain call, user-defined functions report the constructor gap below,
|
|
and non-callable values are not constructors. Error constructors take the ES2022 options object, so
|
|
`new Error(message, { cause })` installs a non-enumerable `cause` when the option is present. `Error.isError`
|
|
is true for every Error value.
|
|
- [x] Arithmetic operators: `+`, `-`, `*`, `/`, `%`, and `**`.
|
|
- [x] Equality and ordering: `==`, `!=`, `===`, `!==`, `<`, `<=`, `>`, and `>=`.
|
|
- [x] Bitwise operators: `&`, `|`, `^`, `~`, `<<`, `>>`, and `>>>`.
|
|
- [x] Logical operators: `&&`, `||`, `??`, and `!`, with short-circuiting.
|
|
- [x] Unary `+`, unary `-`, `void`, `typeof`, `instanceof` (through the constructor's `prototype`, so
|
|
`[] instanceof Object` holds), and `in` across the prototype chain.
|
|
- [x] Prefix and postfix `++` and `--`.
|
|
- [x] Plain, arithmetic, bitwise, and logical assignment operators.
|
|
- [x] Property deletion on plain data objects and arrays, including computed and optional forms; deleting an array index
|
|
creates a hole without changing its length. Deleting a non-configurable property (`length`) or
|
|
assigning a read-only one (`Math.PI`, `fn.name`) throws a `TypeError`, as in strict mode. `delete` of a
|
|
non-reference (`delete 0`, `delete f()`) evaluates the operand and is `true`; `delete x` on a variable throws.
|
|
- [x] Coercion helpers and template interpolation accept functions and namespaces: `String(fn)` and `${fn}` give
|
|
`"[object Function]"` rather than the source text, `isNaN(fn)` is `true`.
|
|
- [x] `==` and `!=` follow IsLooselyEqual: objects (including functions and tool references) compare by identity, a
|
|
nullish operand never coerces the other side, and a data object facing a primitive converts through its own
|
|
`valueOf`/`toString` (default hint) (`fn == null` is `false`, `fn == fn` is `true`, `[1] == 1` and `[1, 2] == "1,2"` are `true`).
|
|
`switch` matches cases with `===`, so `switch (fn) { case fn: }` selects, and `Object.is` compares any two
|
|
values. Operators inspect only their direct operands, so `rows == null` on a large array costs the same as
|
|
`rows === null`, and an object merely holding a function inside (`[fn] + ""`, `-[fn]`) coerces like any other
|
|
data object (`"[object Function]"`, `NaN`).
|
|
- [ ] Coercing a function, promise, generator, or tool reference itself: `fn + ""`, `-fn`, `fn++`, and `fn == 1`
|
|
throw `TypeError: Binary operators require data values.` (or the unary/update form) where JavaScript would use
|
|
the source text or `NaN`.
|
|
- [x] ToPrimitive on program objects: `+ - * / % **`, the relational and bitwise operators, unary `+ - ~`, `++`/`--`,
|
|
compound assignment, `${x}`, `Number`/`String`/`isNaN`/`isFinite`, `parseInt`/`parseFloat` (text and radix),
|
|
`Math.*` arguments, `Error(message)`, and `Array.prototype.join`/`toString` elements call the object's own
|
|
`valueOf`/`toString` in spec order (both operands left then right, `+` with the default hint) and surface their
|
|
throws: `{ valueOf() { return 7 } } * 2` is `14`, `` `${{ toString() { return "x" } }}` `` is `"x"`, and
|
|
`[1, 2]` with `arr.toString = () => "x"` makes `arr + ""` `"x"`. Dates keep their `Symbol.toPrimitive`
|
|
behavior (`date + 1` concatenates, `date - date` subtracts).
|
|
- [x] String and Number method arguments convert through ToPrimitive in spec order, receiver first: search strings,
|
|
separators, fills, and replacements with the string hint, indexes, counts, digits, and radixes with the number
|
|
hint (`"abc".indexOf({ toString() { return "b" } })` is `1`, `(255).toString({ valueOf() { return 16 } })` is
|
|
`"ff"`, `String.prototype.trim.call({ toString() { return " a " } })` is `"a"`). Only consumed positions
|
|
convert; a RegExp pattern is used as is, and `includes`/`startsWith`/`endsWith` reject one before converting.
|
|
- [ ] ToPrimitive elsewhere: `Error.prototype.toString` on an object `message` and numeric arguments of the Array and
|
|
Uint8Array methods (`at`, `indexOf` start, `slice`) still use the built-in form (`NaN`, `"[object Object]"`) and
|
|
ignore own methods.
|
|
- [x] Property keys follow ToPropertyKey: `x[null]` and `x[true]` become string keys, and a data object key
|
|
converts through its own `toString`/`valueOf` (string hint) exactly once per access, in reads, writes,
|
|
compound assignment, `++`, `delete`, `in`, object literals, and destructuring:
|
|
`o[{ toString() { return "id" } }] += 1` updates `o.id`. A nullish base throws before the key converts, as
|
|
in JS. Opaque values (functions, promises, tool references) keep their built-in string form.
|
|
|
|
## Promises and tools
|
|
|
|
- [x] Tool calls start eagerly and return supervised, run-once CodeMode promises.
|
|
- [x] Direct `await`, repeated awaits, and recursive thenable assimilation when a promise or thenable is returned from
|
|
a function/program.
|
|
- [x] `Promise.resolve` and `Promise.reject`.
|
|
- [x] `Promise.all`, `Promise.allSettled`, `Promise.race`, and `Promise.any` over finite collections, custom synchronous
|
|
iterators, and synchronous generators containing promises and plain values.
|
|
- [x] `Promise.all` preserves result order and rejects on the first observed failure without cancelling siblings.
|
|
- [x] `Promise.allSettled` returns plain fulfilled/rejected outcome records.
|
|
- [x] `Promise.race` settles from the first result without cancelling losers at settlement time.
|
|
- [x] Real promise values from `Promise.all`, `Promise.allSettled`, and `Promise.race`; separately constructed
|
|
combinator batches overlap as in normal JavaScript.
|
|
- [x] Promise chaining with `.then`, `.catch`, and `.finally`: handlers run deferred in attach order, returned
|
|
promises are adopted, handler throws reject the derived promise, `.finally` preserves the original settlement
|
|
unless its cleanup fails, and direct self-resolution rejects with a `TypeError`.
|
|
- [x] Every `await` (including of plain values and already-settled promises) defers its continuation one reaction
|
|
turn, so concurrent async functions interleave at await points as in JavaScript.
|
|
- [x] Combinators settle one reaction turn after their deciding member (V8-observable ordering): reactions already
|
|
attached to members run first, and an aggregate cannot beat a plain value settling in the same turn into a
|
|
`Promise.race`. Exact microtask-count parity beyond this observable ordering is not a documented guarantee.
|
|
- [x] All still-pending work (race losers, fail-fast `Promise.all` stragglers, and un-awaited calls alike) is
|
|
interrupted when the program returns; rejections that settled un-awaited become `Success.warnings`
|
|
diagnostics. A combinator abandoned inside its final settlement turn counts as pending and is interrupted
|
|
without a warning.
|
|
- [x] `try`/`catch` can handle awaited tool and promise failures.
|
|
- [x] `Promise.any`: first fulfillment wins; all-rejected rejects with an `AggregateError` whose `errors` array holds
|
|
the catch-normalized reasons in input order, and empty input rejects with an empty `AggregateError`.
|
|
- [x] `new Promise((resolve, reject) => ...)`: the executor runs synchronously and receives first-class resolve/reject
|
|
callables that settle the promise exactly once (they may escape the executor and settle later); an executor
|
|
throw rejects unless the promise already settled, resolving with a promise or callable thenable adopts it, and
|
|
resolving with the promise itself rejects with a `TypeError`. Resolver callables work anywhere callbacks are
|
|
accepted, including `.then`/`.catch` handlers and collection callbacks, and vanish at the data boundary like
|
|
any function.
|
|
- [x] `Promise.withResolvers()`: the same promise and resolver callables as the constructor, as a `{ promise, resolve,
|
|
reject }` object.
|
|
- [x] `Promise.try(fn, ...args)`: calls `fn` synchronously; a throw rejects, a return fulfils, and a returned promise or
|
|
thenable is adopted.
|
|
- [x] Recursive assimilation of objects with an own callable `then` field across `Promise.resolve`, combinators,
|
|
constructors, reactions, `finally`, `await`, and async returns. Thenable methods run deferred, receive
|
|
first-call-wins resolve/reject functions, and ignore throws after settlement. Inherited/accessor `then` fields
|
|
remain outside the supported object model.
|
|
- [x] Dotted tool names are canonicalized into namespace paths; a path can be both callable and a namespace, and the
|
|
last tool supplied for a canonical path wins.
|
|
- [x] Tool path segments may be named `constructor`, `prototype`, or `__proto__` because paths use inert Map keys.
|
|
- [x] Outbound tool arguments are what `JSON.stringify` would serialize (see the boundary rule above). Tools never
|
|
receive `undefined` inside their input object, though a bare `tools.t(undefined)` argument still reaches schema
|
|
decoding as `undefined`.
|
|
- [ ] Tokenize and case-fold non-ASCII tool paths, descriptions, and queries for tool search.
|
|
|
|
## Objects and properties
|
|
|
|
- [x] Own-field reads and writes on plain data objects.
|
|
- [x] `new` dispatches on the evaluated constructor value, so aliases (`const D = Date; new D()`), constructors held in
|
|
objects, and constructors passed as arguments work, while a shadowed name (`const Date = 5; new Date()`) does
|
|
not construct.
|
|
- [x] `Object()` and `new Object()` return `{}` for nullish arguments and pass objects through unchanged;
|
|
primitive wrapper objects (`Object(1)`) are rejected explicitly.
|
|
- [x] Computed property names and object spread. Any value works as a key (ToPropertyKey): strings, numbers, and the
|
|
two confined symbols as themselves, data objects through their own `toString` (`o[[1, 2]]` is `o["1,2"]`), and
|
|
everything else as its string form (`o[null]` is `o["null"]`), in reads, writes, literals, `in`, and
|
|
destructuring.
|
|
- [x] `Object.keys`, `Object.values`, `Object.entries`, `Object.hasOwn`, `Object.assign`, and `Object.fromEntries`, with
|
|
synchronous iterator support for `fromEntries`. Sources follow ToObject: strings enumerate by index, other
|
|
primitives and wrappers contribute nothing, and `null`/`undefined` throw. `Object.assign` accepts array
|
|
targets for index keys only; a primitive target is a `TypeError` rather than a boxed object.
|
|
- [x] `Object.keys` over arrays and tool references.
|
|
- [x] Object identity is preserved by in-CodeMode Object helpers.
|
|
- [x] Every value has a real prototype chain built fresh for each run: `Object.prototype`, `Array.prototype`,
|
|
`String.prototype`, `Error.prototype` → `TypeError.prototype`, and so on hold the built-in methods as
|
|
non-enumerable properties, and each constructor's `prototype` points at it (`[].constructor === Array`,
|
|
`Object.getPrototypeOf([]) === Array.prototype`). Programs may read and even overwrite these prototypes; the
|
|
change is confined to that run. `__proto__` is an ordinary own data key, so `o.__proto__ = x` never changes the
|
|
chain, and `Object.groupBy` results have no prototype at all, as in JS.
|
|
- [x] `Object.getPrototypeOf`: the prototype of an object, or the built-in prototype for a string, number, or boolean
|
|
(`Object.getPrototypeOf("a") === String.prototype`); `null`, `undefined`, and the two confined symbols throw a
|
|
`TypeError`.
|
|
- [x] `Object.create(proto)` with an object or `null` prototype; any other prototype is a `TypeError`
|
|
(`Object prototype may only be an Object or null`). Inherited reads, `in`, `hasOwnProperty`, and own-only
|
|
`Object.keys` follow the chain as in JS, but `for...in` still enumerates own keys only. A second `properties`
|
|
argument other than `undefined` throws a `TypeError`: property descriptors are not supported (there is no
|
|
`Object.defineProperty` either).
|
|
- [x] `Object.freeze`, `Object.seal`, and `Object.preventExtensions`, with `isFrozen`, `isSealed`, and `isExtensible`.
|
|
Each returns its argument and passes primitives through (`Object.freeze(1) === 1`, `Object.isFrozen(1)`).
|
|
Programs run as strict code, so violations throw `TypeError`: `Cannot assign to read only property 'a'`,
|
|
`Cannot add property b, object is not extensible`, and `Cannot delete property 'a'`. Arrays enforce the same
|
|
rules for index writes, `length`, and the mutating methods (`Object.freeze([1]).push(2)` throws; a sealed array's
|
|
`pop()` throws; a non-extensible array's `pop()`, `sort()`, and `splice(0, 1, x)` work). The mutating methods are
|
|
checked once up front, so a `fill` or `sort` that would land on a hole of a non-extensible array succeeds here
|
|
where JS throws. Maps, Sets, and Dates freeze their properties only, not their contents, as in JS.
|
|
`Object.freeze(new Uint8Array(1))` and `seal` throw `TypeError` like JS (`preventExtensions` and empty typed
|
|
arrays are fine). Functions are objects and freeze like any other value.
|
|
- [x] Circular references are rejected when created (`o.self = o`, `array.push(array)`), not at serialization as in JS.
|
|
- [x] `Object.is` for supported data values.
|
|
- [x] `Object.groupBy` over finite collections and custom synchronous iterators/generators, with string-key coercion
|
|
and plain-object results.
|
|
- [x] `Object.prototype` methods on values: `toString` (`"[object Array]"`, `"[object Map]"`, `"[object Promise]"`, and so
|
|
on for every built-in kind, as JS reports through `Symbol.toStringTag`), `toLocaleString` (calls the value's
|
|
`toString`, as in JS), `valueOf`, `hasOwnProperty`, `isPrototypeOf`, and `propertyIsEnumerable`.
|
|
|
|
## Arrays
|
|
|
|
- [x] The `Array` constructor with or without `new`: `Array(a, b)` collects arguments and `Array(n)` creates a sparse
|
|
array of that length; invalid lengths throw `RangeError`. Iteration, spread, join, and JSON handle holes like
|
|
JavaScript, and host results normalize holes to `null`.
|
|
- [x] Static methods: `Array.isArray`, `Array.of`, and `Array.from`, including the `Array.from` mapper form with
|
|
`(value, index)` arguments and stepwise synchronous iterator consumption.
|
|
- [x] Iteration/transformation: `map`, `filter`, `flatMap`, and `forEach`.
|
|
- [x] Searching/tests: `find`, `findIndex`, `findLast`, `findLastIndex`, `some`, `every`, `includes`, `indexOf`, and
|
|
`lastIndexOf`. An explicit `undefined` fromIndex counts as present: `[1, 2, 1].lastIndexOf(1, undefined)` is `0`
|
|
while `lastIndexOf(1)` is `2`.
|
|
- [x] Aggregation: `reduce` and `reduceRight`.
|
|
- [x] Ordering: `sort`, `toSorted`, `reverse`, and `toReversed`.
|
|
- [x] Access/copying: `at`, `slice`, `concat`, `flat`, `with`, `join`, and `toLocaleString` (each element's
|
|
`toLocaleString`, holes and nullish elements as empty strings).
|
|
- [x] Mutation: `push`, `pop`, `shift`, `unshift`, `splice`, `fill`, and `copyWithin`.
|
|
- [x] `keys`, `values`, `entries`, and `[Symbol.iterator]` (the same function as `values`) return live iterator objects
|
|
with `next()` and `[Symbol.iterator]`, as in JS. Iterator objects are opaque references: they print as
|
|
`[opaque reference]`, serialize to `{}`, and cannot be passed to extensions. Every built-in collection iterator
|
|
shares one prototype, where JavaScript gives each collection its own; `Object.getPrototypeOf` shows the
|
|
difference.
|
|
- [x] `length`, numeric indexing, index assignment, spread, and `for...of`.
|
|
- [x] `Array.prototype.toSpliced`.
|
|
- [x] Canonical array/string index parsing: keys such as `"01"` are ordinary properties rather than aliases of index
|
|
`1`.
|
|
- [x] `Array.prototype.sort` preserves trailing holes, while `toSorted` densifies holes into `undefined` elements,
|
|
like JavaScript.
|
|
- [x] Assigning `length` to truncate or extend an array; invalid lengths throw `RangeError`.
|
|
- [x] Non-index own properties on arrays (`arr.foo = 1`, `arr.constructor = null`). They are excluded from the JSON
|
|
form, like `JSON.stringify`.
|
|
- [x] Numeric arguments coerce as in JS (ToIntegerOrInfinity): `indexOf(x, "1")`, `slice("1", "3")`, `at(null)`,
|
|
`flat(1.9)`, `with(1.5, v)`, `Math.max("3", "2")`, `parseInt("11", "2")`, `(1.5).toFixed("2")`,
|
|
`String.fromCharCode("65")`, and the Uint8Array equivalents. `join(sep)` and `JSON.parse(text)` apply ToString
|
|
(`join(null)` is `"1null2"`, `JSON.parse(123)` is `123`). `Array.from({ length: "2" })` applies ToLength; a
|
|
promise source still throws with an `await` hint rather than JS's silent `[]`. `join`, `Math.*`, `parseInt`,
|
|
and the String and Number methods consult a program object's own `valueOf`/`toString`; the array methods do not
|
|
yet (see ToPrimitive above).
|
|
|
|
## Strings
|
|
|
|
- [x] Case/normalization: `toLowerCase`, `toUpperCase`, `normalize`, and the `toLocaleLowerCase`/`toLocaleUpperCase`
|
|
aliases, which ignore their locale argument and apply the default Unicode casing.
|
|
- [x] Trimming: `trim`, `trimStart`, and `trimEnd`, plus the Annex B `trimLeft` and `trimRight` aliases.
|
|
- [x] Searching/tests: `includes`, `startsWith`, `endsWith`, `indexOf`, `lastIndexOf`, and `search`.
|
|
- [x] Slicing/access: `slice`, `substring`, Annex B `substr`, `at`, `charAt`, `charCodeAt`, and `codePointAt`.
|
|
- [x] Construction/transformation: `split`, `concat`, `repeat`, `padStart`, `padEnd`, `replace`, and `replaceAll`.
|
|
- [x] Regular-expression integration: `match`, materialized `matchAll`, `replace`, `replaceAll`, `split`, and `search`.
|
|
- [x] `localeCompare`; locale and options arguments are currently ignored.
|
|
- [x] `isWellFormed` and `toWellFormed`.
|
|
- [x] `toString`, `length`, numeric indexing, spread, `for...of`, and `[Symbol.iterator]` by Unicode code point.
|
|
- [x] Static `String.fromCharCode` and `String.fromCodePoint`.
|
|
- [x] Native argument coercion for supported String methods; for example, `includes(1)` and `slice("1")` coerce like
|
|
native JS, `split(undefined)` returns the whole string, and `includes`/`startsWith`/`endsWith` reject regular
|
|
expressions with a native-style `TypeError`. Data objects convert through their own `toString`/`valueOf` (see
|
|
ToPrimitive above). Opaque runtime references still reject as data errors, and `repeat` still requires a finite
|
|
non-negative count.
|
|
- [x] Native no-argument parity for `match()`, `matchAll()`, and `search()`; all behave as an empty pattern.
|
|
- [x] `String.raw`, on a template object or any `{ raw }` object; raw strings and substitutions coerce through their own
|
|
`toString`.
|
|
- [x] `match`, `matchAll`, `search`, and `split` read any non-RegExp argument as a pattern string, as `new RegExp(arg)`
|
|
would: `"a1b".match(1)` matches `/1/`, `search(null)` looks for `"null"`, `undefined` is the empty pattern, and
|
|
an object supplies its own `toString`.
|
|
|
|
## Numbers and Math
|
|
|
|
- [x] Coercion functions: `Number`, `parseInt`, and `parseFloat`.
|
|
- [x] Number predicates/parsers: `Number.isInteger`, `Number.isFinite`, `Number.isNaN`, `Number.isSafeInteger`,
|
|
`Number.parseInt`, and `Number.parseFloat`.
|
|
- [x] Number formatting: `toFixed`, `toPrecision`, `toExponential`, `toString`, `valueOf`, and `toLocaleString`, which
|
|
always formats as `en-US` (`"1,234.5"`) so output does not depend on the host.
|
|
- [x] Number constants: `MAX_SAFE_INTEGER`, `MIN_SAFE_INTEGER`, `MAX_VALUE`, `MIN_VALUE`, `EPSILON`, `NaN`,
|
|
`POSITIVE_INFINITY`, and `NEGATIVE_INFINITY`.
|
|
- [x] Math constants: `PI`, `E`, `LN2`, `LN10`, `LOG2E`, `LOG10E`, `SQRT2`, and `SQRT1_2`.
|
|
- [x] Math methods: `random`, `max`, `min`, `abs`, `acos`, `acosh`, `asin`, `asinh`, `atan`, `atan2`, `atanh`,
|
|
`floor`, `ceil`, `round`, `trunc`, `sign`, `sqrt`, `cbrt`, `pow`, `hypot`, `cos`, `cosh`, `sin`, `sinh`,
|
|
`tan`, `tanh`, `log`, `log2`, `log10`, `log1p`, `exp`, `expm1`, `f16round`, `fround`, `clz32`, and `imul`.
|
|
- [x] Native zero-argument behavior for `Number()` and `String()`: they produce `0` and `""`, while
|
|
`Number(undefined)` stays `NaN` and `String(undefined)` stays `"undefined"`.
|
|
- [x] `++` and `--` use CodeMode numeric coercion (numeric strings increment, plain data objects become `NaN`, Dates
|
|
use their epoch time) and reject opaque runtime references as data errors.
|
|
- [x] Unknown static members on global namespaces and on `Number`/`String`/the coercion functions read as `undefined`
|
|
for feature detection. Calling any undefined value reports a native-style `TypeError` naming the callee, for
|
|
example `Math.sum is not a function.` or `search(...).catch is not a function.` Unknown `Promise` statics keep
|
|
their descriptive error.
|
|
- [x] `Math.sumPrecise` over finite collections and custom synchronous iterators/generators, rejecting non-number
|
|
elements without coercion.
|
|
- [x] Global coercing `isFinite` and `isNaN`; opaque runtime references reject as data errors, like `Number(...)`.
|
|
|
|
## JSON and console
|
|
|
|
- [x] `JSON.parse` and `JSON.stringify` for supported data objects.
|
|
- [x] Numeric/string indentation for `JSON.stringify`.
|
|
- [x] `JSON.parse` reviver callbacks, including postorder traversal, deletion through `undefined`, and root replacement.
|
|
Revivers receive `(key, value)` with the holder as `this`.
|
|
- [x] `JSON.stringify` function and array replacers. Function replacers receive `(key, value)` in preorder, including
|
|
the root, with the holder as `this`. Array replacers preserve requested property order, deduplicate names, coerce
|
|
number primitives, and ignore non-string/non-number entries. Primitive wrapper entries remain unsupported.
|
|
- [x] Captured `console.log`, `console.info`, `console.debug`, `console.warn`, and `console.error`. An Error prints as
|
|
`Error.prototype.toString` would show it (`Error: boom`), wherever it appears in the logged value.
|
|
- [x] Captured `console.dir` and `console.table`.
|
|
|
|
## Date
|
|
|
|
- [x] `Date.now`, `Date.parse`, and `Date.UTC`.
|
|
- [x] `new Date()` from the current time, epoch milliseconds, a date string, another Date, or local components.
|
|
- [x] `Date()` without `new` returns the current time as a string, like JS, but in deterministic ISO format
|
|
rather than the host's locale/timezone string.
|
|
- [x] `getTime`, `valueOf`, `toISOString`, `toJSON`, and deterministic ISO `toString`.
|
|
- [x] Local getters: `getFullYear`, `getMonth`, `getDate`, `getDay`, `getHours`, `getMinutes`, `getSeconds`, and
|
|
`getMilliseconds`.
|
|
- [x] UTC getters: `getUTCFullYear`, `getUTCMonth`, `getUTCDate`, `getUTCDay`, `getUTCHours`, `getUTCMinutes`,
|
|
`getUTCSeconds`, and `getUTCMilliseconds`.
|
|
- [x] `getTimezoneOffset`, arithmetic, relational comparison, and `instanceof Date`.
|
|
- [x] Date values serialize to ISO strings; invalid dates serialize to `null`.
|
|
- [x] Local and UTC Date setters, including native argument coercion, mutation, rollover, invalid-Date recovery, and
|
|
`TimeClip` behavior. On an invalid Date every setter but `setTime` and `set(UTC)FullYear` answers `NaN` without
|
|
writing, so a time set inside an argument's `valueOf` survives.
|
|
- [x] `Date.prototype.toUTCString` and its `toGMTString` alias.
|
|
- [x] `toDateString` and `toTimeString` in the host's local timezone.
|
|
- [x] `toLocaleString`, `toLocaleDateString`, and `toLocaleTimeString` always format as `en-US` in UTC
|
|
(`"1/1/1970, 12:00:00 AM"`) so output does not depend on the host.
|
|
- [x] Native one-argument Date coercion for supported values, including booleans, null, arrays, and plain objects.
|
|
- [x] Date setters, construction, and `Date.UTC` coerce object arguments through their own `valueOf`/`toString` in
|
|
argument order and surface their throws; only the first seven components are converted.
|
|
- [x] Native Date loose-equality and default primitive-coercion semantics, using CodeMode's deterministic ISO string
|
|
representation for the string primitive.
|
|
- [x] Native `RangeError` branding for invalid `toISOString()` calls.
|
|
|
|
## Regular expressions
|
|
|
|
- [x] Literal and `RegExp(pattern, flags)` construction, with or without `new`.
|
|
- [x] `test`, `exec`, and `toString`.
|
|
- [x] Readable `source`, `flags`, `lastIndex`, `hasIndices`, `global`, `ignoreCase`, `multiline`, `sticky`, `unicode`,
|
|
`unicodeSets`, and `dotAll`.
|
|
- [x] Captures, named groups, match `.index` and `.input`, and stateful global matching.
|
|
- [x] Integration with supported String methods, including function replacers.
|
|
- [x] Writable `lastIndex`, shared by `exec`, `test`, and the String methods. It is a prototype accessor that stores
|
|
a number, so `re.lastIndex = "12"` reads back `12`, `delete` is a no-op, and `hasOwnProperty("lastIndex")` is
|
|
`false`.
|
|
- [x] Match `indices` metadata for the `d` flag, including named groups on `exec`, `match`, and `matchAll` results.
|
|
- [x] `RegExp.escape`.
|
|
|
|
## Iterator
|
|
|
|
- [x] `Iterator.prototype.map`, `filter`, `take`, `drop`, and `flatMap` on any iterator or generator: lazy, one source
|
|
step per result, closing the source when a callback throws, on early `return()`, or when `for...of` or
|
|
destructuring finishes with it early. Once done or closed a helper stays done, and a callback that re-enters its
|
|
own helper is a `TypeError`. `take`/`drop` coerce their count and reject `NaN` or negative counts with a
|
|
`RangeError`; `flatMap` callbacks must return an iterable or iterator, not a string.
|
|
- [x] `Iterator.prototype.reduce`, `toArray`, `forEach`, `some`, `every`, and `find`, closing the source on early exit.
|
|
- [x] `Iterator.from(value)` returns iterators and generators as they are, and wraps strings, iterables, and objects
|
|
with a `next` method. `Iterator` itself is abstract: calling or constructing it is a `TypeError`.
|
|
- [x] Helpers and `Iterator.from` wrappers have `return()`; collection iterators (`array.values()`) do not, as in JS,
|
|
so an early exit from them leaves them where they were.
|
|
- [ ] `Iterator.concat`, `Iterator.zip`, and `Iterator.zipKeyed` (stage 3 proposals).
|
|
|
|
## Map and Set
|
|
|
|
- [x] Static `Map.groupBy` over finite collections and custom synchronous iterators/generators, preserving key identity.
|
|
- [x] `new Map()` from synchronous iterables of entries.
|
|
- [x] Map `get`, `set`, `has`, `delete`, `clear`, `size`, `forEach`, `getOrInsert`, and `getOrInsertComputed`.
|
|
`forEach` is live: entries deleted during the walk are skipped and entries added are visited, as in JS.
|
|
- [x] `new Set()` from synchronous iterables.
|
|
- [x] Set `add`, `has`, `delete`, `clear`, `size`, and `forEach`.
|
|
- [x] Live `keys`, `values`, `entries`, and `[Symbol.iterator]` iterators for Map and Set; a Set-like operand's `keys()`
|
|
may return any iterator or an array.
|
|
- [x] Spread, `for...of`, `Array.from`, and `Object.fromEntries` integration.
|
|
- [x] Map and Set values serialize to `{}` at host/JSON boundaries.
|
|
- [x] Set composition and relation methods: `union`, `intersection`, `difference`, `symmetricDifference`, `isSubsetOf`,
|
|
`isSupersetOf`, and `isDisjointFrom`, including supported Set-like operands.
|
|
- [x] `WeakMap` (`get`, `set`, `has`, `delete`, `getOrInsert`, `getOrInsertComputed`) and `WeakSet` (`add`, `has`,
|
|
`delete`), constructed from iterables. Keys must be program objects: a primitive or tool reference throws
|
|
`Invalid value used as weak map key`, while `has`/`delete`/`get` with one answer `false`/`undefined`. Entries are
|
|
held by a host weak collection, so nothing is retained past the key's own lifetime. As in JS they have no `size`,
|
|
iteration, or `clear`, `structuredClone` rejects them, and they serialize to `{}` at host boundaries.
|
|
|
|
## URL and URI helpers
|
|
|
|
- [x] `encodeURI`, `encodeURIComponent`, `decodeURI`, and `decodeURIComponent`.
|
|
- [x] `new URL(input, base)`, `URL.canParse`, and `URL.parse`.
|
|
- [x] URL `toString`, `toJSON`, and linked `searchParams`.
|
|
- [x] Readable URL fields: `href`, `origin`, `protocol`, `username`, `password`, `host`, `hostname`, `port`,
|
|
`pathname`, `search`, and `hash`.
|
|
- [x] Writable URL fields except `origin`.
|
|
- [x] `new URLSearchParams()` from query strings, data objects, synchronous iterables of pairs, and URLSearchParams.
|
|
- [x] URLSearchParams `append`, `delete`, `get`, `getAll`, `has`, `set`, `sort`, `forEach`, `keys`, `values`,
|
|
`entries`, `[Symbol.iterator]`, `toString`, and `size`.
|
|
- [x] URL values are their href in `JSON.stringify` and at the host boundary. URLSearchParams are `{}` in
|
|
`JSON.stringify` and their query string at the host boundary.
|
|
|
|
## Uint8Array
|
|
|
|
The only binary type. Bytes stay inside the program or cross to extensions as copies; the tool boundary rejects them
|
|
with a hint to encode as text first (`TextDecoder`, `toBase64`, `toHex`).
|
|
|
|
- [x] `new Uint8Array(length | array | iterable | Uint8Array)`, `Uint8Array.from`, `Uint8Array.of`, `fromBase64`,
|
|
and `fromHex`. Lengths are capped like arrays.
|
|
- [x] Index reads and writes with JS byte semantics: values wrap modulo 256, out-of-range writes are ignored, indexes
|
|
cannot be deleted. `length` is a prototype accessor, so `Object.keys` lists only indexes.
|
|
- [x] `at`, `slice`, `subarray` (a view on the same bytes), `set`, `fill`, `reverse`, `indexOf`, `lastIndexOf`,
|
|
`includes`, `join`, `toString`, `toBase64`, `toHex`, and live `keys`, `values`, `entries`, and `[Symbol.iterator]`
|
|
iterators. Start indexes coerce as for arrays, and `lastIndexOf(x, undefined)` searches from index 0 while
|
|
`lastIndexOf(x)` searches from the end, as in JS.
|
|
- [x] Spread, destructuring, `for...of`, `yield*`, `Array.from`, and `new Set(bytes)`. `Array.isArray` is false.
|
|
- [x] String coercion joins with commas; `JSON.stringify` gives `{"0":1,...}`; `console.log` prints
|
|
`Uint8Array(n) [...]`.
|
|
- [x] Callback methods `forEach`, `map`, `filter`, `find`, `findIndex`, `findLast`, `findLastIndex`, `some`, `every`,
|
|
`reduce`, and `reduceRight`, sharing the Array implementations; the callback receives `(byte, index, bytes)`.
|
|
`map` and `filter` return new Uint8Arrays with results clamped like index writes (`map((b) => b * 100)` on
|
|
`[1, 2, 3]` is `[100, 200, 44]`); `reduce` on an empty Uint8Array without an initial value is a `TypeError`.
|
|
- [x] `sort` in place, numeric ascending by default (`[10, 9, 1]` sorts to `[1, 9, 10]`) or by comparator.
|
|
- [ ] `ArrayBuffer`, `DataView`, and other typed arrays.
|
|
|
|
## Web platform helpers
|
|
|
|
- [x] `atob` and `btoa` with forgiving-base64 decoding and WebIDL string conversion; invalid input throws a
|
|
`TypeError`, since there is no `DOMException`.
|
|
- [x] `crypto.randomUUID()` and `crypto.getRandomValues(uint8Array)`.
|
|
- [x] `structuredClone(value)` deep-copies primitives, plain objects (own enumerable string keys onto a plain object;
|
|
the prototype is not kept), arrays (holes and extra keys kept), Map, Set, Date, RegExp (`lastIndex` reset to 0),
|
|
Uint8Array, and errors (standard `name`, `message`, `cause`, and `stack`; other names become `Error`, extra
|
|
fields drop). Shared references stay shared in the copy, and the copy is extensible even when the source was
|
|
frozen. Functions, symbols, promises, iterators, URL, Headers, and tool references cannot be cloned; without a
|
|
`DOMException`, the failure is a `TypeError` whose message starts with `DataCloneError:`.
|
|
- [x] `TextEncoder` and `TextDecoder` for UTF-8 only: any other label is a `RangeError`. `TextDecoder` accepts the
|
|
`fatal` and `ignoreBOM` options; `decode` takes a Uint8Array or nothing.
|
|
- [x] `new Headers()` from records, synchronous iterables of pairs, and Headers, wrapping the host's `Headers`: names
|
|
fold to lowercase, values are normalized and combined, and invalid names or values throw a `TypeError`.
|
|
- [x] Headers `append`, `delete`, `get`, `getSetCookie`, `has`, `set`, `forEach`, `keys`, `values`, `entries`, and
|
|
`[Symbol.iterator]`; iteration is live and sorted by name, with `set-cookie` values kept apart.
|
|
- [x] Headers serialize to a `{ name: value }` object in JSON, in results, and in tool arguments.
|
|
- [ ] `Request`, `Response`, and `Blob`.
|
|
- [ ] `crypto.subtle` and `TextDecoder` streaming or non-UTF-8 encodings.
|
|
|
|
## Extensions
|
|
|
|
Host functions a host opts in through `Extension.make({ name, globals })` and `CodeMode.make({ extensions })`.
|
|
Nothing is exposed unless a host provides it; extension calls are not tool calls.
|
|
|
|
- [x] Each global is a function, callable but not constructible, run with `this` undefined. A global that shadows
|
|
a built-in or another extension throws at `make`.
|
|
- [x] Every value crossing in either direction is converted, never shared: plain objects and arrays are copied,
|
|
`Date`, `RegExp`, `URL`, `URLSearchParams`, `Headers`, `Map`, `Set`, and `Uint8Array` become fresh copies with
|
|
their contents converted (a host `ArrayBuffer` comes in as a `Uint8Array`; other typed arrays cannot come out),
|
|
errors cross as errors with their name, message, `cause`, and own enumerable data, and a `__proto__` key is
|
|
dropped. Functions, generators,
|
|
un-awaited promises, and symbols cannot be passed in; a class instance, a symbol, or a BigInt cannot come out.
|
|
- [x] A host function inside a result becomes a program function whose calls cross the same way, so a result can
|
|
carry methods (`res.json()`) whose host closures keep the host state. Diagnostics name it by its path
|
|
(`fetch.json`). Like any program function it vanishes at the data boundary.
|
|
- [x] Each call to an extension global runs inside the host's `extension.before`/`extension.after` hooks as
|
|
`{ extension, name, args }`, with the host's own error on failure; calls to functions inside results do not.
|
|
- [x] A host `Promise` becomes a program promise. Whatever host code returns, resolves, throws, or rejects with
|
|
crosses the same way, so `catch (e)` receives a copy of the thrown value (an `Error` of the matching type, or
|
|
plain data).
|
|
- [x] An Error crosses, in either direction, as its name, message, `cause`, and own enumerable data, so Node's
|
|
`code`, `errno`, `syscall`, and `path` reach the program and `err.code === "ENOENT"` works. `stack` stays on its
|
|
own side, no field may shadow an Error method, and a field that cannot cross (a class instance, a function) is
|
|
left behind rather than replacing the error.
|
|
- [ ] Program functions as arguments to extension code (callbacks such as `forEach`).
|
|
- [ ] Host classes. Stateful host objects are expressed as closures; a declared method table would be the next
|
|
step if `new X()` in a program is ever needed.
|
|
|
|
## Errors and diagnostics
|
|
|
|
- [x] `Error`, `TypeError`, `RangeError`, `SyntaxError`, `ReferenceError`, `EvalError`, and `URIError`, callable with
|
|
or without `new`.
|
|
- [x] `AggregateError` with the `(errors, message?)` signature and an own `errors` array, constructed directly or by
|
|
an all-rejected `Promise.any`; direct construction accepts custom synchronous iterators and generators.
|
|
- [x] Error `name`/`message`, error inheritance through `instanceof`, and plain-data serialization. `message` is an own
|
|
non-enumerable property and `name` is inherited, as in JS, so `Object.keys(err)` is `[]` for a plain error. The
|
|
result boundary still emits `{ name, message, ...own enumerable }`, so a field such as `code` crosses. `cause` is
|
|
non-enumerable: an extension Error carries it, and this JSON form does not. Errors have no `stack`; the diagnostic
|
|
carries a 1-based line and column in the submitted source instead.
|
|
- [x] `instanceof` against any constructor with a `prototype`, including every built-in and `Function`.
|
|
- [x] Derived error constructors extend `Error` itself: `Object.getPrototypeOf(TypeError) === Error`, so
|
|
`TypeError.isError` is inherited, and `TypeError.prototype` inherits from `Error.prototype`.
|
|
- [x] Catchable user throws, runtime failures raised during interpreted evaluation, awaited tool failures, and awaited
|
|
tool-call-limit failures; parse/compile failures, cooperative timeout, and output bounding remain outside program
|
|
`catch`.
|
|
- [x] Source locations on unsupported-syntax diagnostics. The diagnostic names the rejected node type and attaches a
|
|
short orientation to the supported subset; this matrix is the full reference.
|
|
- [x] Model-visible host failure messages and underlying causes, including output-validation errors.
|
|
- [x] Caught errors do not distinguish user throws, interpreter failures, and tool failures; a program sees one
|
|
Error-shaped value in `catch`, rejection handlers, and `Promise.allSettled` reasons. It always has `name` and
|
|
`message`, plus `cause` and own data when the failure carried them. This is deliberate: the program should
|
|
handle a failure the same way regardless of where it originated.
|
|
- [x] Failures raised by the interpreter are `TypeError`s unless JavaScript names them otherwise (`RangeError`,
|
|
`ReferenceError`, `SyntaxError`, `URIError`), so `e instanceof TypeError` and `e.constructor === TypeError`
|
|
hold. Unsupported syntax reached at runtime is a `SyntaxError`; awaited tool failures stay plain `Error`.
|
|
Host errors escaping a built-in (`(1).toFixed(200)`) become the same-named program error at the call.
|
|
A failure raised inside a promise a built-in created (`Promise.all(1)`, `Promise.race([])`, a resolution cycle)
|
|
is located at the call that created the promise.
|
|
- [x] One failure is one error object: every `catch`, rejection handler, and `allSettled` reason for the same
|
|
failure sees the identical value, so `a === b` holds after awaiting the same rejected promise twice.
|
|
- [x] Rethrowing an interpreter failure keeps its diagnostic: `catch (e) { throw e }` still reports the original
|
|
kind and source location. Uncaught errors report as `name: message` whoever raised them, as
|
|
`Error.prototype.toString` would (`TypeError: Cannot read properties of null (reading 'foo').`,
|
|
`TypeError: bad input`); other thrown values report as `Uncaught: <value>`.
|