mirror of
https://gitee.com/zhangsken/opencode.git
synced 2026-10-16 10:30:01 +08:00
refactor(codemode): give errors a real prototype chain and JS error types (#48559)
This commit is contained in:
@@ -74,6 +74,7 @@ ultimate source of truth. Upstream test262 files run verbatim from `test/test262
|
||||
- [ ] Destructuring a key that member access resolves through the owning built-in, such as
|
||||
`const { constructor } = error`, reads `undefined`.
|
||||
- [ ] Member expressions as `for...in` targets (`for (x.y in obj)`).
|
||||
- [ ] `IteratorClose` during destructuring should throw a `TypeError` when `return()` yields a non-object.
|
||||
|
||||
## Statements and control flow
|
||||
|
||||
@@ -128,8 +129,8 @@ ultimate source of truth. Upstream test262 files run verbatim from `test/test262
|
||||
- [ ] A named function expression's name is not bound inside its own body.
|
||||
- [ ] Redeclaring a function in the same scope is rejected; in JavaScript the last declaration wins.
|
||||
- [ ] A line terminator between `async function` and the function name.
|
||||
- [ ] Async generator functions evaluate parameter defaults and destructuring at the first `next()` rather than at the
|
||||
call, so their errors are not thrown synchronously.
|
||||
- [ ] Generator and async generator functions evaluate parameter defaults and destructuring at the first `next()`
|
||||
rather than at the call, so their errors are not thrown synchronously.
|
||||
- [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
|
||||
@@ -173,8 +174,12 @@ ultimate source of truth. Upstream test262 files run verbatim from `test/test262
|
||||
- [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.
|
||||
- [ ] Operators, `switch` discriminants, and coercion helpers such as `String` and `isNaN` applied to functions and
|
||||
namespaces; JavaScript coerces them, the interpreter rejects non-data operands.
|
||||
- [ ] Operators, `switch` discriminants, template interpolation, and coercion helpers such as `String` and `isNaN`
|
||||
applied to functions and namespaces; JavaScript coerces them, the interpreter rejects non-data operands.
|
||||
- [ ] ToPrimitive on object operands: operators, `Error(message)`, `Date` arguments, and `parseInt` radix should call
|
||||
`valueOf`/`toString` in spec order and surface their throws.
|
||||
- [ ] Property keys follow ToPropertyKey: `x[null]`, `x[true]`, and objects (via `toString`) become string keys; only
|
||||
strings and numbers are accepted.
|
||||
|
||||
## Promises and tools
|
||||
|
||||
@@ -239,15 +244,17 @@ ultimate source of truth. Upstream test262 files run verbatim from `test/test262
|
||||
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] `__proto__`, `constructor`, and `prototype` are ordinary own data keys. `x.constructor` without an own key resolves
|
||||
to the owning built-in (`[].constructor === Array`, `new TypeError().constructor === TypeError`); prototype objects
|
||||
are not observable, so `[].__proto__` and `Object.prototype` read as `undefined` and `o.__proto__ = x` sets an own
|
||||
field.
|
||||
- [x] `__proto__`, `constructor`, and `prototype` are ordinary own data keys. Errors inherit `constructor` from a real
|
||||
`Error.prototype` → `TypeError.prototype` chain, so `new TypeError().constructor === TypeError` holds through
|
||||
member access and destructuring alike; `x.constructor` on other values without an own key resolves to the owning
|
||||
built-in (`[].constructor === Array`). Prototype objects are not observable, so `[].__proto__` and
|
||||
`Object.prototype` read as `undefined` and `o.__proto__ = x` sets an own field.
|
||||
- [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.
|
||||
- [ ] `Object.prototype` methods on values: `toString`, `toLocaleString`, `valueOf`, and `hasOwnProperty`.
|
||||
- [ ] `Object.prototype` methods on values: `toString`, `toLocaleString`, `valueOf`, `hasOwnProperty`, and
|
||||
`propertyIsEnumerable`.
|
||||
|
||||
## Arrays
|
||||
|
||||
@@ -298,6 +305,8 @@ ultimate source of truth. Upstream test262 files run verbatim from `test/test262
|
||||
`repeat` still requires a finite non-negative count.
|
||||
- [x] Native no-argument parity for `match()`, `matchAll()`, and `search()`; all behave as an empty pattern. Present
|
||||
arguments must still be a regular expression or string pattern.
|
||||
- [ ] `String.raw`.
|
||||
- [ ] `match`, `search`, and `split` accept any value and coerce it (objects via `toString`), like JavaScript.
|
||||
|
||||
## Numbers and Math
|
||||
|
||||
@@ -352,6 +361,8 @@ ultimate source of truth. Upstream test262 files run verbatim from `test/test262
|
||||
- [x] `Date.prototype.toUTCString` and its `toGMTString` alias.
|
||||
- [x] `toDateString` and `toTimeString` in the host's local timezone.
|
||||
- [x] Native one-argument Date coercion for supported values, including booleans, null, arrays, and plain objects.
|
||||
- [ ] Date setters and multi-argument construction coerce object arguments through `valueOf`/`toString` and surface
|
||||
their throws.
|
||||
- [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.
|
||||
@@ -396,8 +407,8 @@ ultimate source of truth. Upstream test262 files run verbatim from `test/test262
|
||||
|
||||
## Web platform helpers
|
||||
|
||||
- [x] `atob` and `btoa` with forgiving-base64 decoding and WebIDL string conversion; invalid input throws an Error
|
||||
named `InvalidCharacterError`, since there is no `DOMException`.
|
||||
- [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()`.
|
||||
- [ ] `crypto.getRandomValues` and `crypto.subtle`, `TextEncoder`/`TextDecoder`, and `Blob`: these need a binary
|
||||
value type, which the JSON-like data model does not have yet.
|
||||
@@ -421,5 +432,6 @@ ultimate source of truth. Upstream test262 files run verbatim from `test/test262
|
||||
- [x] Caught errors do not distinguish user throws, interpreter failures, and tool failures; a program sees one
|
||||
Error-shaped value with `name` and `message` in `catch`, rejection handlers, and `Promise.allSettled` reasons.
|
||||
This is deliberate: the program should handle a failure the same way regardless of where it originated.
|
||||
- [ ] Failures raised by the interpreter itself carry the generic `Error` name where JavaScript throws a `TypeError`,
|
||||
`RangeError`, or `ReferenceError`, so `e instanceof TypeError` and `e.constructor === TypeError` are false.
|
||||
- [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`.
|
||||
|
||||
@@ -2,9 +2,11 @@ export * as Data from "./data.js"
|
||||
|
||||
import type { DiagnosticKind } from "./codemode.js"
|
||||
import {
|
||||
get,
|
||||
ownEntries,
|
||||
parseArrayIndex,
|
||||
ProgramArray,
|
||||
ProgramError,
|
||||
ProgramFunction,
|
||||
ProgramObject,
|
||||
set,
|
||||
@@ -120,6 +122,11 @@ const copy = (value: unknown, label: string, mode: Mode, depth: number, seen: Se
|
||||
}
|
||||
if (value instanceof ProgramObject) {
|
||||
const copied: Record<string, unknown> = {}
|
||||
// Errors serialize as { name, message, ...own }: both may be inherited, and neither is enumerable in JS.
|
||||
if (value instanceof ProgramError) {
|
||||
define(copied, "name", copy(get(value, "name"), label, mode, depth + 1, seen))
|
||||
define(copied, "message", copy(get(value, "message"), label, mode, depth + 1, seen))
|
||||
}
|
||||
for (const [key, item] of ownEntries(value)) {
|
||||
const next = copy(item, label, mode, depth + 1, seen)
|
||||
if (next === undefined && mode === "json") continue
|
||||
|
||||
@@ -5,15 +5,10 @@ import { toData, ToolRuntimeError } from "../data.js"
|
||||
import { type AstNode, formatLocation, InterpreterRuntimeError, ProgramThrow, sourceLocation } from "./model.js"
|
||||
import { containsRuntimeReference } from "./references.js"
|
||||
import { type HostCall, HostFunction } from "./host.js"
|
||||
import { get, ProgramError, ProgramObject } from "./objects.js"
|
||||
import { createErrorValue, type ErrorType, isErrorType } from "./intrinsics.js"
|
||||
import { get, hasPrototype, ProgramArray, ProgramError, ProgramObject, set } from "./objects.js"
|
||||
import { type Runner } from "./runner.js"
|
||||
import {
|
||||
coerceToString,
|
||||
createAggregateErrorValue,
|
||||
createErrorValue,
|
||||
errorBrandName,
|
||||
errorConstructors,
|
||||
} from "../stdlib/value.js"
|
||||
import { coerceToString } from "../stdlib/value.js"
|
||||
|
||||
export const normalizeError = (error: unknown): Diagnostic => {
|
||||
if (error instanceof InterpreterRuntimeError) {
|
||||
@@ -77,15 +72,19 @@ export const normalizeError = (error: unknown): Diagnostic => {
|
||||
}
|
||||
}
|
||||
|
||||
export const caughtErrorValue = (thrown: unknown): unknown => {
|
||||
export const caughtErrorValue = <R>(runner: Runner<R>, thrown: unknown): unknown => {
|
||||
if (thrown instanceof ProgramThrow) return thrown.value
|
||||
if (thrown instanceof InterpreterRuntimeError) return createErrorValue(thrown.errorName, thrown.message)
|
||||
const name = thrown instanceof Error && errorConstructors.has(thrown.name) ? thrown.name : "Error"
|
||||
return createErrorValue(name, normalizeError(thrown).message)
|
||||
const prototypes = runner.intrinsics.errors
|
||||
if (thrown instanceof InterpreterRuntimeError) return createErrorValue(prototypes[thrown.type], thrown.message)
|
||||
const type = thrown instanceof Error && isErrorType(thrown.name) ? thrown.name : "Error"
|
||||
return createErrorValue(prototypes[type], normalizeError(thrown).message)
|
||||
}
|
||||
|
||||
const constructErrorValue = (name: string, args: Array<unknown>): ProgramError =>
|
||||
createErrorValue(name, args[0] === undefined ? "" : coerceToString(args[0]))
|
||||
export const createAggregateErrorValue = <R>(runner: Runner<R>, errors: Array<unknown>, message: string) => {
|
||||
const value = createErrorValue(runner.intrinsics.errors.AggregateError, message)
|
||||
set(value, "errors", new ProgramArray(errors))
|
||||
return value
|
||||
}
|
||||
|
||||
const constructAggregateErrorValue = <R>(
|
||||
runner: Runner<R>,
|
||||
@@ -95,33 +94,31 @@ const constructAggregateErrorValue = <R>(
|
||||
Effect.gen(function* () {
|
||||
const cursor = yield* runner.syncIterator(args[0], node)
|
||||
if (cursor === undefined) {
|
||||
throw new InterpreterRuntimeError("new AggregateError(...) expects a synchronous iterable of errors.", node).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError("new AggregateError(...) expects a synchronous iterable of errors.", node)
|
||||
}
|
||||
const errors: Array<unknown> = []
|
||||
while (true) {
|
||||
const step = yield* cursor.next
|
||||
if (step.done) {
|
||||
return createAggregateErrorValue(errors, args[1] === undefined ? "" : coerceToString(args[1]))
|
||||
return createAggregateErrorValue(runner, errors, args[1] === undefined ? "" : coerceToString(args[1]))
|
||||
}
|
||||
errors.push(step.value)
|
||||
}
|
||||
})
|
||||
|
||||
/** An error constructor such as `Error` or `TypeError`; callable with or without `new`, like JS. */
|
||||
export const errorGlobal = <R>(name: string, runner: Runner<R>) => {
|
||||
export const errorGlobal = <R>(type: ErrorType, runner: Runner<R>) => {
|
||||
const prototype = runner.intrinsics.errors[type]
|
||||
const construct: HostCall<R> = (args, node) =>
|
||||
name === "AggregateError"
|
||||
type === "AggregateError"
|
||||
? constructAggregateErrorValue(runner, args, node)
|
||||
: Effect.sync(() => constructErrorValue(name, args))
|
||||
return new HostFunction<R>({
|
||||
name,
|
||||
: Effect.sync(() => createErrorValue(prototype, args[0] === undefined ? undefined : coerceToString(args[0])))
|
||||
const fn = new HostFunction<R>({
|
||||
name: type,
|
||||
call: construct,
|
||||
construct,
|
||||
instanceOf: (value) => {
|
||||
const brand = errorBrandName(value)
|
||||
return brand !== undefined && (name === "Error" || brand === name)
|
||||
},
|
||||
instanceOf: (value) => hasPrototype(value, prototype),
|
||||
})
|
||||
set(prototype, "constructor", fn)
|
||||
return fn
|
||||
}
|
||||
|
||||
@@ -10,10 +10,11 @@ import { objectGlobal } from "../stdlib/object.js"
|
||||
import { regexpGlobal } from "../stdlib/regexp.js"
|
||||
import { stringGlobal } from "../stdlib/string.js"
|
||||
import { uriGlobal, urlGlobal, urlSearchParamsGlobal } from "../stdlib/url.js"
|
||||
import { coercion, errorConstructors } from "../stdlib/value.js"
|
||||
import { coercion } from "../stdlib/value.js"
|
||||
import { atobGlobal, btoaGlobal, cryptoGlobal } from "../stdlib/web.js"
|
||||
import { ToolReference } from "../tool-runtime.js"
|
||||
import { errorGlobal } from "./errors.js"
|
||||
import { errorTypes } from "./intrinsics.js"
|
||||
import { HostFunction } from "./host.js"
|
||||
import { AsyncIteratorSymbol, InterpreterRuntimeError, IteratorSymbol } from "./model.js"
|
||||
import { promiseGlobal, type PromiseRuntime } from "./promises.js"
|
||||
@@ -35,7 +36,7 @@ const symbolGlobal = new HostFunction({
|
||||
throw new InterpreterRuntimeError(
|
||||
"Symbol is not callable; only Symbol.asyncIterator and Symbol.iterator are available.",
|
||||
node,
|
||||
).as("TypeError")
|
||||
)
|
||||
}),
|
||||
callback: false,
|
||||
members: { asyncIterator: AsyncIteratorSymbol, iterator: IteratorSymbol },
|
||||
@@ -75,5 +76,5 @@ export const globals = <R>(host: Host<R>): ReadonlyArray<readonly [string, unkno
|
||||
["atob", atobGlobal],
|
||||
["btoa", btoaGlobal],
|
||||
["crypto", cryptoGlobal],
|
||||
...[...errorConstructors].map((name) => [name, errorGlobal(name, host.runner)] as const),
|
||||
...errorTypes.map((type) => [type, errorGlobal(type, host.runner)] as const),
|
||||
]
|
||||
|
||||
@@ -75,5 +75,5 @@ export const requiresNew =
|
||||
(name: string): HostCall<never> =>
|
||||
(_, node) =>
|
||||
Effect.sync(() => {
|
||||
throw new InterpreterRuntimeError(`Constructor ${name} requires 'new'.`, node).as("TypeError")
|
||||
throw new InterpreterRuntimeError(`Constructor ${name} requires 'new'.`, node)
|
||||
})
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import { ProgramError, ProgramObject, set } from "./objects.js"
|
||||
|
||||
export const errorTypes = [
|
||||
"Error",
|
||||
"TypeError",
|
||||
"RangeError",
|
||||
"SyntaxError",
|
||||
"ReferenceError",
|
||||
"EvalError",
|
||||
"URIError",
|
||||
"AggregateError",
|
||||
] as const
|
||||
|
||||
export type ErrorType = (typeof errorTypes)[number]
|
||||
|
||||
export const isErrorType = (name: string): name is ErrorType => (errorTypes as ReadonlyArray<string>).includes(name)
|
||||
|
||||
/** The built-in prototype objects of one runtime. Constructors attach themselves as `constructor` when created. */
|
||||
export type Intrinsics = {
|
||||
readonly errors: Readonly<Record<ErrorType, ProgramObject>>
|
||||
}
|
||||
|
||||
export const createErrorValue = (prototype: ProgramObject, message: string | undefined): ProgramError => {
|
||||
const value = new ProgramError(prototype)
|
||||
if (message !== undefined) set(value, "message", message)
|
||||
return value
|
||||
}
|
||||
|
||||
export const createIntrinsics = (): Intrinsics => {
|
||||
const error = new ProgramObject()
|
||||
set(error, "name", "Error")
|
||||
set(error, "message", "")
|
||||
const derived = (type: ErrorType) => {
|
||||
const proto = new ProgramObject(error)
|
||||
set(proto, "name", type)
|
||||
set(proto, "message", "")
|
||||
return proto
|
||||
}
|
||||
return {
|
||||
errors: {
|
||||
Error: error,
|
||||
TypeError: derived("TypeError"),
|
||||
RangeError: derived("RangeError"),
|
||||
SyntaxError: derived("SyntaxError"),
|
||||
ReferenceError: derived("ReferenceError"),
|
||||
EvalError: derived("EvalError"),
|
||||
URIError: derived("URIError"),
|
||||
AggregateError: derived("AggregateError"),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import { invokeURLMethod, uriArgument } from "../stdlib/url.js"
|
||||
import { coerceToNumber, coerceToString } from "../stdlib/value.js"
|
||||
import { compareText } from "../tool-runtime.js"
|
||||
import { Values } from "../values.js"
|
||||
import { type AstNode, IntrinsicReference, InterpreterRuntimeError } from "./model.js"
|
||||
import { type AstNode, InterpreterRuntimeError, IntrinsicReference, rangeError } from "./model.js"
|
||||
import { get, ProgramArray, ProgramObject, record } from "./objects.js"
|
||||
import { containsOpaqueReference, rejectCircularInsertion, typeofValue } from "./references.js"
|
||||
import { applyCollectionCallback, isSupportedCallback, type Runner, toPrimitive } from "./runner.js"
|
||||
@@ -111,7 +111,7 @@ const invokeStringMethod = (value: string, name: string, args: Array<unknown>, n
|
||||
throw new InterpreterRuntimeError(
|
||||
`String.${name} cannot take a regular expression; use regex.test(string) or String.search instead.`,
|
||||
node,
|
||||
).as("TypeError")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,10 +143,10 @@ const invokeStringMethod = (value: string, name: string, args: Array<unknown>, n
|
||||
try {
|
||||
result = value.normalize(form)
|
||||
} catch {
|
||||
throw new InterpreterRuntimeError(
|
||||
throw rangeError(
|
||||
`String.normalize expects the form "NFC", "NFD", "NFKC", or "NFKD" (got ${JSON.stringify(form)}).`,
|
||||
node,
|
||||
).as("RangeError")
|
||||
)
|
||||
}
|
||||
break
|
||||
}
|
||||
@@ -233,7 +233,7 @@ const invokeStringMethod = (value: string, name: string, args: Array<unknown>, n
|
||||
case "repeat": {
|
||||
const count = num(0)
|
||||
if (!Number.isFinite(count) || count < 0)
|
||||
throw new InterpreterRuntimeError("String.repeat expects a finite non-negative count.", node).as("RangeError")
|
||||
throw rangeError("String.repeat expects a finite non-negative count.", node)
|
||||
result = value.repeat(count)
|
||||
break
|
||||
}
|
||||
@@ -519,19 +519,17 @@ const loadSetRecord = <R>(runner: Runner<R>, source: unknown, name: string, node
|
||||
})
|
||||
}
|
||||
if (!(source instanceof ProgramObject)) {
|
||||
throw new InterpreterRuntimeError(`Set.${name} expects a Set-like object.`, node).as("TypeError")
|
||||
throw new InterpreterRuntimeError(`Set.${name} expects a Set-like object.`, node)
|
||||
}
|
||||
return Effect.gen(function* () {
|
||||
const size = yield* coerceNumericArgument(runner, get(source, "size"), node)
|
||||
if (Number.isNaN(size)) {
|
||||
throw new InterpreterRuntimeError(`Set.${name} received a Set-like object with an invalid size.`, node).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError(`Set.${name} received a Set-like object with an invalid size.`, node)
|
||||
}
|
||||
const has = get(source, "has")
|
||||
const keys = get(source, "keys")
|
||||
if (!isSupportedCallback(has) || !isSupportedCallback(keys)) {
|
||||
throw new InterpreterRuntimeError(`Set.${name} expects callable 'has' and 'keys' methods.`, node).as("TypeError")
|
||||
throw new InterpreterRuntimeError(`Set.${name} expects callable 'has' and 'keys' methods.`, node)
|
||||
}
|
||||
return {
|
||||
size: Math.max(Math.trunc(size), 0),
|
||||
@@ -539,7 +537,7 @@ const loadSetRecord = <R>(runner: Runner<R>, source: unknown, name: string, node
|
||||
keys: () =>
|
||||
Effect.flatMap(runner.invokeCallable(keys, [], node), (result) => {
|
||||
if (result instanceof ProgramArray) return Effect.succeed(result.items)
|
||||
throw new InterpreterRuntimeError(`Set.${name} expected 'keys' to return an iterator.`, node).as("TypeError")
|
||||
throw new InterpreterRuntimeError(`Set.${name} expected 'keys' to return an iterator.`, node)
|
||||
}),
|
||||
}
|
||||
})
|
||||
@@ -558,7 +556,7 @@ const invokeURLSearchParamsMethod = <R>(
|
||||
throw new InterpreterRuntimeError(
|
||||
`URLSearchParams.${name} requires ${count} argument${count === 1 ? "" : "s"}.`,
|
||||
node,
|
||||
).as("TypeError")
|
||||
)
|
||||
}
|
||||
}
|
||||
switch (name) {
|
||||
@@ -690,7 +688,7 @@ const invokeArrayMethod = <R>(
|
||||
const index = optNumber(args[0], "index") ?? 0
|
||||
const resolved = index < 0 ? target.length + index : index
|
||||
if (resolved < 0 || resolved >= target.length) {
|
||||
throw new InterpreterRuntimeError("Array.with index is out of range.", node)
|
||||
throw rangeError("Array.with index is out of range.", node)
|
||||
}
|
||||
const copied = [...target]
|
||||
copied[resolved] = args[1]
|
||||
@@ -820,9 +818,7 @@ const invokeArrayMethod = <R>(
|
||||
if (args.length < 2) {
|
||||
while (start < length && !(start in target)) start += 1
|
||||
if (start === length)
|
||||
throw new InterpreterRuntimeError("Array.reduce of an empty array with no initial value.", node).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError("Array.reduce of an empty array with no initial value.", node)
|
||||
accumulator = target[start]
|
||||
start += 1
|
||||
}
|
||||
@@ -838,9 +834,7 @@ const invokeArrayMethod = <R>(
|
||||
if (args.length < 2) {
|
||||
while (start >= 0 && !(start in target)) start -= 1
|
||||
if (start < 0)
|
||||
throw new InterpreterRuntimeError("Array.reduceRight of an empty array with no initial value.", node).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError("Array.reduceRight of an empty array with no initial value.", node)
|
||||
accumulator = target[start]
|
||||
start -= 1
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { Node } from "acorn"
|
||||
import type { ErrorType } from "./intrinsics.js"
|
||||
import type { Effect } from "effect"
|
||||
import type { DiagnosticKind } from "../codemode.js"
|
||||
import type { ProgramObject } from "./objects.js"
|
||||
@@ -80,25 +81,29 @@ export const OptionalShortCircuit: unique symbol = Symbol("codemode.optional-sho
|
||||
|
||||
export class InterpreterRuntimeError extends Error {
|
||||
readonly node?: AstNode
|
||||
errorName = "Error"
|
||||
|
||||
constructor(
|
||||
message: string,
|
||||
node?: AstNode,
|
||||
readonly kind: DiagnosticKind = "ExecutionFailure",
|
||||
readonly suggestions?: ReadonlyArray<string>,
|
||||
/** The JS error class a program sees when it catches this failure. */
|
||||
readonly type: ErrorType = "TypeError",
|
||||
) {
|
||||
super(message)
|
||||
this.name = "InterpreterRuntimeError"
|
||||
if (node) this.node = node
|
||||
}
|
||||
|
||||
as(errorName: string): this {
|
||||
this.errorName = errorName
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
const failure = (type: ErrorType) => (message: string, node?: AstNode) =>
|
||||
new InterpreterRuntimeError(message, node, "ExecutionFailure", undefined, type)
|
||||
|
||||
export const rangeError = failure("RangeError")
|
||||
export const referenceError = failure("ReferenceError")
|
||||
export const syntaxError = failure("SyntaxError")
|
||||
export const uriError = failure("URIError")
|
||||
|
||||
// Orient the agent rather than enumerate JavaScript; interpreter-support.md is the full matrix.
|
||||
export const supportedSyntaxMessage =
|
||||
"This is a restricted JavaScript-like language. Supported: plain and async functions, data literals, destructuring, standard control flow, await and Promise, and built-ins such as Array, Object, Math, JSON, Date, RegExp, Map, Set, and URL. Unsupported: classes, this, getters/setters, tagged templates, BigInt, and custom Symbols. Use plain functions and data objects instead."
|
||||
@@ -109,6 +114,7 @@ export const unsupportedSyntax = (kind: string, node: AstNode): InterpreterRunti
|
||||
node,
|
||||
"UnsupportedSyntax",
|
||||
[supportedSyntaxMessage],
|
||||
"SyntaxError",
|
||||
)
|
||||
|
||||
export const isRecord = (value: unknown): value is Record<string, unknown> =>
|
||||
|
||||
@@ -13,11 +13,8 @@ export class ProgramArray extends ProgramObject {
|
||||
}
|
||||
}
|
||||
|
||||
export class ProgramError extends ProgramObject {
|
||||
constructor(readonly errorName: string) {
|
||||
super()
|
||||
}
|
||||
}
|
||||
/** An object with the [[ErrorData]] slot: what `Error.prototype.toString` and the host boundary recognize as an error. */
|
||||
export class ProgramError extends ProgramObject {}
|
||||
|
||||
export class ProgramFunction extends ProgramObject {
|
||||
readonly length: number
|
||||
@@ -78,6 +75,13 @@ export const get = (target: ProgramObject, key: PropertyKey): unknown => {
|
||||
return undefined
|
||||
}
|
||||
|
||||
export const hasPrototype = (value: unknown, proto: ProgramObject): boolean => {
|
||||
for (let current = value instanceof ProgramObject ? value.proto : null; current !== null; current = current.proto) {
|
||||
if (current === proto) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export const has = (target: ProgramObject, key: PropertyKey): boolean => {
|
||||
for (let current: ProgramObject | null = target; current !== null; current = current.proto) {
|
||||
if (hasOwn(current, key)) return true
|
||||
|
||||
@@ -3,9 +3,8 @@ import type { Diagnostic } from "../codemode.js"
|
||||
import { type AstNode, InterpreterRuntimeError, ProgramThrow, PromiseInstanceMethodReference } from "./model.js"
|
||||
import { get, ProgramArray, ProgramFunction, ProgramObject, record } from "./objects.js"
|
||||
import { HostFunction, requiresNew, sync } from "./host.js"
|
||||
import { caughtErrorValue, normalizeError } from "./errors.js"
|
||||
import { caughtErrorValue, createAggregateErrorValue, normalizeError } from "./errors.js"
|
||||
import { typeofValue } from "./references.js"
|
||||
import { createAggregateErrorValue } from "../stdlib/value.js"
|
||||
import { Values } from "../values.js"
|
||||
import { applyCollectionCallback, isSupportedCallback, type Runner, type SupportedCallback } from "./runner.js"
|
||||
|
||||
@@ -95,7 +94,7 @@ export class PromiseRuntime<R> {
|
||||
}
|
||||
|
||||
export const selfResolutionError = (node?: AstNode): InterpreterRuntimeError =>
|
||||
new InterpreterRuntimeError("Chaining cycle detected: a promise cannot resolve with itself.", node).as("TypeError")
|
||||
new InterpreterRuntimeError("Chaining cycle detected: a promise cannot resolve with itself.", node)
|
||||
|
||||
export const resolvePromiseValue = <R>(
|
||||
runner: Runner<R>,
|
||||
@@ -154,9 +153,7 @@ const invokePromiseMethod = <R>(
|
||||
Effect.gen(function* () {
|
||||
const cursor = yield* runner.syncIterator(args[0], node)
|
||||
if (cursor === undefined) {
|
||||
throw new InterpreterRuntimeError(`Promise.${name} expects an array or other synchronous iterable.`, node).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError(`Promise.${name} expects an array or other synchronous iterable.`, node)
|
||||
}
|
||||
const items: Array<Values.Promise> = []
|
||||
while (true) {
|
||||
@@ -186,7 +183,7 @@ const invokePromiseMethod = <R>(
|
||||
continue
|
||||
}
|
||||
if (Cause.hasInterruptsOnly(exit.cause)) return yield* Effect.failCause(exit.cause)
|
||||
outcomes.push(record({ status: "rejected", reason: caughtErrorValue(Cause.squash(exit.cause)) }))
|
||||
outcomes.push(record({ status: "rejected", reason: caughtErrorValue(runner, Cause.squash(exit.cause)) }))
|
||||
}
|
||||
yield* Effect.yieldNow
|
||||
return new ProgramArray(outcomes)
|
||||
@@ -204,13 +201,13 @@ const invokePromiseMethod = <R>(
|
||||
Effect.flatMap(promises.await(item), (exit) => {
|
||||
if (Exit.isSuccess(exit)) return Effect.fail(new PromiseAnyFulfilled(exit.value))
|
||||
if (Cause.hasInterruptsOnly(exit.cause)) return Effect.failCause(exit.cause)
|
||||
return Effect.succeed(caughtErrorValue(Cause.squash(exit.cause)))
|
||||
return Effect.succeed(caughtErrorValue(runner, Cause.squash(exit.cause)))
|
||||
}),
|
||||
)
|
||||
return yield* settleAfterTurn(
|
||||
Effect.all(flipped, { concurrency: "unbounded" }).pipe(
|
||||
Effect.flatMap((reasons) =>
|
||||
Effect.fail(new ProgramThrow(createAggregateErrorValue(reasons, "All promises were rejected"))),
|
||||
Effect.fail(new ProgramThrow(createAggregateErrorValue(runner, reasons, "All promises were rejected"))),
|
||||
),
|
||||
Effect.catch((error) =>
|
||||
error instanceof PromiseAnyFulfilled ? Effect.succeed(error.value) : Effect.fail(error),
|
||||
@@ -248,7 +245,7 @@ const constructPromise = <R>(
|
||||
throw new InterpreterRuntimeError(
|
||||
"new Promise(...) expects an executor function (e.g. new Promise((resolve, reject) => { ... })).",
|
||||
node,
|
||||
).as("TypeError")
|
||||
)
|
||||
}
|
||||
return Effect.gen(function* () {
|
||||
const deferred = Deferred.makeUnsafe<unknown, unknown>()
|
||||
@@ -311,7 +308,7 @@ const chainReaction = <R>(
|
||||
const exit = yield* reactionExit(promises, source)
|
||||
const handler = Exit.isSuccess(exit) ? onFulfilled : onRejected
|
||||
if (handler === undefined) return yield* exit
|
||||
const input = Exit.isSuccess(exit) ? exit.value : caughtErrorValue(Cause.squash(exit.cause))
|
||||
const input = Exit.isSuccess(exit) ? exit.value : caughtErrorValue(runner, Cause.squash(exit.cause))
|
||||
const result = yield* applyCollectionCallback(runner, handler, method, node)([input])
|
||||
return yield* resolvePromiseValue(runner, result, node, self)
|
||||
}),
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Values } from "../values.js"
|
||||
import { coerceToString } from "../stdlib/value.js"
|
||||
import { HostFunction } from "./host.js"
|
||||
import { type AstNode, InterpreterRuntimeError, IntrinsicReference } from "./model.js"
|
||||
import type { Intrinsics } from "./intrinsics.js"
|
||||
import { get, has, ProgramFunction, ProgramObject } from "./objects.js"
|
||||
import { typeofValue } from "./references.js"
|
||||
|
||||
@@ -11,7 +12,7 @@ export type IteratorCursor<R> = {
|
||||
readonly close: Effect.Effect<void, unknown, R>
|
||||
}
|
||||
|
||||
/** Everything a host function needs to call back into the program. */
|
||||
/** Everything a host function needs from the realm: calling back into the program and its intrinsic objects. */
|
||||
export type Runner<R> = {
|
||||
readonly invokeFunction: (fn: ProgramFunction, args: Array<unknown>) => Effect.Effect<unknown, unknown, R>
|
||||
readonly invokeCallable: (
|
||||
@@ -21,6 +22,7 @@ export type Runner<R> = {
|
||||
) => Effect.Effect<unknown, unknown, R>
|
||||
readonly settlePromise: (promise: Values.Promise) => Effect.Effect<unknown, unknown, never>
|
||||
readonly syncIterator: (value: unknown, node: AstNode) => Effect.Effect<IteratorCursor<R> | undefined, unknown, R>
|
||||
readonly intrinsics: Intrinsics
|
||||
}
|
||||
|
||||
export const preserveConsumerError = <A, R>(
|
||||
@@ -53,7 +55,7 @@ export const toPrimitive = <R>(
|
||||
const result = yield* runner.invokeCallable(callable, [], node)
|
||||
if (result === null || (typeof result !== "object" && typeof result !== "function")) return result
|
||||
}
|
||||
throw new InterpreterRuntimeError("Cannot convert object to primitive value.", node).as("TypeError")
|
||||
throw new InterpreterRuntimeError("Cannot convert object to primitive value.", node)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -81,7 +83,7 @@ export const applyCollectionCallback = <R>(
|
||||
node,
|
||||
)
|
||||
}
|
||||
throw new InterpreterRuntimeError(`${name} expects a function callback.`, node).as("TypeError")
|
||||
throw new InterpreterRuntimeError(`${name} expects a function callback.`, node)
|
||||
}
|
||||
return (callbackArgs) => runner.invokeCallable(callback, callbackArgs, node)
|
||||
}
|
||||
|
||||
@@ -51,19 +51,21 @@ import {
|
||||
CodeModeGenerator,
|
||||
ComputedValue,
|
||||
GeneratorMethodReference,
|
||||
GeneratorReturn,
|
||||
type GeneratorRequestKind,
|
||||
IntrinsicReference,
|
||||
GeneratorReturn,
|
||||
InterpreterRuntimeError,
|
||||
IntrinsicReference,
|
||||
IteratorSymbol,
|
||||
type MemberReference,
|
||||
OptionalShortCircuit,
|
||||
PromiseInstanceMethodReference,
|
||||
ProgramThrow,
|
||||
PromiseInstanceMethodReference,
|
||||
rangeError,
|
||||
type StatementResult,
|
||||
unsupportedSyntax,
|
||||
} from "./model.js"
|
||||
import { caughtErrorValue } from "./errors.js"
|
||||
import { createIntrinsics } from "./intrinsics.js"
|
||||
import { globals, type Host } from "./globals.js"
|
||||
import { HostFunction, HostNamespace } from "./host.js"
|
||||
import { invokeIntrinsic } from "./methods.js"
|
||||
@@ -97,7 +99,7 @@ import { constructRegExp, regexpMethods, regexpProperties } from "../stdlib/rege
|
||||
import { stringMethods } from "../stdlib/string.js"
|
||||
import { uriArgument, urlMethods, urlProperties, urlSearchParamsMethods, urlWritableProperties } from "../stdlib/url.js"
|
||||
import { enumerableSource } from "../stdlib/object.js"
|
||||
import { coerceToNumber, coerceToString, compoundOperators, errorBrandName } from "../stdlib/value.js"
|
||||
import { coerceToNumber, coerceToString, compoundOperators } from "../stdlib/value.js"
|
||||
import { Values } from "../values.js"
|
||||
|
||||
// What a loop does with its body's result: exit with a StatementResult, or undefined to keep iterating.
|
||||
@@ -141,7 +143,7 @@ const constructorName = (value: unknown): string | undefined => {
|
||||
if (value instanceof Values.URLSearchParams) return "URLSearchParams"
|
||||
if (value instanceof Values.Promise) return "Promise"
|
||||
if (!(value instanceof ProgramObject) || value instanceof ProgramFunction) return undefined
|
||||
return errorBrandName(value) ?? "Object"
|
||||
return "Object"
|
||||
}
|
||||
|
||||
const instanceofValue = (lhs: unknown, rhs: unknown, node: AstNode): boolean => {
|
||||
@@ -295,6 +297,7 @@ export class Runtime<R> {
|
||||
invokeCallable: (callable, args, node) => this.root.invokeCallable(callable, args, node),
|
||||
settlePromise: (promise) => this.root.settlePromise(promise),
|
||||
syncIterator: (value, node) => this.root.syncIterator(value, node),
|
||||
intrinsics: createIntrinsics(),
|
||||
}
|
||||
this.builtins = new Map([...globals(this), ...extraGlobals(this)])
|
||||
for (const [name, value] of this.builtins) globalScope.set(name, { mutable: false, value })
|
||||
@@ -647,7 +650,7 @@ class Frame<R> {
|
||||
throw new InterpreterRuntimeError(
|
||||
`${awaiting ? "for await...of" : "for...of"} requires an array, string, Map, Set, or URLSearchParams, or custom iterator value.`,
|
||||
node,
|
||||
).as("TypeError")
|
||||
)
|
||||
}
|
||||
const close = () =>
|
||||
iterator
|
||||
@@ -871,7 +874,7 @@ class Frame<R> {
|
||||
|
||||
private requireIteratorObject(value: unknown, context: string, node: AstNode): ProgramObject {
|
||||
if (value instanceof ProgramObject) return value
|
||||
throw new InterpreterRuntimeError(`${context} must be an object.`, node).as("TypeError")
|
||||
throw new InterpreterRuntimeError(`${context} must be an object.`, node)
|
||||
}
|
||||
|
||||
private requireIterator(value: unknown, node: AstNode): ProgramObject | CodeModeGenerator {
|
||||
@@ -882,7 +885,7 @@ class Frame<R> {
|
||||
|
||||
private requireIteratorMethod(value: unknown, context: string, node: AstNode): unknown {
|
||||
if (typeofValue(value) === "function") return value
|
||||
throw new InterpreterRuntimeError(`${context} must be a function.`, node).as("TypeError")
|
||||
throw new InterpreterRuntimeError(`${context} must be a function.`, node)
|
||||
}
|
||||
|
||||
// for...in over null/undefined iterates nothing, like JS.
|
||||
@@ -994,7 +997,7 @@ class Frame<R> {
|
||||
return Effect.failCause(cause)
|
||||
}
|
||||
|
||||
const caught = caughtErrorValue(Cause.squash(cause))
|
||||
const caught = caughtErrorValue(self.runtime.runner, Cause.squash(cause))
|
||||
const parameter = handler.param
|
||||
self.scopes.push()
|
||||
return Effect.gen(function* () {
|
||||
@@ -1179,9 +1182,7 @@ class Frame<R> {
|
||||
return Effect.gen(function* () {
|
||||
const cursor = yield* self.syncIterator(value, pattern)
|
||||
if (cursor === undefined) {
|
||||
throw new InterpreterRuntimeError("Array destructuring requires a supported iterable value.", pattern).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError("Array destructuring requires a supported iterable value.", pattern)
|
||||
}
|
||||
let done = false
|
||||
for (const element of pattern.elements) {
|
||||
@@ -1314,7 +1315,7 @@ class Frame<R> {
|
||||
: callee instanceof HostFunction
|
||||
? `new ${name}(...) is not supported; call ${name}(...) without new instead.`
|
||||
: `${name} is not a constructor.`
|
||||
throw new InterpreterRuntimeError(message, node).as("TypeError")
|
||||
throw new InterpreterRuntimeError(message, node)
|
||||
}
|
||||
const args = yield* self.evaluateCallArguments(node.arguments)
|
||||
return yield* construct(args, node)
|
||||
@@ -1609,9 +1610,7 @@ class Frame<R> {
|
||||
}
|
||||
if (callable instanceof HostFunction) return yield* (callable as HostFunction<R>).call(args, node)
|
||||
if (callable === undefined || callable === null) {
|
||||
throw new InterpreterRuntimeError(`${calleeDescription(callee)} is not a function.`, callee ?? node).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError(`${calleeDescription(callee)} is not a function.`, callee ?? node)
|
||||
}
|
||||
throw new InterpreterRuntimeError("Only tools are callable here.", callee ?? node)
|
||||
})
|
||||
@@ -1628,9 +1627,7 @@ class Frame<R> {
|
||||
const spread = yield* self.evaluateExpression(argNode.argument)
|
||||
const cursor = yield* self.syncIterator(spread, argNode)
|
||||
if (cursor === undefined)
|
||||
throw new InterpreterRuntimeError("Spread arguments require a synchronous iterable.", argNode).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError("Spread arguments require a synchronous iterable.", argNode)
|
||||
while (true) {
|
||||
const step = yield* cursor.next
|
||||
if (step.done) break
|
||||
@@ -1695,7 +1692,7 @@ class Frame<R> {
|
||||
const generator = new CodeModeGenerator(asynchronous, (kind, value, node) => {
|
||||
const request = { kind, value, response: Deferred.makeUnsafe<unknown, unknown>() }
|
||||
if (!asynchronous && state.active) {
|
||||
return Effect.fail(new InterpreterRuntimeError("Generator is already running.", node).as("TypeError"))
|
||||
return Effect.fail(new InterpreterRuntimeError("Generator is already running.", node))
|
||||
}
|
||||
if (asynchronous && (state.completed || (!state.started && kind !== "next"))) {
|
||||
state.started = true
|
||||
@@ -1865,17 +1862,14 @@ class Frame<R> {
|
||||
}
|
||||
if (error instanceof ProgramThrow) {
|
||||
yield* cursor.close
|
||||
throw new InterpreterRuntimeError("The delegated iterator does not provide a throw() method.", node).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError("The delegated iterator does not provide a throw() method.", node)
|
||||
}
|
||||
return yield* Effect.failCause(resumed.cause)
|
||||
}
|
||||
}
|
||||
|
||||
const iterator = yield* self.customIterator(value, node, self.generatorAsync)
|
||||
if (!iterator)
|
||||
throw new InterpreterRuntimeError("yield* requires a compatible iterable value.", node).as("TypeError")
|
||||
if (!iterator) throw new InterpreterRuntimeError("yield* requires a compatible iterable value.", node)
|
||||
let kind: GeneratorRequestKind = "next"
|
||||
let input: unknown = undefined
|
||||
while (true) {
|
||||
@@ -1888,9 +1882,7 @@ class Frame<R> {
|
||||
if (method === undefined || method === null) {
|
||||
if (kind === "return") return yield* Effect.fail(new GeneratorReturn(input))
|
||||
yield* self.closeIterator(iterator, node, self.generatorAsync)
|
||||
throw new InterpreterRuntimeError("The delegated iterator does not provide a throw() method.", node).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError("The delegated iterator does not provide a throw() method.", node)
|
||||
}
|
||||
const called = yield* self.invokeCallable(
|
||||
self.requireIteratorMethod(method, `Iterator ${kind}`, node),
|
||||
@@ -1986,7 +1978,7 @@ class Frame<R> {
|
||||
const spread = yield* self.evaluateExpression(element.argument)
|
||||
const cursor = yield* self.syncIterator(spread, element)
|
||||
if (cursor === undefined)
|
||||
throw new InterpreterRuntimeError("Array spread requires a synchronous iterable.", element).as("TypeError")
|
||||
throw new InterpreterRuntimeError("Array spread requires a synchronous iterable.", element)
|
||||
while (true) {
|
||||
const step = yield* cursor.next
|
||||
if (step.done) break
|
||||
@@ -2262,7 +2254,7 @@ class Frame<R> {
|
||||
if (reference.target instanceof Values.URL) {
|
||||
const property = key as string
|
||||
if (!urlWritableProperties.has(property)) {
|
||||
throw new InterpreterRuntimeError(`URL.${property} is read-only.`, node).as("TypeError")
|
||||
throw new InterpreterRuntimeError(`URL.${property} is read-only.`, node)
|
||||
}
|
||||
try {
|
||||
const url = reference.target.url as unknown as Record<string, string>
|
||||
@@ -2270,7 +2262,7 @@ class Frame<R> {
|
||||
return
|
||||
} catch (error) {
|
||||
if (error instanceof InterpreterRuntimeError || error instanceof ToolRuntimeError) throw error
|
||||
throw new InterpreterRuntimeError(`URL.${property} received an invalid value.`, node).as("TypeError")
|
||||
throw new InterpreterRuntimeError(`URL.${property} received an invalid value.`, node)
|
||||
}
|
||||
}
|
||||
if (reference.target instanceof Values.RegExp) {
|
||||
@@ -2285,8 +2277,8 @@ class Frame<R> {
|
||||
node,
|
||||
)
|
||||
if (set(target, key, next)) return
|
||||
if (target instanceof ProgramArray) throw new InterpreterRuntimeError("Invalid array length", node).as("RangeError")
|
||||
throw new InterpreterRuntimeError(`Cannot assign to read only property '${String(key)}'.`, node).as("TypeError")
|
||||
if (target instanceof ProgramArray) throw rangeError("Invalid array length", node)
|
||||
throw new InterpreterRuntimeError(`Cannot assign to read only property '${String(key)}'.`, node)
|
||||
}
|
||||
|
||||
private toPropertyKey(value: unknown, node: AstNode): PropertyKey {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { type AstNode, type Binding, InterpreterRuntimeError } from "./model.js"
|
||||
import { type AstNode, type Binding, InterpreterRuntimeError, referenceError } from "./model.js"
|
||||
|
||||
export class ScopeStack {
|
||||
private readonly scopes: Array<Map<string, Binding>>
|
||||
@@ -36,11 +36,11 @@ export class ScopeStack {
|
||||
const binding = this.resolve(name)
|
||||
|
||||
if (!binding) {
|
||||
throw new InterpreterRuntimeError(`Unknown identifier '${name}'.`, node).as("ReferenceError")
|
||||
throw referenceError(`Unknown identifier '${name}'.`, node)
|
||||
}
|
||||
|
||||
if (binding.initialized === false) {
|
||||
throw new InterpreterRuntimeError(`Cannot access '${name}' before initialization.`, node).as("ReferenceError")
|
||||
throw referenceError(`Cannot access '${name}' before initialization.`, node)
|
||||
}
|
||||
|
||||
return binding.value
|
||||
@@ -50,15 +50,15 @@ export class ScopeStack {
|
||||
const binding = this.resolve(name)
|
||||
|
||||
if (!binding) {
|
||||
throw new InterpreterRuntimeError(`Unknown identifier '${name}'.`, node).as("ReferenceError")
|
||||
throw referenceError(`Unknown identifier '${name}'.`, node)
|
||||
}
|
||||
|
||||
if (binding.initialized === false) {
|
||||
throw new InterpreterRuntimeError(`Cannot access '${name}' before initialization.`, node).as("ReferenceError")
|
||||
throw referenceError(`Cannot access '${name}' before initialization.`, node)
|
||||
}
|
||||
|
||||
if (!binding.mutable) {
|
||||
throw new InterpreterRuntimeError(`Cannot assign to constant '${name}'.`, node).as("TypeError")
|
||||
throw new InterpreterRuntimeError(`Cannot assign to constant '${name}'.`, node)
|
||||
}
|
||||
|
||||
binding.value = value
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Effect } from "effect"
|
||||
import { HostFunction, sync, syncCall } from "../interpreter/host.js"
|
||||
import { type AstNode, CodeModeGenerator, InterpreterRuntimeError } from "../interpreter/model.js"
|
||||
import { type AstNode, CodeModeGenerator, InterpreterRuntimeError, rangeError } from "../interpreter/model.js"
|
||||
import { get, ProgramArray, ProgramObject } from "../interpreter/objects.js"
|
||||
import { describeValue } from "../interpreter/references.js"
|
||||
import { applyCollectionCallback, preserveConsumerError, type Runner } from "../interpreter/runner.js"
|
||||
@@ -10,7 +10,7 @@ const constructArray = (args: Array<unknown>, node: AstNode): ProgramArray => {
|
||||
const first = args[0]
|
||||
if (typeof first !== "number") return new ProgramArray([first])
|
||||
if (!Number.isInteger(first) || first < 0 || first > 4294967295) {
|
||||
throw new InterpreterRuntimeError("Invalid array length.", node).as("RangeError")
|
||||
throw rangeError("Invalid array length.", node)
|
||||
}
|
||||
// Sparse like JS: Array(3) has holes, and combinator loops already skip them.
|
||||
return new ProgramArray(new Array(first))
|
||||
@@ -41,9 +41,7 @@ const arrayFrom = <R>(runner: Runner<R>, args: Array<unknown>, node: AstNode): E
|
||||
const cursor = yield* runner.syncIterator(source, node)
|
||||
if (cursor === undefined) {
|
||||
if (source instanceof CodeModeGenerator) {
|
||||
throw new InterpreterRuntimeError("Array.from expects a synchronous iterable or array-like value.", node).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError("Array.from expects a synchronous iterable or array-like value.", node)
|
||||
}
|
||||
const arrayLike = arrayLikeSource(source, node)
|
||||
const values: Array<unknown> = []
|
||||
|
||||
@@ -89,15 +89,13 @@ export const groupBy = <R>(runner: Runner<R>, namespace: "Map" | "Object") =>
|
||||
call: (args, node) => {
|
||||
const source = args[0]
|
||||
if (source === null || source === undefined) {
|
||||
throw new InterpreterRuntimeError(`${namespace}.groupBy expects an iterable collection.`, node).as("TypeError")
|
||||
throw new InterpreterRuntimeError(`${namespace}.groupBy expects an iterable collection.`, node)
|
||||
}
|
||||
const apply = applyCollectionCallback(runner, args[1], `${namespace}.groupBy`, node)
|
||||
return Effect.gen(function* () {
|
||||
const cursor = yield* runner.syncIterator(source, node)
|
||||
if (cursor === undefined) {
|
||||
throw new InterpreterRuntimeError(`${namespace}.groupBy expects an iterable collection.`, node).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError(`${namespace}.groupBy expects an iterable collection.`, node)
|
||||
}
|
||||
if (namespace === "Map") {
|
||||
const result = new Values.Map()
|
||||
@@ -139,10 +137,7 @@ const constructMap = <R>(runner: Runner<R>, init: unknown, node: AstNode) => {
|
||||
return Effect.gen(function* () {
|
||||
const cursor = yield* runner.syncIterator(init, node)
|
||||
if (cursor === undefined) {
|
||||
throw new InterpreterRuntimeError(
|
||||
"new Map(...) expects an iterable of [key, value] pairs or no argument.",
|
||||
node,
|
||||
).as("TypeError")
|
||||
throw new InterpreterRuntimeError("new Map(...) expects an iterable of [key, value] pairs or no argument.", node)
|
||||
}
|
||||
while (true) {
|
||||
const step = yield* cursor.next
|
||||
@@ -151,9 +146,7 @@ const constructMap = <R>(runner: Runner<R>, init: unknown, node: AstNode) => {
|
||||
cursor,
|
||||
Effect.sync(() => {
|
||||
if (!(step.value instanceof ProgramObject)) {
|
||||
throw new InterpreterRuntimeError("new Map(...) expects [key, value] pairs as entry objects.", node).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError("new Map(...) expects [key, value] pairs as entry objects.", node)
|
||||
}
|
||||
target.map.set(getOwn(step.value, 0), getOwn(step.value, 1))
|
||||
}),
|
||||
@@ -168,9 +161,7 @@ const constructSet = <R>(runner: Runner<R>, init: unknown, node: AstNode) => {
|
||||
return Effect.gen(function* () {
|
||||
const cursor = yield* runner.syncIterator(init, node)
|
||||
if (cursor === undefined) {
|
||||
throw new InterpreterRuntimeError("new Set(...) expects a synchronous iterable or no argument.", node).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError("new Set(...) expects a synchronous iterable or no argument.", node)
|
||||
}
|
||||
while (true) {
|
||||
const step = yield* cursor.next
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Effect } from "effect"
|
||||
import { HostFunction, sync } from "../interpreter/host.js"
|
||||
import { type AstNode, InterpreterRuntimeError } from "../interpreter/model.js"
|
||||
import { type AstNode, InterpreterRuntimeError, rangeError } from "../interpreter/model.js"
|
||||
import { type Runner, toPrimitive } from "../interpreter/runner.js"
|
||||
import { Values } from "../values.js"
|
||||
import { coerceToNumber, coerceToString } from "./value.js"
|
||||
@@ -99,7 +99,7 @@ export const invokeDateMethod = (
|
||||
case "valueOf":
|
||||
return value.time
|
||||
case "toISOString":
|
||||
if (!Number.isFinite(value.time)) throw new InterpreterRuntimeError("Invalid time value.", node).as("RangeError")
|
||||
if (!Number.isFinite(value.time)) throw rangeError("Invalid time value.", node)
|
||||
return hosted.toISOString()
|
||||
case "toJSON":
|
||||
return Number.isFinite(value.time) ? hosted.toISOString() : null
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Effect } from "effect"
|
||||
import { HostFunction, HostNamespace } from "../interpreter/host.js"
|
||||
import { applyCollectionCallback, type Runner } from "../interpreter/runner.js"
|
||||
import { type AstNode, InterpreterRuntimeError } from "../interpreter/model.js"
|
||||
import { type AstNode, InterpreterRuntimeError, syntaxError } from "../interpreter/model.js"
|
||||
import { typeofValue } from "../interpreter/references.js"
|
||||
import { fromData, toData, toProgram } from "../data.js"
|
||||
import { get, ownKeys, ProgramArray, ProgramObject, record, remove, set } from "../interpreter/objects.js"
|
||||
@@ -21,10 +21,10 @@ const parse = <R>(runner: Runner<R>, args: Array<unknown>, node: AstNode): Effec
|
||||
try {
|
||||
return fromData(JSON.parse(text), "JSON.parse result")
|
||||
} catch (error) {
|
||||
throw new InterpreterRuntimeError(
|
||||
throw syntaxError(
|
||||
`JSON.parse received invalid JSON: ${error instanceof Error ? error.message : String(error)}`,
|
||||
node,
|
||||
).as("SyntaxError")
|
||||
)
|
||||
}
|
||||
})()
|
||||
if (typeofValue(args[1]) !== "function") return Effect.succeed(parsed)
|
||||
@@ -72,8 +72,7 @@ const stringify = <R>(runner: Runner<R>, args: Array<unknown>, node: AstNode): E
|
||||
if (typeof value === "number") return Number.isFinite(value) ? value : null
|
||||
if (value === null || typeof value === "string" || typeof value === "boolean") return value
|
||||
if (!(value instanceof ProgramObject)) return {}
|
||||
if (stack.has(value))
|
||||
throw new InterpreterRuntimeError("Converting circular structure to JSON.", node).as("TypeError")
|
||||
if (stack.has(value)) throw new InterpreterRuntimeError("Converting circular structure to JSON.", node)
|
||||
stack.add(value)
|
||||
if (value instanceof ProgramArray) {
|
||||
const result: Array<unknown> = []
|
||||
|
||||
@@ -42,7 +42,7 @@ const sumPrecise = <R>(runner: Runner<R>) =>
|
||||
Effect.gen(function* () {
|
||||
const cursor = yield* runner.syncIterator(args[0], node)
|
||||
if (cursor === undefined) {
|
||||
throw new InterpreterRuntimeError("Math.sumPrecise expects a synchronous iterable.", node).as("TypeError")
|
||||
throw new InterpreterRuntimeError("Math.sumPrecise expects a synchronous iterable.", node)
|
||||
}
|
||||
const numbers: Array<number> = []
|
||||
while (true) {
|
||||
@@ -52,9 +52,7 @@ const sumPrecise = <R>(runner: Runner<R>) =>
|
||||
cursor,
|
||||
Effect.sync(() => {
|
||||
if (typeof step.value !== "number") {
|
||||
throw new InterpreterRuntimeError("Math.sumPrecise expects an iterable of numbers.", node).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError("Math.sumPrecise expects an iterable of numbers.", node)
|
||||
}
|
||||
numbers.push(step.value)
|
||||
}),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { toProgram } from "../data.js"
|
||||
import { sync } from "../interpreter/host.js"
|
||||
import { type AstNode, InterpreterRuntimeError } from "../interpreter/model.js"
|
||||
import { type AstNode, InterpreterRuntimeError, rangeError } from "../interpreter/model.js"
|
||||
import { coercion, coerceToString } from "./value.js"
|
||||
|
||||
export const numberMethods = new Set(["toFixed", "toPrecision", "toExponential", "toString", "valueOf"])
|
||||
@@ -28,7 +28,7 @@ export const invokeNumberMethod = (value: number, name: string, args: Array<unkn
|
||||
case "toString": {
|
||||
const radix = optNum(0)
|
||||
if (radix !== undefined && (radix < 2 || radix > 36)) {
|
||||
throw new InterpreterRuntimeError("Number.toString radix must be between 2 and 36.", node)
|
||||
throw rangeError("Number.toString radix must be between 2 and 36.", node)
|
||||
}
|
||||
result = value.toString(radix)
|
||||
break
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import { Effect } from "effect"
|
||||
import { toProgram } from "../data.js"
|
||||
import { HostFunction, sync, syncCall } from "../interpreter/host.js"
|
||||
import { type AstNode, AsyncIteratorSymbol, InterpreterRuntimeError, IteratorSymbol } from "../interpreter/model.js"
|
||||
import {
|
||||
type AstNode,
|
||||
AsyncIteratorSymbol,
|
||||
InterpreterRuntimeError,
|
||||
IteratorSymbol,
|
||||
rangeError,
|
||||
} from "../interpreter/model.js"
|
||||
import { getOwn, hasOwn, ownEntries, ownKeys, ProgramArray, ProgramObject, set } from "../interpreter/objects.js"
|
||||
import {
|
||||
containsOpaqueReference,
|
||||
@@ -18,9 +24,7 @@ import { coerceToString } from "./value.js"
|
||||
// ToObject for enumeration.
|
||||
export const enumerableSource = (label: string, value: unknown, node: AstNode): ProgramObject => {
|
||||
if (value === null || value === undefined) {
|
||||
throw new InterpreterRuntimeError(`${label} cannot convert ${describeValue(value)} to an object.`, node).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError(`${label} cannot convert ${describeValue(value)} to an object.`, node)
|
||||
}
|
||||
if (value instanceof Values.Promise) {
|
||||
throw new InterpreterRuntimeError(
|
||||
@@ -48,7 +52,7 @@ export const objectAssign = (args: Array<unknown>, node: AstNode): unknown => {
|
||||
throw new InterpreterRuntimeError(
|
||||
`Object.assign expects a data object or array target, received ${describeValue(target)}.`,
|
||||
node,
|
||||
).as("TypeError")
|
||||
)
|
||||
}
|
||||
const seen = new Set<object>()
|
||||
for (const source of args.slice(1)) {
|
||||
@@ -58,7 +62,7 @@ export const objectAssign = (args: Array<unknown>, node: AstNode): unknown => {
|
||||
if (typeof key === "symbol" && key !== AsyncIteratorSymbol && key !== IteratorSymbol) continue
|
||||
rejectCircularInsertion(target, getOwn(from, key), "Object.assign result", node, seen)
|
||||
if (!set(target, key, getOwn(from, key))) {
|
||||
throw new InterpreterRuntimeError("Invalid array length", node).as("RangeError")
|
||||
throw rangeError("Invalid array length", node)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,9 +78,7 @@ const objectFromEntries = <R>(
|
||||
return Effect.gen(function* () {
|
||||
const cursor = yield* runner.syncIterator(source, node)
|
||||
if (cursor === undefined) {
|
||||
throw new InterpreterRuntimeError("Object.fromEntries expects a synchronous iterable of entries.", node).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError("Object.fromEntries expects a synchronous iterable of entries.", node)
|
||||
}
|
||||
while (true) {
|
||||
const step = yield* cursor.next
|
||||
@@ -85,9 +87,7 @@ const objectFromEntries = <R>(
|
||||
cursor,
|
||||
Effect.sync(() => {
|
||||
if (!(step.value instanceof ProgramObject) || containsOpaqueReference(step.value)) {
|
||||
throw new InterpreterRuntimeError("Object.fromEntries expects [key, value] entry objects.", node).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError("Object.fromEntries expects [key, value] entry objects.", node)
|
||||
}
|
||||
set(out, coerceToString(getOwn(step.value, 0)), getOwn(step.value, 1))
|
||||
}),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { sync, syncCall } from "../interpreter/host.js"
|
||||
import { type AstNode, InterpreterRuntimeError } from "../interpreter/model.js"
|
||||
import { type AstNode, InterpreterRuntimeError, syntaxError } from "../interpreter/model.js"
|
||||
import { ProgramArray, record, set } from "../interpreter/objects.js"
|
||||
import { Values } from "../values.js"
|
||||
import { coerceToNumber, coerceToString } from "./value.js"
|
||||
@@ -34,10 +34,10 @@ export const toHostRegex = (arg: unknown, method: string, node: AstNode, extraFl
|
||||
try {
|
||||
return new RegExp(arg, extraFlags)
|
||||
} catch (error) {
|
||||
throw new InterpreterRuntimeError(
|
||||
throw syntaxError(
|
||||
`String.${method} received the string ${JSON.stringify(arg)}, which is not a valid regular expression pattern (${regexFailureReason(error)}). ${escapeRegexHint}`,
|
||||
node,
|
||||
).as("SyntaxError")
|
||||
)
|
||||
}
|
||||
}
|
||||
throw new InterpreterRuntimeError(
|
||||
@@ -60,22 +60,22 @@ export const constructRegExp = (args: Array<unknown>, node: AstNode): Values.Reg
|
||||
const pattern = first instanceof Values.RegExp ? first.regex.source : first === undefined ? "" : coerceToString(first)
|
||||
const flagsArg = args[1]
|
||||
if (flagsArg !== undefined && typeof flagsArg !== "string") {
|
||||
throw new InterpreterRuntimeError(
|
||||
throw syntaxError(
|
||||
`RegExp flags must be a string of flag characters (e.g. "g", "gi"), not ${flagsArg === null ? "null" : typeof flagsArg}.`,
|
||||
node,
|
||||
).as("SyntaxError")
|
||||
)
|
||||
}
|
||||
const flags = flagsArg ?? (first instanceof Values.RegExp ? first.regex.flags : "")
|
||||
try {
|
||||
return new Values.RegExp(pattern, flags)
|
||||
} catch (error) {
|
||||
const reason = regexFailureReason(error)
|
||||
throw new InterpreterRuntimeError(
|
||||
throw syntaxError(
|
||||
/flag/i.test(reason)
|
||||
? `new RegExp(...) received invalid flags ${JSON.stringify(flags)} (${reason}). Valid flags are d, g, i, m, s, u, v, and y.`
|
||||
: `new RegExp(...) received ${JSON.stringify(pattern)}, which is not a valid regular expression pattern (${reason}). ${escapeRegexHint}`,
|
||||
node,
|
||||
).as("SyntaxError")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ export const regexpGlobal = sync("RegExp", constructRegExp, {
|
||||
members: {
|
||||
escape: sync("RegExp.escape", (args, node) => {
|
||||
if (typeof args[0] !== "string") {
|
||||
throw new InterpreterRuntimeError("RegExp.escape expects a string.", node).as("TypeError")
|
||||
throw new InterpreterRuntimeError("RegExp.escape expects a string.", node)
|
||||
}
|
||||
return RegExp.escape(args[0])
|
||||
}),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Effect } from "effect"
|
||||
import { toProgram } from "../data.js"
|
||||
import { HostFunction, requiresNew, sync, syncCall } from "../interpreter/host.js"
|
||||
import { type AstNode, InterpreterRuntimeError } from "../interpreter/model.js"
|
||||
import { type AstNode, InterpreterRuntimeError, uriError } from "../interpreter/model.js"
|
||||
import { ownEntries, ProgramObject } from "../interpreter/objects.js"
|
||||
import { isRuntimeReference } from "../interpreter/references.js"
|
||||
import { preserveConsumerError, type Runner } from "../interpreter/runner.js"
|
||||
@@ -68,10 +68,10 @@ export const uriGlobal = (name: UriFunction) =>
|
||||
try {
|
||||
return uriFunctions[name](value)
|
||||
} catch (error) {
|
||||
throw new InterpreterRuntimeError(
|
||||
throw uriError(
|
||||
`${name} received malformed URI data: ${error instanceof Error ? error.message : String(error)}`,
|
||||
node,
|
||||
).as("URIError")
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -81,7 +81,7 @@ export const urlArgument = (value: unknown, label: string): string =>
|
||||
const urlStatic = (name: "canParse" | "parse") =>
|
||||
sync(`URL.${name}`, (args, node) => {
|
||||
if (args.length === 0) {
|
||||
throw new InterpreterRuntimeError(`URL.${name} requires a URL argument.`, node).as("TypeError")
|
||||
throw new InterpreterRuntimeError(`URL.${name} requires a URL argument.`, node)
|
||||
}
|
||||
const input = urlArgument(args[0], `URL.${name} input`)
|
||||
const base = args[1] === undefined ? undefined : urlArgument(args[1], `URL.${name} base`)
|
||||
@@ -95,9 +95,7 @@ const urlStatic = (name: "canParse" | "parse") =>
|
||||
|
||||
const constructURL = (args: Array<unknown>, node: AstNode): Values.URL => {
|
||||
if (args.length === 0) {
|
||||
throw new InterpreterRuntimeError("new URL(...) requires a URL string and an optional base URL.", node).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError("new URL(...) requires a URL string and an optional base URL.", node)
|
||||
}
|
||||
const input = urlArgument(args[0], "new URL input")
|
||||
const base = args[1] === undefined ? undefined : urlArgument(args[1], "new URL base")
|
||||
@@ -107,7 +105,7 @@ const constructURL = (args: Array<unknown>, node: AstNode): Values.URL => {
|
||||
throw new InterpreterRuntimeError(
|
||||
`new URL(...) received an invalid URL${base === undefined ? "" : " or base URL"}.`,
|
||||
node,
|
||||
).as("TypeError")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,9 +125,7 @@ const readURLSearchParamsPair = <R>(
|
||||
Effect.gen(function* () {
|
||||
const cursor = yield* runner.syncIterator(value, node)
|
||||
if (cursor === undefined) {
|
||||
throw new InterpreterRuntimeError("new URLSearchParams(...) expects iterable [name, value] pairs.", node).as(
|
||||
"TypeError",
|
||||
)
|
||||
throw new InterpreterRuntimeError("new URLSearchParams(...) expects iterable [name, value] pairs.", node)
|
||||
}
|
||||
const items: Array<string> = []
|
||||
while (true) {
|
||||
@@ -165,10 +161,7 @@ const constructURLSearchParams = <R>(
|
||||
const step = yield* cursor.next
|
||||
if (step.done) {
|
||||
if (entries.some((entry) => entry.length !== 2)) {
|
||||
throw new InterpreterRuntimeError(
|
||||
"new URLSearchParams(...) expects iterable [name, value] pairs.",
|
||||
node,
|
||||
).as("TypeError")
|
||||
throw new InterpreterRuntimeError("new URLSearchParams(...) expects iterable [name, value] pairs.", node)
|
||||
}
|
||||
return new Values.URLSearchParams(
|
||||
new URLSearchParams(entries.map((entry): [string, string] => [entry[0] ?? "", entry[1] ?? ""])),
|
||||
@@ -181,14 +174,14 @@ const constructURLSearchParams = <R>(
|
||||
throw new InterpreterRuntimeError(
|
||||
"new URLSearchParams(...) expects a query string, data object, or synchronous iterable pairs.",
|
||||
node,
|
||||
).as("TypeError")
|
||||
)
|
||||
}
|
||||
if (Values.isValue(init)) return new Values.URLSearchParams(new URLSearchParams())
|
||||
if (!(init instanceof ProgramObject)) {
|
||||
throw new InterpreterRuntimeError(
|
||||
"new URLSearchParams(...) expects a query string, data object, iterable pairs, or URLSearchParams.",
|
||||
node,
|
||||
).as("TypeError")
|
||||
)
|
||||
}
|
||||
return new Values.URLSearchParams(
|
||||
new URLSearchParams(Object.fromEntries(ownEntries(init).map(([key, value]) => [key, coerceToString(value)]))),
|
||||
|
||||
@@ -1,38 +1,11 @@
|
||||
import { type HostFunction, sync, type SyncOptions } from "../interpreter/host.js"
|
||||
import { type AstNode, InterpreterRuntimeError } from "../interpreter/model.js"
|
||||
import { toProgram } from "../data.js"
|
||||
import { get, ProgramArray, ProgramError, set } from "../interpreter/objects.js"
|
||||
import { get, ProgramArray, ProgramError } from "../interpreter/objects.js"
|
||||
import { Values } from "../values.js"
|
||||
|
||||
export const errorConstructors = new Set([
|
||||
"Error",
|
||||
"TypeError",
|
||||
"RangeError",
|
||||
"SyntaxError",
|
||||
"ReferenceError",
|
||||
"EvalError",
|
||||
"URIError",
|
||||
"AggregateError",
|
||||
])
|
||||
|
||||
export const compoundOperators = new Set(["+=", "-=", "*=", "/=", "%=", "**=", "&=", "|=", "^=", "<<=", ">>=", ">>>="])
|
||||
|
||||
export const createErrorValue = (name: string, message: string): ProgramError => {
|
||||
const value = new ProgramError(name)
|
||||
set(value, "name", name)
|
||||
set(value, "message", message)
|
||||
return value
|
||||
}
|
||||
|
||||
export const createAggregateErrorValue = (errors: Array<unknown>, message: string): ProgramError => {
|
||||
const value = createErrorValue("AggregateError", message)
|
||||
set(value, "errors", new ProgramArray(errors))
|
||||
return value
|
||||
}
|
||||
|
||||
export const errorBrandName = (value: unknown): string | undefined =>
|
||||
value instanceof ProgramError ? value.errorName : undefined
|
||||
|
||||
export const coerceToString = (value: unknown): string => {
|
||||
if (value === null) return "null"
|
||||
if (value === undefined) return "undefined"
|
||||
|
||||
@@ -2,16 +2,16 @@ import { HostNamespace, sync } from "../interpreter/host.js"
|
||||
import { InterpreterRuntimeError } from "../interpreter/model.js"
|
||||
import { coerceToString } from "./value.js"
|
||||
|
||||
// WebIDL DOMString conversion: a missing argument is a TypeError, anything else stringifies.
|
||||
// WebIDL DOMString conversion: a missing argument is a TypeError, anything else stringifies. Invalid input is a
|
||||
// TypeError as well; browsers throw a DOMException named InvalidCharacterError, which CodeMode does not have.
|
||||
const base64 = (name: "atob" | "btoa") =>
|
||||
sync(name, (args, node) => {
|
||||
if (args.length === 0)
|
||||
throw new InterpreterRuntimeError(`${name} requires 1 argument (a string)`, node).as("TypeError")
|
||||
if (args.length === 0) throw new InterpreterRuntimeError(`${name} requires 1 argument (a string)`, node)
|
||||
const input = coerceToString(args[0])
|
||||
try {
|
||||
return name === "atob" ? atob(input) : btoa(input)
|
||||
} catch {
|
||||
throw new InterpreterRuntimeError("The string contains invalid characters.", node).as("InvalidCharacterError")
|
||||
throw new InterpreterRuntimeError("The string contains invalid characters.", node)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -392,11 +392,35 @@ describe("Error values and instanceof", () => {
|
||||
])
|
||||
})
|
||||
|
||||
test("diagnostics without a specific real-JS analogue are named plain Error", async () => {
|
||||
expect(await value(`try { JSON.parse(5) } catch (e) { return [e.name, e instanceof Error] }`)).toEqual([
|
||||
"Error",
|
||||
test("interpreter failures are TypeErrors; unsupported syntax is a SyntaxError", async () => {
|
||||
expect(await value(`try { null.x } catch (e) { return [e.name, e instanceof TypeError] }`)).toEqual([
|
||||
"TypeError",
|
||||
true,
|
||||
])
|
||||
expect(await value(`try { tools + 1 } catch (e) { return e.name }`)).toBe("TypeError")
|
||||
expect(await value(`try { class A {} } catch (e) { return [e.name, e instanceof SyntaxError] }`)).toEqual([
|
||||
"SyntaxError",
|
||||
true,
|
||||
])
|
||||
})
|
||||
|
||||
test("errors inherit constructor and instanceof through a real prototype chain", async () => {
|
||||
expect(
|
||||
await value(`
|
||||
const { constructor } = new RangeError("r")
|
||||
let caught
|
||||
try { const { a } = null } catch (e) { caught = e }
|
||||
return [
|
||||
constructor === RangeError,
|
||||
new RangeError("r") instanceof Error,
|
||||
new RangeError("r") instanceof TypeError,
|
||||
caught.constructor === TypeError,
|
||||
({ ...caught }).constructor === Object,
|
||||
"constructor" in caught,
|
||||
Object.keys(new RangeError("r")),
|
||||
]
|
||||
`),
|
||||
).toEqual([true, true, false, true, true, true, ["message"]])
|
||||
})
|
||||
|
||||
test("Promise.allSettled rejection reasons are Error values", async () => {
|
||||
@@ -421,15 +445,19 @@ describe("Error values and instanceof", () => {
|
||||
])
|
||||
})
|
||||
|
||||
test("error values still serialize as plain { name, message } data", async () => {
|
||||
test("errors serialize as { name, message } by brand; name is inherited and message is own", async () => {
|
||||
expect(await value(`return new Error("m")`)).toEqual({ name: "Error", message: "m" })
|
||||
expect(await value(`return JSON.stringify(new Error("m"))`)).toBe('{"name":"Error","message":"m"}')
|
||||
expect(await value(`try { throw new Error("m") } catch (e) { return Object.keys(e) }`)).toEqual(["name", "message"])
|
||||
expect(await value(`try { throw new Error("m") } catch (e) { return [Object.keys(e), e.name] }`)).toEqual([
|
||||
["message"],
|
||||
"Error",
|
||||
])
|
||||
expect(await value(`return Object.keys(new Error())`)).toEqual([])
|
||||
})
|
||||
|
||||
test("spreading an error loses the brand, like losing the prototype in JS", async () => {
|
||||
expect(await value(`const e = new Error("m"); return ({ ...e }) instanceof Error`)).toBe(false)
|
||||
expect(await value(`const e = new Error("m"); return { ...e }`)).toEqual({ name: "Error", message: "m" })
|
||||
expect(await value(`const e = new Error("m"); return { ...e }`)).toEqual({ message: "m" })
|
||||
})
|
||||
|
||||
test("typeof Error is function; an unknown instanceof right-hand side is a catchable error", async () => {
|
||||
|
||||
@@ -8,8 +8,8 @@ import { executeProgram } from "../../src/interpreter/execute.js"
|
||||
import type { Host } from "../../src/interpreter/globals.js"
|
||||
import { HostFunction } from "../../src/interpreter/host.js"
|
||||
import { ProgramThrow } from "../../src/interpreter/model.js"
|
||||
import { get, ProgramArray, ProgramObject } from "../../src/interpreter/objects.js"
|
||||
import { createErrorValue, errorBrandName } from "../../src/stdlib/value.js"
|
||||
import { createErrorValue } from "../../src/interpreter/intrinsics.js"
|
||||
import { get, hasPrototype, ProgramArray, ProgramObject, set } from "../../src/interpreter/objects.js"
|
||||
import { ToolRuntime } from "../../src/tool-runtime.js"
|
||||
|
||||
export const root = import.meta.dir
|
||||
@@ -65,7 +65,11 @@ export const run = async (file: string): Promise<Outcome> => {
|
||||
}
|
||||
|
||||
const harness = <R>(host: Host<R>, onDone: (error: unknown) => void): ReadonlyArray<readonly [string, unknown]> => {
|
||||
const fail = (message: string) => Effect.fail(new ProgramThrow(createErrorValue("Test262Error", message)))
|
||||
const test262Prototype = new ProgramObject()
|
||||
set(test262Prototype, "name", "Test262Error")
|
||||
const test262 = (args: Array<unknown>) =>
|
||||
createErrorValue(test262Prototype, args[0] === undefined ? "" : String(args[0]))
|
||||
const fail = (message: string) => Effect.fail(new ProgramThrow(test262([message])))
|
||||
const prefix = (message: unknown) => (message === undefined ? "" : `${String(message)} `)
|
||||
const compare = (a: unknown, b: unknown) =>
|
||||
a instanceof ProgramArray &&
|
||||
@@ -74,11 +78,12 @@ const harness = <R>(host: Host<R>, onDone: (error: unknown) => void): ReadonlyAr
|
||||
a.items.every((value, i) => Object.is(value, b.items[i]))
|
||||
const test262Error = new HostFunction<R>({
|
||||
name: "Test262Error",
|
||||
call: (args) => Effect.succeed(createErrorValue("Test262Error", args[0] === undefined ? "" : String(args[0]))),
|
||||
construct: (args) => Effect.succeed(createErrorValue("Test262Error", args[0] === undefined ? "" : String(args[0]))),
|
||||
instanceOf: (value) => errorBrandName(value) === "Test262Error",
|
||||
call: (args) => Effect.succeed(test262(args)),
|
||||
construct: (args) => Effect.succeed(test262(args)),
|
||||
instanceOf: (value) => hasPrototype(value, test262Prototype),
|
||||
members: { thrower: new HostFunction<R>({ name: "Test262Error.thrower", call: (args) => fail(String(args[0])) }) },
|
||||
})
|
||||
set(test262Prototype, "constructor", test262Error)
|
||||
const compareArray = new HostFunction<R>({
|
||||
name: "compareArray",
|
||||
call: (args) => Effect.succeed(compare(args[0], args[1])),
|
||||
@@ -124,13 +129,11 @@ const harness = <R>(host: Host<R>, onDone: (error: unknown) => void): ReadonlyAr
|
||||
Effect.matchCauseEffect({
|
||||
onFailure: (cause) => {
|
||||
if (cause.reasons.some(Cause.isInterruptReason)) return Effect.failCause(cause)
|
||||
const thrown = caughtErrorValue(Cause.squash(cause))
|
||||
if (thrown === null || typeof thrown !== "object") {
|
||||
return fail(`${prefix(args[2])}Thrown value was not an object!`)
|
||||
}
|
||||
const actual = errorBrandName(thrown)
|
||||
if (actual === expected) return Effect.void
|
||||
return fail(`${prefix(args[2])}Expected a ${expected} but got a ${actual ?? "non-error object"}`)
|
||||
const thrown = caughtErrorValue(host.runner, Cause.squash(cause))
|
||||
if (!(thrown instanceof ProgramObject)) return fail(`${prefix(args[2])}Thrown value was not an object!`)
|
||||
const actual = get(thrown, "constructor")
|
||||
if (actual === args[0]) return Effect.void
|
||||
return fail(`${prefix(args[2])}Expected a ${expected} but got a ${show(actual)}`)
|
||||
},
|
||||
onSuccess: () =>
|
||||
fail(`${prefix(args[2])}Expected a ${expected} to be thrown but no exception was thrown at all`),
|
||||
@@ -162,5 +165,5 @@ const show = (value: unknown): string => {
|
||||
if (value instanceof HostFunction) return value.name
|
||||
if (!(value instanceof ProgramObject)) return String(value)
|
||||
const message = get(value, "message")
|
||||
return typeof message === "string" ? `${errorBrandName(value) ?? "object"}: ${message}` : "object"
|
||||
return typeof message === "string" ? `${String(get(value, "name") ?? "object")}: ${message}` : "object"
|
||||
}
|
||||
|
||||
@@ -4,23 +4,23 @@ built-ins/Array/prototype/copyWithin/coerced-values-start-change-target.js # Ar
|
||||
built-ins/Array/prototype/copyWithin/coerced-values-start.js # Array.copyWithin expects start to be a number.
|
||||
built-ins/Array/prototype/copyWithin/coerced-values-target.js # Array.copyWithin expects target index to be a number.
|
||||
built-ins/Array/prototype/copyWithin/fill-holes.js # .hasOwnProperty is not a function.
|
||||
built-ins/Array/prototype/copyWithin/return-abrupt-from-end.js # Expected a Test262Error but got a Error
|
||||
built-ins/Array/prototype/copyWithin/return-abrupt-from-start.js # Expected a Test262Error but got a Error
|
||||
built-ins/Array/prototype/copyWithin/return-abrupt-from-target.js # Expected a Test262Error but got a Error
|
||||
built-ins/Array/prototype/copyWithin/return-abrupt-from-end.js # Expected a Test262Error but got a TypeError
|
||||
built-ins/Array/prototype/copyWithin/return-abrupt-from-start.js # Expected a Test262Error but got a TypeError
|
||||
built-ins/Array/prototype/copyWithin/return-abrupt-from-target.js # Expected a Test262Error but got a TypeError
|
||||
built-ins/Array/prototype/entries/iteration-mutable.js # .next is not a function.
|
||||
built-ins/Array/prototype/entries/iteration.js # .next is not a function.
|
||||
built-ins/Array/prototype/every/15.4.4.16-7-7.js # .hasOwnProperty is not a function.
|
||||
built-ins/Array/prototype/every/15.4.4.16-8-13.js # Property key must be a string or number, or Symbol.asyncIterator/Symbol.iterator.
|
||||
built-ins/Array/prototype/fill/coerced-indexes.js # Array.fill expects start to be a number.
|
||||
built-ins/Array/prototype/fill/return-abrupt-from-end.js # Expected a Test262Error but got a Error
|
||||
built-ins/Array/prototype/fill/return-abrupt-from-start.js # Expected a Test262Error but got a Error
|
||||
built-ins/Array/prototype/fill/return-abrupt-from-end.js # Expected a Test262Error but got a TypeError
|
||||
built-ins/Array/prototype/fill/return-abrupt-from-start.js # Expected a Test262Error but got a TypeError
|
||||
built-ins/Array/prototype/filter/15.4.4.20-10-4.js # Property key must be a string or number, or Symbol.asyncIterator/Symbol.iterator.
|
||||
built-ins/Array/prototype/filter/create-ctor-non-object.js # null value Expected a TypeError to be thrown but no exception was thrown at all
|
||||
built-ins/Array/prototype/flat/non-numeric-depth-should-not-throw.js # Array.flat expects depth to be a number.
|
||||
built-ins/Array/prototype/forEach/15.4.4.18-8-12.js # Property key must be a string or number, or Symbol.asyncIterator/Symbol.iterator.
|
||||
built-ins/Array/prototype/includes/length-zero-returns-false.js # Array.includes expects a value and optional start index.
|
||||
built-ins/Array/prototype/includes/no-arg.js # Array.includes expects a value and optional start index.
|
||||
built-ins/Array/prototype/includes/return-abrupt-tointeger-fromindex.js # Expected a Test262Error but got a Error
|
||||
built-ins/Array/prototype/includes/return-abrupt-tointeger-fromindex.js # Expected a Test262Error but got a TypeError
|
||||
built-ins/Array/prototype/includes/tointeger-fromindex.js # Array.includes expects start index to be a number.
|
||||
built-ins/Array/prototype/indexOf/15.4.4.14-5-1.js # Array.indexOf expects start index to be a number.
|
||||
built-ins/Array/prototype/indexOf/15.4.4.14-5-15.js # Array.indexOf expects start index to be a number.
|
||||
@@ -32,7 +32,7 @@ built-ins/Array/prototype/indexOf/15.4.4.14-5-20.js # Array.indexOf expects sta
|
||||
built-ins/Array/prototype/indexOf/15.4.4.14-5-21.js # Array.indexOf expects start index to be a number.
|
||||
built-ins/Array/prototype/indexOf/15.4.4.14-5-22.js # Array.indexOf expects start index to be a number.
|
||||
built-ins/Array/prototype/indexOf/15.4.4.14-5-23.js # Array.indexOf expects start index to be a number.
|
||||
built-ins/Array/prototype/indexOf/15.4.4.14-5-24.js # Expected a TypeError but got a Error
|
||||
built-ins/Array/prototype/indexOf/15.4.4.14-5-24.js # toStringAccessed
|
||||
built-ins/Array/prototype/indexOf/15.4.4.14-5-3.js # Array.indexOf expects start index to be a number.
|
||||
built-ins/Array/prototype/indexOf/15.4.4.14-5-5.js # Array.indexOf expects start index to be a number.
|
||||
built-ins/Array/prototype/indexOf/15.4.4.14-9-7.js # Array assignment result contains a circular value.
|
||||
@@ -56,7 +56,7 @@ built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-20.js # Array.lastIndexOf exp
|
||||
built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-21.js # Array.lastIndexOf expects start index to be a number.
|
||||
built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-22.js # Array.lastIndexOf expects start index to be a number.
|
||||
built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-23.js # Array.lastIndexOf expects start index to be a number.
|
||||
built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-24.js # Expected a TypeError but got a Error
|
||||
built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-24.js # toStringAccessed
|
||||
built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-3.js # Array.lastIndexOf expects start index to be a number.
|
||||
built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-4.js # a.lastIndexOf(2,undefined) Expected SameValue(«1», «-1») to be true
|
||||
built-ins/Array/prototype/lastIndexOf/15.4.4.15-5-5.js # Array.lastIndexOf expects start index to be a number.
|
||||
@@ -135,179 +135,19 @@ language/statements/async-generator/dstr/obj-ptrn-prop-obj-value-null.js # Expe
|
||||
language/statements/async-generator/dstr/obj-ptrn-prop-obj-value-undef.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/rest-params-trailing-comma-early-error.js # expected SyntaxError but the program ran
|
||||
language/statements/async-generator/return-undefined-implicit-and-explicit.js # Actual ["tick 1", "tick 2", "g1 ret", "g2 ret", "g3 ret", "g4 ret"] and expected ["tick 1", "g1 ret"
|
||||
language/statements/const/dstr/ary-ptrn-elem-obj-val-null.js # Expected a TypeError but got a Error
|
||||
language/statements/const/dstr/ary-ptrn-elem-obj-val-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/const/dstr/obj-init-null.js # Expected a TypeError but got a Error
|
||||
language/statements/const/dstr/obj-init-undefined.js # Expected a TypeError but got a Error
|
||||
language/statements/const/dstr/obj-ptrn-prop-obj-value-null.js # Expected a TypeError but got a Error
|
||||
language/statements/const/dstr/obj-ptrn-prop-obj-value-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/for-await-of/async-func-decl-dstr-array-elem-init-in.js # Failed to parse TypeScript: '…' expected.
|
||||
language/statements/for-await-of/async-func-decl-dstr-array-elem-nested-array-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-decl-dstr-array-elem-nested-array-undefined-hole.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-decl-dstr-array-elem-nested-array-undefined-own.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-decl-dstr-array-elem-nested-array-undefined.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-decl-dstr-array-elem-nested-obj-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-decl-dstr-array-elem-nested-obj-undefined-hole.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-decl-dstr-array-elem-nested-obj-undefined-own.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-decl-dstr-array-elem-nested-obj-undefined.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-decl-dstr-array-elem-put-const.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-decl-dstr-array-elem-put-unresolvable-strict.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-func-decl-dstr-array-elem-trlg-iter-elision-iter-nrml-close-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-decl-dstr-obj-empty-bool.js # Object destructuring requires a data object or array value, received a boolean.
|
||||
language/statements/for-await-of/async-func-decl-dstr-obj-empty-num.js # Object destructuring requires a data object or array value, received a number.
|
||||
language/statements/for-await-of/async-func-decl-dstr-obj-empty-string.js # Object destructuring requires a data object or array value, received a string.
|
||||
language/statements/for-await-of/async-func-decl-dstr-obj-rest-number.js # Object destructuring requires a data object or array value, received a number.
|
||||
language/statements/for-await-of/async-func-decl-dstr-obj-rest-str-val.js # Object destructuring requires a data object or array value, received a string.
|
||||
language/statements/for-await-of/async-func-dstr-const-ary-init-iter-get-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-ary-ptrn-elem-ary-val-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-ary-ptrn-elem-id-init-throws.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-ary-ptrn-elem-id-init-unresolvable.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-ary-ptrn-elem-id-iter-step-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-ary-ptrn-elem-obj-val-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-ary-ptrn-elem-obj-val-undef.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-ary-ptrn-elision-step-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-ary-ptrn-rest-id-elision-next-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-ary-ptrn-rest-id-iter-step-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-obj-init-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-obj-init-undefined.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-obj-ptrn-id-init-throws.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-obj-ptrn-id-init-unresolvable.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-obj-ptrn-list-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-obj-ptrn-prop-ary-value-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-obj-ptrn-prop-eval-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-obj-ptrn-prop-id-init-throws.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-obj-ptrn-prop-id-init-unresolvable.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-obj-ptrn-prop-obj-value-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-const-obj-ptrn-prop-obj-value-undef.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-ary-init-iter-get-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-ary-ptrn-elem-ary-val-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-ary-ptrn-elem-id-init-throws.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-ary-ptrn-elem-id-init-unresolvable.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-ary-ptrn-elem-id-iter-step-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-ary-ptrn-elem-obj-val-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-ary-ptrn-elem-obj-val-undef.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-ary-ptrn-elision-step-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-ary-ptrn-rest-id-elision-next-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-ary-ptrn-rest-id-iter-step-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-obj-init-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-obj-init-undefined.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-obj-ptrn-id-init-throws.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-obj-ptrn-id-init-unresolvable.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-obj-ptrn-list-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-obj-ptrn-prop-ary-value-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-obj-ptrn-prop-eval-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-obj-ptrn-prop-id-init-throws.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-obj-ptrn-prop-id-init-unresolvable.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-obj-ptrn-prop-obj-value-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-let-obj-ptrn-prop-obj-value-undef.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-ary-init-iter-get-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-ary-ptrn-elem-ary-val-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-ary-ptrn-elem-id-init-throws.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-ary-ptrn-elem-id-init-unresolvable.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-ary-ptrn-elem-id-iter-step-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-ary-ptrn-elem-obj-val-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-ary-ptrn-elem-obj-val-undef.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-ary-ptrn-elision-step-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-ary-ptrn-rest-id-elision-next-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-ary-ptrn-rest-id-iter-step-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-obj-init-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-obj-init-undefined.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-obj-ptrn-id-init-throws.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-obj-ptrn-id-init-unresolvable.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-obj-ptrn-list-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-obj-ptrn-prop-ary-value-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-obj-ptrn-prop-eval-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-obj-ptrn-prop-id-init-throws.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-obj-ptrn-prop-id-init-unresolvable.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-obj-ptrn-prop-obj-value-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-dstr-var-obj-ptrn-prop-obj-value-undef.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-func-decl-dstr-obj-empty-bool.js # TypeError: Object destructuring requires a data object or array value, received a boolean.
|
||||
language/statements/for-await-of/async-func-decl-dstr-obj-empty-num.js # TypeError: Object destructuring requires a data object or array value, received a number.
|
||||
language/statements/for-await-of/async-func-decl-dstr-obj-empty-string.js # TypeError: Object destructuring requires a data object or array value, received a string.
|
||||
language/statements/for-await-of/async-func-decl-dstr-obj-rest-number.js # TypeError: Object destructuring requires a data object or array value, received a number.
|
||||
language/statements/for-await-of/async-func-decl-dstr-obj-rest-str-val.js # TypeError: Object destructuring requires a data object or array value, received a string.
|
||||
language/statements/for-await-of/async-gen-decl-dstr-array-elem-init-in.js # Failed to parse TypeScript: '…' expected.
|
||||
language/statements/for-await-of/async-gen-decl-dstr-array-elem-iter-get-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-decl-dstr-array-elem-iter-nrml-close-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-decl-dstr-array-elem-iter-nrml-close-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-decl-dstr-array-elem-iter-rtrn-close-null.js # "Promise incorrectly fulfilled."
|
||||
language/statements/for-await-of/async-gen-decl-dstr-array-elem-nested-array-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-decl-dstr-array-elem-nested-array-undefined-hole.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-decl-dstr-array-elem-nested-array-undefined-own.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-decl-dstr-array-elem-nested-array-undefined.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-decl-dstr-array-elem-nested-obj-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-decl-dstr-array-elem-nested-obj-undefined-hole.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-decl-dstr-array-elem-nested-obj-undefined-own.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-decl-dstr-array-elem-nested-obj-undefined.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-decl-dstr-array-elem-put-const.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-decl-dstr-array-elem-put-unresolvable-strict.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-gen-decl-dstr-array-elem-trlg-iter-elision-iter-nrml-close-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-decl-dstr-array-elem-trlg-iter-elision-iter-nrml-close-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-decl-dstr-array-elem-trlg-iter-list-nrml-close-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-decl-dstr-array-elem-trlg-iter-list-thrw-close-skip.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-decl-dstr-obj-empty-bool.js # Object destructuring requires a data object or array value, received a boolean.
|
||||
language/statements/for-await-of/async-gen-decl-dstr-obj-empty-num.js # Object destructuring requires a data object or array value, received a number.
|
||||
language/statements/for-await-of/async-gen-decl-dstr-obj-empty-string.js # Object destructuring requires a data object or array value, received a string.
|
||||
language/statements/for-await-of/async-gen-decl-dstr-obj-rest-number.js # Object destructuring requires a data object or array value, received a number.
|
||||
language/statements/for-await-of/async-gen-decl-dstr-obj-rest-str-val.js # Object destructuring requires a data object or array value, received a string.
|
||||
language/statements/for-await-of/async-gen-dstr-const-ary-init-iter-get-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-ary-ptrn-elem-ary-val-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-ary-ptrn-elem-id-init-throws.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-ary-ptrn-elem-id-init-unresolvable.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-ary-ptrn-elem-id-iter-step-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-ary-ptrn-elem-obj-val-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-ary-ptrn-elem-obj-val-undef.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-ary-ptrn-elision-step-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-ary-ptrn-rest-id-elision-next-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-ary-ptrn-rest-id-iter-step-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-obj-init-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-obj-init-undefined.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-obj-ptrn-id-init-throws.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-obj-ptrn-id-init-unresolvable.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-obj-ptrn-list-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-obj-ptrn-prop-ary-value-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-obj-ptrn-prop-eval-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-obj-ptrn-prop-id-init-throws.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-obj-ptrn-prop-id-init-unresolvable.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-obj-ptrn-prop-obj-value-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-const-obj-ptrn-prop-obj-value-undef.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-ary-init-iter-get-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-ary-ptrn-elem-ary-val-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-ary-ptrn-elem-id-init-throws.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-ary-ptrn-elem-id-init-unresolvable.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-ary-ptrn-elem-id-iter-step-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-ary-ptrn-elem-obj-val-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-ary-ptrn-elem-obj-val-undef.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-ary-ptrn-elision-step-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-ary-ptrn-rest-id-elision-next-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-ary-ptrn-rest-id-iter-step-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-obj-init-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-obj-init-undefined.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-obj-ptrn-id-init-throws.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-obj-ptrn-id-init-unresolvable.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-obj-ptrn-list-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-obj-ptrn-prop-ary-value-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-obj-ptrn-prop-eval-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-obj-ptrn-prop-id-init-throws.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-obj-ptrn-prop-id-init-unresolvable.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-obj-ptrn-prop-obj-value-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-let-obj-ptrn-prop-obj-value-undef.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-ary-init-iter-get-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-ary-ptrn-elem-ary-val-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-ary-ptrn-elem-id-init-throws.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-ary-ptrn-elem-id-init-unresolvable.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-ary-ptrn-elem-id-iter-step-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-ary-ptrn-elem-obj-val-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-ary-ptrn-elem-obj-val-undef.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-ary-ptrn-elision-step-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-ary-ptrn-rest-id-elision-next-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-ary-ptrn-rest-id-iter-step-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-obj-init-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-obj-init-undefined.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-obj-ptrn-id-init-throws.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-obj-ptrn-id-init-unresolvable.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-obj-ptrn-list-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-obj-ptrn-prop-ary-value-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-obj-ptrn-prop-eval-err.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-obj-ptrn-prop-id-init-throws.js # Expected SameValue(«undefined», «Test262Error») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-obj-ptrn-prop-id-init-unresolvable.js # Expected SameValue(«undefined», «ReferenceError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-obj-ptrn-prop-obj-value-null.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-dstr-var-obj-ptrn-prop-obj-value-undef.js # Expected SameValue(«undefined», «TypeError») to be true
|
||||
language/statements/for-await-of/async-gen-decl-dstr-obj-empty-bool.js # TypeError: Object destructuring requires a data object or array value, received a boolean.
|
||||
language/statements/for-await-of/async-gen-decl-dstr-obj-empty-num.js # TypeError: Object destructuring requires a data object or array value, received a number.
|
||||
language/statements/for-await-of/async-gen-decl-dstr-obj-empty-string.js # TypeError: Object destructuring requires a data object or array value, received a string.
|
||||
language/statements/for-await-of/async-gen-decl-dstr-obj-rest-number.js # TypeError: Object destructuring requires a data object or array value, received a number.
|
||||
language/statements/for-await-of/async-gen-decl-dstr-obj-rest-str-val.js # TypeError: Object destructuring requires a data object or array value, received a string.
|
||||
language/statements/for-in/12.6.4-1.js # .hasOwnProperty is not a function.
|
||||
language/statements/for-in/head-lhs-member.js # Unsupported for...in binding.
|
||||
language/statements/for-of/Array.prototype.Symbol.iterator.js # The called value is not a function.
|
||||
@@ -315,10 +155,6 @@ language/statements/for-of/dstr/array-elem-init-in.js # Failed to parse TypeScr
|
||||
language/statements/for-of/dstr/array-elem-iter-rtrn-close-err.js # Iterator next must be a function.
|
||||
language/statements/for-of/dstr/array-elem-iter-rtrn-close-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/for-of/dstr/array-elem-iter-thrw-close-err.js # Expected SameValue(«1», «0») to be true
|
||||
language/statements/for-of/dstr/array-elem-nested-obj-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/array-elem-nested-obj-undefined-hole.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/array-elem-nested-obj-undefined-own.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/array-elem-nested-obj-undefined.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/array-elem-trlg-iter-list-rtrn-close-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/for-of/dstr/array-elem-trlg-iter-list-rtrn-close-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/for-of/dstr/array-elem-trlg-iter-list-thrw-close-err.js # Expected SameValue(«1», «0») to be true
|
||||
@@ -329,58 +165,14 @@ language/statements/for-of/dstr/array-rest-iter-rtrn-close-err.js # Iterator ne
|
||||
language/statements/for-of/dstr/array-rest-iter-rtrn-close-null.js # Iterator next must be a function.
|
||||
language/statements/for-of/dstr/array-rest-iter-thrw-close-err.js # Expected SameValue(«11», «0») to be true
|
||||
language/statements/for-of/dstr/array-rest-lref-err.js # Expected SameValue(«1», «0») to be true
|
||||
language/statements/for-of/dstr/const-ary-ptrn-elem-obj-val-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/const-ary-ptrn-elem-obj-val-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/const-obj-init-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/const-obj-init-undefined.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/const-obj-ptrn-prop-obj-value-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/const-obj-ptrn-prop-obj-value-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/let-ary-ptrn-elem-obj-val-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/let-ary-ptrn-elem-obj-val-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/let-obj-init-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/let-obj-init-undefined.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/let-obj-ptrn-prop-obj-value-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/let-obj-ptrn-prop-obj-value-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/obj-empty-bool.js # Object destructuring requires a data object or array value, received a boolean.
|
||||
language/statements/for-of/dstr/obj-empty-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/obj-empty-num.js # Object destructuring requires a data object or array value, received a number.
|
||||
language/statements/for-of/dstr/obj-empty-string.js # Object destructuring requires a data object or array value, received a string.
|
||||
language/statements/for-of/dstr/obj-empty-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/obj-prop-name-evaluation-error.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/obj-prop-nested-obj-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/obj-prop-nested-obj-undefined-own.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/obj-prop-nested-obj-undefined.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/obj-rest-number.js # Object destructuring requires a data object or array value, received a number.
|
||||
language/statements/for-of/dstr/obj-rest-str-val.js # Object destructuring requires a data object or array value, received a string.
|
||||
language/statements/for-of/dstr/obj-rest-val-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/obj-rest-val-undefined.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/var-ary-ptrn-elem-obj-val-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/var-ary-ptrn-elem-obj-val-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/var-obj-init-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/var-obj-init-undefined.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/var-obj-ptrn-prop-obj-value-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/dstr/var-obj-ptrn-prop-obj-value-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/for-of/throw-from-catch.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
|
||||
language/statements/for-of/throw-from-finally.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
|
||||
language/statements/for-of/throw.js # … cannot be constructed: user-defined constructors and classes are not supported. Call it as a funct
|
||||
language/statements/for/dstr/const-ary-ptrn-elem-obj-val-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for/dstr/const-ary-ptrn-elem-obj-val-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/for/dstr/const-obj-init-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for/dstr/const-obj-init-undefined.js # Expected a TypeError but got a Error
|
||||
language/statements/for/dstr/const-obj-ptrn-prop-obj-value-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for/dstr/const-obj-ptrn-prop-obj-value-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/for/dstr/let-ary-ptrn-elem-obj-val-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for/dstr/let-ary-ptrn-elem-obj-val-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/for/dstr/let-obj-init-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for/dstr/let-obj-init-undefined.js # Expected a TypeError but got a Error
|
||||
language/statements/for/dstr/let-obj-ptrn-prop-obj-value-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for/dstr/let-obj-ptrn-prop-obj-value-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/for/dstr/var-ary-ptrn-elem-obj-val-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for/dstr/var-ary-ptrn-elem-obj-val-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/for/dstr/var-obj-init-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for/dstr/var-obj-init-undefined.js # Expected a TypeError but got a Error
|
||||
language/statements/for/dstr/var-obj-ptrn-prop-obj-value-null.js # Expected a TypeError but got a Error
|
||||
language/statements/for/dstr/var-obj-ptrn-prop-obj-value-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/function/13.2-19-b-3gs.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/function/13.2-2-s.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/function/S13.2.1_A5_T1.js # .toString is not a function.
|
||||
@@ -390,18 +182,6 @@ language/statements/function/S13_A6_T1.js # Identifier '…' has already been d
|
||||
language/statements/function/S14_A2.js # Unknown identifier '…'.
|
||||
language/statements/function/S14_A5_T1.js # Identifier '…' has already been declared.
|
||||
language/statements/function/S14_A5_T2.js # Identifier '…' has already been declared.
|
||||
language/statements/function/dstr/ary-ptrn-elem-obj-val-null.js # Expected a TypeError but got a Error
|
||||
language/statements/function/dstr/ary-ptrn-elem-obj-val-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/function/dstr/dflt-ary-ptrn-elem-obj-val-null.js # Expected a TypeError but got a Error
|
||||
language/statements/function/dstr/dflt-ary-ptrn-elem-obj-val-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/function/dstr/dflt-obj-init-null.js # Expected a TypeError but got a Error
|
||||
language/statements/function/dstr/dflt-obj-init-undefined.js # Expected a TypeError but got a Error
|
||||
language/statements/function/dstr/dflt-obj-ptrn-prop-obj-value-null.js # Expected a TypeError but got a Error
|
||||
language/statements/function/dstr/dflt-obj-ptrn-prop-obj-value-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/function/dstr/obj-init-null.js # Expected a TypeError but got a Error
|
||||
language/statements/function/dstr/obj-init-undefined.js # Expected a TypeError but got a Error
|
||||
language/statements/function/dstr/obj-ptrn-prop-obj-value-null.js # Expected a TypeError but got a Error
|
||||
language/statements/function/dstr/obj-ptrn-prop-obj-value-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/function/rest-params-trailing-comma-early-error.js # expected SyntaxError but the program ran
|
||||
language/statements/generators/dflt-params-abrupt.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dflt-params-ref-later.js # Expected a ReferenceError to be thrown but no exception was thrown at all
|
||||
@@ -452,12 +232,6 @@ language/statements/generators/has-instance.js # The right-hand side of '…' m
|
||||
language/statements/generators/rest-params-trailing-comma-early-error.js # expected SyntaxError but the program ran
|
||||
language/statements/labeled/value-await-non-module-escaped.js # Failed to parse TypeScript: Keywords cannot contain escape characters.
|
||||
language/statements/labeled/value-await-non-module.js # Failed to parse TypeScript: Expression expected.
|
||||
language/statements/let/dstr/ary-ptrn-elem-obj-val-null.js # Expected a TypeError but got a Error
|
||||
language/statements/let/dstr/ary-ptrn-elem-obj-val-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/let/dstr/obj-init-null.js # Expected a TypeError but got a Error
|
||||
language/statements/let/dstr/obj-init-undefined.js # Expected a TypeError but got a Error
|
||||
language/statements/let/dstr/obj-ptrn-prop-obj-value-null.js # Expected a TypeError but got a Error
|
||||
language/statements/let/dstr/obj-ptrn-prop-obj-value-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/return/S12.9_A1_T1.js # expected SyntaxError but the program ran
|
||||
language/statements/return/S12.9_A1_T10.js # expected SyntaxError but the program ran
|
||||
language/statements/return/S12.9_A1_T2.js # expected SyntaxError but the program ran
|
||||
@@ -472,15 +246,3 @@ language/statements/switch/S12.11_A1_T4.js # Switch discriminants must be data
|
||||
language/statements/switch/scope-lex-open-dflt.js # Switch discriminants must be data values.
|
||||
language/statements/try/S12.14_A19_T1.js # .toString is not a function.
|
||||
language/statements/try/S12.14_A19_T2.js # .toString is not a function.
|
||||
language/statements/try/dstr/ary-ptrn-elem-obj-val-null.js # Expected a TypeError but got a Error
|
||||
language/statements/try/dstr/ary-ptrn-elem-obj-val-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/try/dstr/obj-init-null.js # Expected a TypeError but got a Error
|
||||
language/statements/try/dstr/obj-init-undefined.js # Expected a TypeError but got a Error
|
||||
language/statements/try/dstr/obj-ptrn-prop-obj-value-null.js # Expected a TypeError but got a Error
|
||||
language/statements/try/dstr/obj-ptrn-prop-obj-value-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/variable/dstr/ary-ptrn-elem-obj-val-null.js # Expected a TypeError but got a Error
|
||||
language/statements/variable/dstr/ary-ptrn-elem-obj-val-undef.js # Expected a TypeError but got a Error
|
||||
language/statements/variable/dstr/obj-init-null.js # Expected a TypeError but got a Error
|
||||
language/statements/variable/dstr/obj-init-undefined.js # Expected a TypeError but got a Error
|
||||
language/statements/variable/dstr/obj-ptrn-prop-obj-value-null.js # Expected a TypeError but got a Error
|
||||
language/statements/variable/dstr/obj-ptrn-prop-obj-value-undef.js # Expected a TypeError but got a Error
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
*
|
||||
* Copyright © web-platform-tests contributors. Governed by the 3-Clause BSD license in LICENSE.wpt.
|
||||
*
|
||||
* `assert_throws_dom("InvalidCharacterError", …)` becomes a check on `error.name`: CodeMode has no
|
||||
* DOMException, so the name is carried on a plain Error.
|
||||
* `assert_throws_dom("InvalidCharacterError", …)` becomes a check for a TypeError: CodeMode has no DOMException.
|
||||
*/
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
@@ -58,7 +57,7 @@ const referenceEncoder = `
|
||||
function testBtoa(input) {
|
||||
var expected = mybtoa(input)
|
||||
if (expected === "INVALID_CHARACTER_ERR") {
|
||||
try { btoa(input) } catch (error) { return error.name === "InvalidCharacterError" ? "ok" : error.name }
|
||||
try { btoa(input) } catch (error) { return error instanceof TypeError ? "ok" : error.name }
|
||||
return "did not throw"
|
||||
}
|
||||
if (btoa(input) !== expected) return "btoa mismatch"
|
||||
@@ -102,7 +101,7 @@ describe("atob WPT parity (fetch/data-urls/resources/base64.json)", () => {
|
||||
[-0, null],
|
||||
]
|
||||
|
||||
test(`${base64Cases.length} forgiving-base64 inputs decode to the expected bytes or throw InvalidCharacterError`, async () => {
|
||||
test(`${base64Cases.length} forgiving-base64 inputs decode to the expected bytes or throw a TypeError`, async () => {
|
||||
expect(
|
||||
await value(`
|
||||
const cases = ${JSON.stringify(base64Cases)}
|
||||
@@ -113,7 +112,7 @@ describe("atob WPT parity (fetch/data-urls/resources/base64.json)", () => {
|
||||
const bytes = Array.from({ length: result.length }, (_, i) => result.charCodeAt(i))
|
||||
return JSON.stringify(bytes) === JSON.stringify(output) ? [] : [[input, bytes]]
|
||||
} catch (error) {
|
||||
return output === null && error.name === "InvalidCharacterError" ? [] : [[input, error.name]]
|
||||
return output === null && error instanceof TypeError ? [] : [[input, error.name]]
|
||||
}
|
||||
})
|
||||
`),
|
||||
@@ -138,7 +137,7 @@ describe("atob WPT parity (fetch/data-urls/resources/base64.json)", () => {
|
||||
const bytes = output.map((_, i) => result.charCodeAt(i))
|
||||
return JSON.stringify(bytes) === JSON.stringify(output) ? [] : [[String(input), bytes]]
|
||||
} catch (error) {
|
||||
return output === null && error.name === "InvalidCharacterError" ? [] : [[String(input), error.name]]
|
||||
return output === null && error instanceof TypeError ? [] : [[String(input), error.name]]
|
||||
}
|
||||
})
|
||||
`),
|
||||
|
||||
Reference in New Issue
Block a user