Merge commit '6e92d2345e8231a44556ce7d416451f5f3e6c398' as 'engine262'

This commit is contained in:
2026-03-27 10:07:29 +05:30
433 changed files with 90478 additions and 0 deletions
+106
View File
@@ -0,0 +1,106 @@
#####################
### Failed Tests ###
#####################
# Comments start with `#` or `;`.
# Paths are relative to the `test262/test` directory.
# Paths may contain globs.
# TODO: import defer
language/expressions/dynamic-import/import-defer/import-defer-transitive-async-module/main.js
language/expressions/dynamic-import/import-defer/sync/main.js
language/expressions/dynamic-import/import-defer/sync-dependency-of-deferred-async-module/main.js
# Non-strict mode
# Annex B
## RegExp.prototype.compile
staging/sm/RegExp/compile-lastIndex.js
staging/sm/RegExp/constructor-ordering.js
staging/sm/RegExp/flags-param-handling.js
staging/sm/RegExp/match-local-tolength-recompilation.js
staging/sm/RegExp/prototype.js
staging/sm/RegExp/replace-compile-elembase.js
staging/sm/RegExp/replace-compile.js
staging/sm/RegExp/replace-local-tolength-recompilation.js
staging/sm/String/matchAll.js
# SourceCharacterIdentityEscape
language/literals/regexp/S7.8.5_A1.4_T2.js
language/literals/regexp/S7.8.5_A2.4_T2.js
# IdentityEscape + ExtendedPatternCharacter
staging/sm/RegExp/unicode-braced.js
built-ins/String/prototype/split/separator-regexp.js # references /\k<x>/, /\XA0/, /\X/
# Block
staging/sm/lexical-environment/block-scoped-functions-annex-b-arguments.js
staging/sm/lexical-environment/block-scoped-functions-annex-b-eval.js
staging/sm/lexical-environment/block-scoped-functions-annex-b-if.js
staging/sm/lexical-environment/block-scoped-functions-annex-b-label.js
staging/sm/lexical-environment/block-scoped-functions-annex-b-notapplicable.js
staging/sm/lexical-environment/block-scoped-functions-annex-b-parameter.js
staging/sm/lexical-environment/block-scoped-functions-annex-b-same-name.js
staging/sm/lexical-environment/block-scoped-functions-annex-b-with.js
staging/sm/lexical-environment/block-scoped-functions-annex-b.js
staging/sm/lexical-environment/block-scoped-functions-deprecated-redecl.js
# TODO: https://github.com/tc39/ecma262/issues/3592
built-ins/RegExp/regexp-modifiers/add-ignoreCase-affects-slash-upper-p.js
# Failed tests appended by --update-failed-tests
built-ins/String/prototype/localeCompare/15.5.4.9_CE.js
staging/sm/Array/toLocaleString-01.js
staging/sm/async-functions/await-in-arrow-parameters.js
staging/sm/async-functions/await-in-parameters-of-async-func.js
staging/sm/async-functions/property.js
staging/sm/AsyncGenerators/for-await-bad-syntax.js
staging/sm/Atomics/cross-compartment.js
staging/sm/Atomics/detached-buffers.js
staging/sm/class/newTargetDefaults.js
staging/sm/class/superCallBadNewTargetPrototype.js
staging/sm/class/superPropDestructuring.js
staging/sm/Date/setTime-argument-shortcircuiting.js
staging/sm/Date/time-components-negative-zero.js
staging/sm/Date/toISOString-01.js
staging/sm/destructuring/bug1396261.js
staging/sm/destructuring/order-super.js
staging/sm/expressions/destructuring-pattern-parenthesized.js
staging/sm/expressions/nullish-coalescing.js
staging/sm/expressions/optional-chain.js
staging/sm/extensions/arguments-property-access-in-function.js
staging/sm/extensions/censor-strict-caller.js
staging/sm/extensions/clone-v1-typed-array-data.dat
staging/sm/extensions/function-caller-skips-eval-frames.js
staging/sm/extensions/function-properties.js
staging/sm/extensions/recursion.js
staging/sm/fields/await-identifier-module-3.js
staging/sm/fields/await-identifier-script.js
staging/sm/Function/function-caller-restrictions.js
staging/sm/Function/function-name-for.js
staging/sm/Function/function-toString-builtin-name.js
staging/sm/Function/function-toString-builtin.js
staging/sm/Function/invalid-parameter-list.js
staging/sm/generators/runtime.js
staging/sm/generators/syntax.js
staging/sm/generators/yield-star-throw-htmldda.js
staging/sm/lexical-environment/for-loop.js
staging/sm/lexical-environment/var-in-catch-body-annex-b-eval.js
staging/sm/Math/f16round.js
staging/sm/misc/explicit-undefined-optional-argument.js
staging/sm/misc/future-reserved-words.js
staging/sm/Proxy/revoked-get-function-realm-typeerror.js
staging/sm/regress/regress-554955-5.js
staging/sm/regress/regress-577648-1.js
staging/sm/regress/regress-577648-2.js
staging/sm/regress/regress-584355.js
staging/sm/regress/regress-586482-1.js
staging/sm/regress/regress-586482-2.js
staging/sm/regress/regress-586482-3.js
staging/sm/regress/regress-586482-4.js
staging/sm/regress/regress-586482-5.js
staging/sm/regress/regress-602621.js
staging/sm/statements/for-in-with-declaration.js
staging/sm/statements/regress-642975.js
staging/sm/strict/strict-function-statements.js
staging/sm/String/unicode-braced.js
staging/sm/syntax/declaration-forbidden-in-label.js
staging/sm/syntax/linefeed-at-eof-in-unterminated-string-or-template.js
staging/sm/TypedArray/sort-negative-nan.js
staging/sm/TypedArray/toString.js
+27
View File
@@ -0,0 +1,27 @@
# https://github.com/tc39/test262/blob/main/features.txt
# Start with `-` to skip feature
# Map feature to engine262 feature using `feature = engine262featurename`
# e.g.:
# import-defer = import-defer
decorators = decorators
Temporal = temporal
# Update with test262 on Feb 2025, to be investigated/implemented
-Float16Array
-arraybuffer-transfer
-explicit-resource-management
-source-phase-imports
-source-phase-imports-module-source
-immutable-arraybuffer
# Added before Feb 2025
-Atomics
-Atomics.waitAsync
-Atomics.pause
-caller
-SharedArrayBuffer
-tail-call-optimization
-Temporal
-resizable-arraybuffer
+124
View File
@@ -0,0 +1,124 @@
#####################
### Skipped Tests ###
#####################
# Comments start with `#` or `;`.
# Paths are relative to the `test262/test` directory.
# Paths may contain globs.
annexB
intl402
# fix CI?
harness/nativeFunctionMatcher.js
# Our date parser is now calling the host algorithm, may unstable based on the host.
built-ins/Date/parse/without-utc-offset.js
# Decorators (not merged yet) https://github.com/tc39/test262/pull/4103/
## wrong test, we are correct
language/expressions/class/decorator/class/error/class-deco-invalid-return-arrow.js
language/statements/class/decorator/class/error/class-deco-invalid-return-arrow.js
language/expressions/class/decorator/class/class-deco-returns-proxy.js
language/statements/class/decorator/class/class-deco-returns-proxy.js
# TODO (Feb 2026)
language/import/import-defer/evaluation-triggers/ignore-super-property-set-exported.js
language/import/import-defer/evaluation-triggers/ignore-super-property-set-not-exported.js
language/module-code/ambiguous-export-bindings/namespace-unambiguous-if-import-star-as-and-export.js
language/module-code/ambiguous-export-bindings/namespace-unambiguous-if-export-star-as-from.js
language/module-code/ambiguous-export-bindings/namespace-unambiguous-if-export-star-as-from-and-import-star-as-and-export.js
language/identifiers/start-unicode-17.0.0-escaped.js
language/identifiers/part-unicode-17.0.0-class-escaped.js
language/identifiers/part-unicode-17.0.0.js
language/identifiers/start-unicode-17.0.0-class-escaped.js
language/identifiers/part-unicode-17.0.0-class.js
language/identifiers/start-unicode-17.0.0.js
language/identifiers/start-unicode-17.0.0-class.js
language/identifiers/part-unicode-17.0.0-escaped.js
built-ins/Promise/allSettledKeyed/not-a-constructor.js
built-ins/Promise/allSettledKeyed/proto.js
built-ins/Promise/allSettledKeyed/name.js
built-ins/Promise/allSettledKeyed/extensible.js
built-ins/Promise/allSettledKeyed/prop-desc.js
built-ins/Promise/allSettledKeyed/length.js
built-ins/Promise/allKeyed/not-a-constructor.js
built-ins/Promise/allKeyed/prop-desc.js
built-ins/Promise/allKeyed/proto.js
built-ins/Promise/allKeyed/extensible.js
built-ins/Promise/allKeyed/length.js
built-ins/Promise/allKeyed/name.js
built-ins/Iterator/zipKeyed/suspended-start-iterator-close-calls-return.js
built-ins/Iterator/zipKeyed/iterables-containing-string-objects.js
built-ins/Iterator/zipKeyed/iterator-zip-iteration-iterator-step-value-abrupt-completion.js
built-ins/Iterator/zipKeyed/results-object-has-default-attributes.js
built-ins/Iterator/zipKeyed/iterator-zip-iteration-strict-iterator-close-i-is-not-zero-abrupt-completion.js
built-ins/Iterator/zipKeyed/suspended-start-iterator-close-calls-next.js
built-ins/Iterator/zipKeyed/padding-iteration.js
built-ins/Iterator/zipKeyed/iterator-zip-iteration-iterator-close-abrupt-completion.js
built-ins/Iterator/zipKeyed/iterator-zip-iteration-longest-iterator-close-abrupt-completion.js
built-ins/Iterator/zipKeyed/proto.js
built-ins/Iterator/zipKeyed/iterables-iteration-inherited.js
built-ins/Iterator/zipKeyed/iterables-iteration-symbol-key.js
built-ins/Iterator/zipKeyed/basic-longest.js
built-ins/Iterator/zipKeyed/basic-strict.js
built-ins/Iterator/zipKeyed/iterables-iteration-get-iterator-flattenable-abrupt-completion.js
built-ins/Iterator/zipKeyed/iterables-iteration-after-reading-options.js
built-ins/Iterator/zipKeyed/iterator-zip-iteration-shortest-iterator-close-abrupt-completion.js
built-ins/Iterator/zipKeyed/suspended-yield-iterator-close-calls-next.js
built-ins/Iterator/zipKeyed/iterator-zip-iteration-strict-iterator-step-abrupt-completion.js
built-ins/Iterator/zipKeyed/padding-iteration-get-abrupt-completion.js
built-ins/Iterator/zipKeyed/prop-desc.js
built-ins/Iterator/zipKeyed/iterables-iteration-get-abrupt-completion.js
built-ins/Iterator/zipKeyed/results-object-from-array.js
built-ins/Iterator/zipKeyed/iterables-iteration.js
built-ins/Iterator/zipKeyed/is-function.js
built-ins/Iterator/zipKeyed/iterables-iteration-undefined.js
built-ins/Iterator/zipKeyed/iterables-iteration-get-own-property-abrupt-completion.js
built-ins/Iterator/zipKeyed/options.js
built-ins/Iterator/zipKeyed/iterables-iteration-deleted.js
built-ins/Iterator/zipKeyed/suspended-yield-iterator-close-calls-return.js
built-ins/Iterator/zipKeyed/basic-shortest.js
built-ins/Iterator/zipKeyed/options-padding.js
built-ins/Iterator/zipKeyed/iterables-iteration-enumerable.js
built-ins/Iterator/zipKeyed/iterator-zip-iteration-strict-iterator-close-i-is-zero-abrupt-completion.js
built-ins/Iterator/zipKeyed/length.js
built-ins/Iterator/zipKeyed/results-object-has-no-undefined-iterables-properties.js
built-ins/Iterator/zipKeyed/options-mode.js
built-ins/Iterator/zipKeyed/name.js
built-ins/Iterator/zipKeyed/result-is-iterator.js
built-ins/Iterator/zipKeyed/iterator-zip-iteration.js
built-ins/Iterator/zip/iterables-containing-string-objects.js
built-ins/Iterator/zip/iterator-zip-iteration-strict-iterator-close-i-is-not-zero-abrupt-completion.js
built-ins/Iterator/zip/padding-iteration-iterator-close-abrupt-completion.js
built-ins/Iterator/zip/suspended-start-iterator-close-calls-return.js
built-ins/Iterator/zip/suspended-start-iterator-close-calls-next.js
built-ins/Iterator/zip/iterator-zip-iteration-iterator-step-value-abrupt-completion.js
built-ins/Iterator/zip/padding-iteration.js
built-ins/Iterator/zip/padding-iteration-get-iterator-abrupt-completion.js
built-ins/Iterator/zip/iterator-zip-iteration-iterator-close-abrupt-completion.js
built-ins/Iterator/zip/iterator-zip-iteration-longest-iterator-close-abrupt-completion.js
built-ins/Iterator/zip/proto.js
built-ins/Iterator/zip/basic-longest.js
built-ins/Iterator/zip/basic-strict.js
built-ins/Iterator/zip/iterables-iteration-get-iterator-flattenable-abrupt-completion.js
built-ins/Iterator/zip/iterables-iteration-after-reading-options.js
built-ins/Iterator/zip/iterator-zip-iteration-shortest-iterator-close-abrupt-completion.js
built-ins/Iterator/zip/suspended-yield-iterator-close-calls-next.js
built-ins/Iterator/zip/iterator-zip-iteration-strict-iterator-step-abrupt-completion.js
built-ins/Iterator/zip/prop-desc.js
built-ins/Iterator/zip/iterables-iteration.js
built-ins/Iterator/zip/is-function.js
built-ins/Iterator/zip/padding-iteration-iterator-step-value-abrupt-completion.js
built-ins/Iterator/zip/options.js
built-ins/Iterator/zip/suspended-yield-iterator-close-calls-return.js
built-ins/Iterator/zip/options-padding.js
built-ins/Iterator/zip/iterables-iteration-iterator-step-value-abrupt-completion.js
built-ins/Iterator/zip/basic-shortest.js
built-ins/Iterator/zip/iterator-zip-iteration-strict-iterator-close-i-is-zero-abrupt-completion.js
built-ins/Iterator/zip/length.js
built-ins/Iterator/zip/name.js
built-ins/Iterator/zip/iterator-zip-iteration.js
built-ins/Iterator/zip/result-is-iterator.js
built-ins/Iterator/zip/options-mode.js
built-ins/RegExp/unicodeSets/generated/rgi-emoji-17.0.js
+97
View File
@@ -0,0 +1,97 @@
##################
### Slow Tests ###
##################
# Comments start with `#` or `;`.
# Paths are relative to the `test262/test` directory.
# Paths may contain globs.
built-ins/RegExp/property-escapes/generated
built-ins/RegExp/CharacterClassEscapes
# Slow on CI
built-ins/Array/prototype/concat/Array.prototype.concat_small-typed-array.js
built-ins/Array/prototype/every/15.4.4.16-7-c-ii-2.js
built-ins/Array/prototype/indexOf/15.4.4.14-10-1.js
built-ins/Array/prototype/lastIndexOf/15.4.4.15-9-1.js
built-ins/Array/prototype/map/15.4.4.19-8-c-ii-1.js
built-ins/Array/prototype/some/15.4.4.17-7-c-ii-2.js
built-ins/decodeURI
built-ins/encodeURIComponent
language/literals/regexp/S7.8.5_A1.4_T2.js
language/literals/regexp/S7.8.5_A2.4_T2.js
staging/sm/expressions/object-literal-__proto__.js
staging/sm/misc/getter-setter-outerize-this.js
staging/sm/Proxy/ownkeys-linear.js
staging/sm/RegExp/unicode-class-braced.js
staging/sm/String/replace-math.js
staging/sm/TypedArray/entries.js
staging/sm/TypedArray/fill.js
staging/sm/TypedArray/forEach.js
staging/sm/TypedArray/sort_small.js
staging/sm/TypedArray/sort-negative-nan.js
# Slow tests appended by --update-slow-tests=10
built-ins/Array/fromAsync/asyncitems-arraylike-too-long.js
built-ins/Array/prototype/concat/Array.prototype.concat_large-typed-array.js
built-ins/decodeURI/S15.1.3.1_A1.10_T1.js
built-ins/decodeURI/S15.1.3.1_A1.11_T1.js
built-ins/decodeURI/S15.1.3.1_A1.11_T2.js
built-ins/decodeURI/S15.1.3.1_A1.12_T1.js
built-ins/decodeURI/S15.1.3.1_A1.12_T2.js
built-ins/decodeURI/S15.1.3.1_A1.12_T3.js
built-ins/decodeURI/S15.1.3.1_A1.2_T1.js
built-ins/decodeURI/S15.1.3.1_A1.2_T2.js
built-ins/decodeURI/S15.1.3.1_A2.1_T1.js
built-ins/decodeURI/S15.1.3.1_A2.4_T1.js
built-ins/decodeURI/S15.1.3.1_A2.5_T1.js
built-ins/decodeURIComponent/S15.1.3.2_A1.10_T1.js
built-ins/decodeURIComponent/S15.1.3.2_A1.11_T1.js
built-ins/decodeURIComponent/S15.1.3.2_A1.11_T2.js
built-ins/decodeURIComponent/S15.1.3.2_A1.12_T1.js
built-ins/decodeURIComponent/S15.1.3.2_A1.12_T2.js
built-ins/decodeURIComponent/S15.1.3.2_A1.12_T3.js
built-ins/decodeURIComponent/S15.1.3.2_A1.2_T1.js
built-ins/decodeURIComponent/S15.1.3.2_A1.2_T2.js
built-ins/decodeURIComponent/S15.1.3.2_A2.1_T1.js
built-ins/decodeURIComponent/S15.1.3.2_A2.4_T1.js
built-ins/decodeURIComponent/S15.1.3.2_A2.5_T1.js
built-ins/encodeURI/S15.1.3.3_A2.3_T1.js
built-ins/encodeURI/S15.1.3.3_A2.5_T1.js
built-ins/encodeURIComponent/S15.1.3.4_A2.3_T1.js
built-ins/encodeURIComponent/S15.1.3.4_A2.5_T1.js
built-ins/Function/prototype/toString/built-in-function-object.js
built-ins/parseFloat/S15.1.2.3_A6.js
built-ins/parseInt/S15.1.2.2_A8.js
built-ins/RegExp/character-class-escape-non-whitespace.js
language/comments/S7.4_A5.js
language/comments/S7.4_A6.js
language/literals/regexp/S7.8.5_A1.1_T2.js
language/literals/regexp/S7.8.5_A2.1_T2.js
staging/sm/Array/length-truncate-nonconfigurable-sparse.js
staging/sm/Array/toSpliced-dense.js
staging/sm/Date/dst-offset-caching-1-of-8.js
staging/sm/Date/dst-offset-caching-2-of-8.js
staging/sm/Date/dst-offset-caching-3-of-8.js
staging/sm/Date/dst-offset-caching-4-of-8.js
staging/sm/Date/dst-offset-caching-5-of-8.js
staging/sm/Date/dst-offset-caching-6-of-8.js
staging/sm/Date/dst-offset-caching-7-of-8.js
staging/sm/Date/dst-offset-caching-8-of-8.js
staging/sm/Date/two-digit-years.js
staging/sm/expressions/short-circuit-compound-assignment.js
staging/sm/Function/has-instance-jitted.js
staging/sm/JSON/parse-mega-huge-array.js
staging/sm/RegExp/unicode-ignoreCase.js
staging/sm/regress/regress-1507322-deep-weakmap.js
staging/sm/regress/regress-610026.js
staging/sm/String/fromCodePoint.js
staging/sm/String/string-upper-lower-mapping.js
staging/sm/TypedArray/element-setting-converts-using-ToNumber.js
staging/sm/TypedArray/every-and-some.js
staging/sm/TypedArray/map-and-filter.js
staging/sm/TypedArray/set-same-buffer-different-source-target-types.js
staging/sm/TypedArray/sort_large_countingsort.js
staging/sm/TypedArray/sort_modifications.js
staging/sm/TypedArray/sort_snans.js
staging/sm/TypedArray/sort_sorted.js
+37
View File
@@ -0,0 +1,37 @@
##########################
### Slow Tests (on CI) ###
##########################
# Comments start with `#` or `;`.
# Paths are relative to the `test262/test` directory.
# Paths may contain globs.
built-ins/Array/prototype/concat/Array.prototype.concat_small-typed-array.js
built-ins/Array/prototype/every/15.4.4.16-7-c-ii-2.js
built-ins/Array/prototype/filter/15.4.4.20-9-c-ii-1.js
built-ins/Array/prototype/forEach/15.4.4.18-7-c-ii-1.js
built-ins/Array/prototype/indexOf/15.4.4.14-10-1.js
built-ins/Array/prototype/lastIndexOf/15.4.4.15-9-1.js
built-ins/Array/prototype/map/15.4.4.19-8-c-ii-1.js
built-ins/Array/prototype/some/15.4.4.17-7-c-ii-2.js
built-ins/encodeURI/S15.1.3.3_A2.4_T1.js
built-ins/encodeURI/S15.1.3.3_A2.4_T2.js
built-ins/encodeURIComponent/S15.1.3.4_A2.4_T1.js
built-ins/encodeURIComponent/S15.1.3.4_A2.4_T2.js
built-ins/String/prototype/repeat/empty-string-returns-empty.js
built-ins/TypedArray/prototype/copyWithin/coerced-values-end-detached-prototype.js
built-ins/TypedArray/prototype/copyWithin/coerced-values-end-detached.js
built-ins/TypedArray/prototype/copyWithin/coerced-values-start-detached.js
language/literals/regexp/S7.8.5_A1.4_T2.js
language/literals/regexp/S7.8.5_A2.4_T2.js
staging/sm/expressions/object-literal-__proto__.js
staging/sm/misc/getter-setter-outerize-this.js
staging/sm/Proxy/ownkeys-linear.js
staging/sm/RegExp/unicode-class-braced.js
staging/sm/String/replace-math.js
staging/sm/TypedArray/entries.js
staging/sm/TypedArray/fill.js
staging/sm/TypedArray/forEach.js
staging/sm/TypedArray/sort_small.js
staging/sm/TypedArray/sort_small.js
staging/sm/TypedArray/sort-negative-nan.js
Submodule engine262/test/test262/test262 added at 3aa9cb2c71
+446
View File
@@ -0,0 +1,446 @@
/* eslint-disable no-console */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { join, resolve, relative } from 'node:path';
import { createWriteStream } from 'node:fs';
import { opendir, readFile, stat } from 'node:fs/promises';
import { stripVTControlCharacters, styleText } from 'node:util';
import { fork } from 'node:child_process';
import { cpus } from 'node:os';
import { glob, isDynamicPattern } from 'tinyglobby';
import YAML from 'js-yaml';
import { highlight } from 'cli-highlight';
import {
type WorkerToSupervisor, type SupervisorToWorker, Test,
readList,
type WorkerToSupervisor_Failed,
type Stack,
} from '../base.mts';
import { annotateFileWithURL, isCI } from '../tui.mts';
import {
createTestReporter,
supportColor,
type SkipReason,
} from '../tui.mts';
import { fatal_exit } from '../base.mts';
import { args } from './test262.mts';
const inputs = {
Test262TestsPath: join(process.env.TEST262 || resolve(import.meta.dirname, 'test262'), 'test'),
AllTests: async () => {
const files: string[] = [];
for await (const file of readdir(inputs.Test262TestsPath)) {
files.push(file);
}
inputs.AllTests = async () => files;
return files;
},
AssertToBeFailedList: resolve(import.meta.dirname, 'failed'),
SkipList: resolve(import.meta.dirname, 'skip'),
SlowList: resolve(import.meta.dirname, 'slow'),
SlowListCI: resolve(import.meta.dirname, 'slow-ci'),
Features: resolve(import.meta.dirname, 'features'),
};
const outputs = {
LastRunFailedList: resolve(import.meta.dirname, 'last-failed-list'),
CurrentRunFailureLog: resolve(import.meta.dirname, 'last-failed.log'),
};
if (args.values['failed-only']) {
args.positionals = (await readFile(outputs.LastRunFailedList, { encoding: 'utf-8' })).split('\n');
}
const outputStreams = {
SlowList: args.values['update-slow'] ? createWriteStream(inputs.SlowList, { encoding: 'utf-8', flags: 'a' }) : undefined,
LastRunFailedList: createWriteStream(outputs.LastRunFailedList, { encoding: 'utf-8' }),
CurrentRunFailureLog: createWriteStream(outputs.CurrentRunFailureLog, { encoding: 'utf-8' }),
AssertToBeFailedList: args.values['update-failed'] ? createWriteStream(inputs.AssertToBeFailedList, { encoding: 'utf-8', flags: 'a' }) : undefined,
};
let allTestsDiscovered = false;
const disabledFeatures = new Set<string>();
readList(inputs.Features).forEach((feature) => {
if (feature.startsWith('-')) {
disabledFeatures.add(feature.slice(1));
}
});
disabledFeatures.delete(args.values.features!);
const workersToStart = Math.max(
1,
process.env.NUM_WORKERS
? Number.parseInt(process.env.NUM_WORKERS, 10)
: cpus().length - 2,
);
const workers = Array.from({ length: workersToStart }, (_, index) => createWorker(index));
/**
* Do not replace this with reporter.workers.
* This variable maintains the state in the main thread, but reporter.workers is updated asynchronously based on the feedback from workers.
*/
const workerHasPendingTask: boolean[] = new Array(workersToStart).fill(false);
const [
slowList,
slowListCI,
skipList,
assertToBeFailedList,
] = await Promise.all([
readListPaths(inputs.SlowList, false),
readListPaths(inputs.SlowListCI, true),
readListPaths(inputs.SkipList, false),
readListPaths(inputs.AssertToBeFailedList, false),
]);
if (outputStreams.AssertToBeFailedList) {
outputStreams.AssertToBeFailedList.write('\n# Failed tests appended by --update-failed-tests\n');
}
/** This is for skipping the report of a test if it's variant (strict version) has already failed. */
const currentRunFailedTestFiles = new Set<string>();
const pendingTests: Test[] = [];
const reporter = createTestReporter();
if (outputStreams.SlowList) {
const second = parseInt(args.values['update-slow']!, 10);
if (Number.isNaN(second)) {
fatal_exit('--update-slow must be a number');
}
outputStreams.SlowList.write(`\n# Slow tests appended by --update-slow=${second}\n`);
reporter.setSlowTestReporting(second, outputStreams.SlowList);
}
function discoverTest(test: Test) {
reporter.addTest(test);
const disabledFeature = test.attrs.features?.find((feature: string) => disabledFeatures.has(feature));
if (disabledFeature) {
return reporter.skipTest(test.id, 'feature-disabled', disabledFeature);
}
if (skipList.has(test.file)) {
return reporter.skipTest(test.id, 'skip-list');
}
if (slowList.has(test.file) && !args.values['run-slow']) {
return reporter.skipTest(test.id, 'slow-list');
}
if (isCI && slowListCI.has(test.file) && !args.values['run-slow']) {
return reporter.skipTest(test.id, 'slow-list');
}
pendingTests.push(test);
distributeTest();
return undefined;
}
function distributeTest() {
while (true) {
const candidate = workerHasPendingTask.findIndex((work) => !work);
if (candidate === -1) {
return;
}
if (!pendingTests.length) {
if (allTestsDiscovered && workerHasPendingTask.every((work) => !work)) {
reporter.exit();
}
return;
}
workers[candidate].send(pendingTests.shift()! satisfies SupervisorToWorker);
workerHasPendingTask[candidate] = true;
}
}
const visited = new Set<string>();
reporter.start();
reporter.addEventListener('exit', () => {
workers.forEach((worker) => worker.kill());
});
reporter.onExit.promise.then(() => {
if (args.values.verbose || args.values.vv) {
const skip: Record<SkipReason, Set<string>> = {
'feature-disabled': new Set<string>(),
'skip-list': new Set<string>(),
'slow-list': new Set<string>(),
};
const passed: Set<string> = new Set<string>();
const skipByFeature: Record<string, Set<string>> = {};
const failed: Set<string> = new Set<string>();
for (const test of reporter.tests.values()) {
if (test.status === 'skipped') {
if (test.skipFeature) {
(skipByFeature[test.skipFeature] ??= new Set()).add(test.file);
} else if (test.skipReason) {
skip[test.skipReason].add(test.file);
}
} else if (test.status === 'failed') {
failed.add(test.file);
} else if (args.values.vv && test.status === 'passed') {
passed.add(test.file);
}
}
if (args.values.vv && passed.size > 0) {
console.log(styleText('green', 'The following tests passed:'));
for (const test of passed) {
console.log(`- ./test/test262/test262/test/${test}`);
}
}
let skipPrint = () => {
console.log(styleText('yellow', 'The following tests were skipped:'));
skipPrint = () => { };
};
for (const [reason, tests] of Object.entries(skip)) {
if (tests.size === 0) {
continue;
}
skipPrint();
console.log(`- Reason: ${styleText('yellow', reason)} (${tests.size} tests)`);
for (const test of tests) {
console.log(` - ./test/test262/test262/test/${test}`);
}
}
for (const [feature, tests] of Object.entries(skipByFeature)) {
skipPrint();
console.log(`- Reason: ${styleText('yellow', `feature-disabled (${feature})`)} (${tests.size} tests)`);
for (const test of tests) {
console.log(` - ./test/test262/test262/test/${test}`);
}
}
if (failed.size > 0) {
console.log(styleText('red', '\nThe following tests failed:'));
for (const test of failed) {
console.log(`- ./test/test262/test262/test/${test}`);
}
}
}
});
const engineFeatures = [...args.values['engine-features'] || []];
const promises = [];
for await (const file of parsePositionals(args.positionals, true)) {
if (visited.has(file) || /_FIXTURE|README\.md|\.py|\.map|\.mts/.test(file)) {
continue;
}
visited.add(file);
promises.push(readFile(file, 'utf8').then((contents) => {
const frontmatterYaml = contents.match(/\/\*---(.*?)---\*\//s)?.[1];
const attrs: any = frontmatterYaml ? YAML.load(frontmatterYaml) : {};
if (args.values.features && (!attrs.features || !attrs.features.includes(args.values.features))) {
// feature not match
return;
}
attrs.flags = (attrs.flags || []).reduce((acc: any, c: any) => {
acc[c] = true;
return acc;
}, {});
attrs.includes = attrs.includes || [];
const test = new Test(relative(inputs.Test262TestsPath, file), file, engineFeatures, attrs, '', contents);
if (test.attrs.flags.module) {
discoverTest(test.withDifferentTestFlag('module'));
} else {
if (!test.attrs.flags.onlyStrict && !args.values['strict-only'] && !args.values.fast) {
discoverTest(test);
}
if (!test.attrs.flags.noStrict && !test.attrs.flags.raw) {
discoverTest(test.withDifferentTestFlag('strict', `'use strict';${test.content}`));
}
}
}));
}
if (args.positionals.length && !promises.length) {
fatal_exit(`No tests found based on the given globs: ${args.positionals.join(', ')}`);
}
await Promise.all(promises);
allTestsDiscovered = true;
reporter.allTestsDiscovered();
distributeTest();
async function readListPaths(file: string, defaults: boolean) {
const list = readList(file);
const files = new Set<string>();
for await (const file of parsePositionals(list, defaults)) {
files.add(relative(inputs.Test262TestsPath, file));
}
return files;
}
async function* readdir(dir: string): AsyncGenerator<string> {
for await (const dirent of await opendir(dir)) {
const p = join(dir, dirent.name);
if (dirent.isDirectory()) {
yield* readdir(p);
} else {
yield p;
}
}
}
async function* parsePositional(pattern: string): AsyncGenerator<string> {
if (!isDynamicPattern(pattern)) {
const a_path = join(inputs.Test262TestsPath, pattern);
const a = await stat(a_path).catch(() => undefined);
if (a?.isDirectory()) {
return yield* readdir(a_path);
} else if (a?.isFile()) {
return yield a_path;
}
const b_path = join(process.cwd(), pattern);
const b = await stat(b_path).catch(() => undefined);
if (b?.isDirectory()) {
return yield* readdir(b_path);
} else if (b?.isFile()) {
return yield b_path;
}
const files = await inputs.AllTests();
const matched = files.filter((f) => f.toLowerCase().includes(pattern.toLowerCase()));
if (matched.length) {
return yield* matched;
}
}
const files1 = await glob(pattern, { cwd: inputs.Test262TestsPath, absolute: true, caseSensitiveMatch: false });
if (files1.length) {
return yield* files1;
}
const files2 = await glob(pattern, { cwd: process.cwd(), absolute: true, caseSensitiveMatch: false });
if (files2.length) {
return yield* files2;
}
return undefined;
}
async function* parsePositionals(pattern: string[], defaults: boolean): AsyncGenerator<string> {
if (!pattern.length) {
if (defaults) {
yield* readdir(inputs.Test262TestsPath);
}
return;
}
for (const p of pattern) {
if (p) {
yield* parsePositional(p);
}
}
}
function createWorker(workerId: number) {
const c = fork(resolve(import.meta.dirname, './test262-worker.mts'));
c.on('message', (message: WorkerToSupervisor) => {
switch (message.status) {
case 'RUNNING':
return reporter.updateWorker(workerId, message.testId);
case 'PASS':
workerHasPendingTask[workerId] = false;
reporter.updateWorker(workerId, null);
distributeTest();
if (assertToBeFailedList.has(message.file)) {
if (currentRunFailedTestFiles.has(message.file)) {
return reporter.testFailed(message.testId);
} else {
currentRunFailedTestFiles.add(message.file);
return fail({
file: message.file,
description: 'The test is declared to be failed, but passed.',
error: '',
flags: message.flags,
status: 'FAIL',
testId: message.testId,
stack: [],
}, false);
}
}
return reporter.testPassed(message.testId);
case 'FAIL': {
workerHasPendingTask[workerId] = false;
reporter.updateWorker(workerId, null);
distributeTest();
if (assertToBeFailedList.has(message.file)) {
return reporter.assertFailedTestFails(message.testId);
}
if (currentRunFailedTestFiles.has(message.file)) {
return reporter.testFailed(message.testId);
}
currentRunFailedTestFiles.add(message.file);
outputStreams.LastRunFailedList.write(`${message.file}\n`);
if (outputStreams.AssertToBeFailedList) {
outputStreams.AssertToBeFailedList.write(`${message.file}\n`);
}
return fail(message, true);
}
default:
console.error(message);
throw new RangeError('Unknown message from worker');
}
});
c.on('exit', (code) => {
if (code !== 0 && code !== null) {
fatal_exit(`Worker ${workerId} exited with code ${code}`);
}
});
return c;
}
function fail(message: WorkerToSupervisor_Failed, showSource: boolean) {
const { description, testId, file } = message;
let error = message.error;
error = error.replaceAll(`${process.cwd()}/`, '');
process.exitCode = 1;
const desc = styleText('yellow', description.trim());
const descNeedOwnLine = desc.includes('\n') || desc.length > (process.stdout.columns - file.length - 8);
// FAILED filename.js
const line1 = `${styleText(['bgRed', 'white', 'bold'], ' FAIL ')} ${annotateFileWithURL(file)}${descNeedOwnLine ? '' : ` ${desc}`}\n`;
// Test description in the header
const line2 = descNeedOwnLine ? `${indent(desc, ' ')}\n` : '';
// Source code with error position annotated
const line3 = showSource ? annotateSourceWithErrorPosition(error, reporter.tests.get(testId)!.content, message.stack) : '';
// Error message
const line4 = `${indent(error, ' ')}\n`;
const line5 = styleText('red', `${'⎯'.repeat(process.stdout.columns)}\n`);
const output = line1 + line2 + line3 + line4;
reporter.stdout(output, line5);
outputStreams.CurrentRunFailureLog.write(stripVTControlCharacters(output));
reporter.testFailed(testId);
}
function indent(string: string, space: string) {
return string.split('\n').map((line) => space + line).join('\n');
}
function annotateSourceWithErrorPosition(error: string, sourceCode: string, [stack]: Stack[]) {
sourceCode = stack?.source || sourceCode;
if (!stack) {
return '';
}
if (sourceCode.endsWith('\n')) {
sourceCode = sourceCode.slice(0, -1);
}
const highLightedLines = (supportColor ? highlight(sourceCode, { language: 'js' }) : sourceCode).split('\n');
const linesPad = (highLightedLines.length + 1).toString().length;
const decoratedLines = highLightedLines.map((line, index) => ` ${styleText('red', (index + 1).toString().padStart(linesPad))} | ${line}`);
const LINES_BEFORE = 3;
const LINES_AFTER = 2;
const slicedLines = decoratedLines.slice(
Math.max(0, Number(stack.line) - LINES_BEFORE),
Math.min(decoratedLines.length, Number(stack.line)),
);
slicedLines.push(''.padStart(linesPad + 5) + styleText('red', `${'-'.repeat(Math.max(Number(stack.column) - 1, 0))}^ ${error.split('\n')[0].trim()}`));
slicedLines.push(
decoratedLines.slice(
Number(stack.line),
Math.min(decoratedLines.length, Number(stack.line) + LINES_AFTER),
).join('\n'),
);
sourceCode = `${slicedLines.join('\n')}`;
sourceCode += '\n';
return sourceCode;
}
+260
View File
@@ -0,0 +1,260 @@
/* eslint-disable no-console */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable no-multi-assign */
import * as path from 'node:path';
import * as fs from 'node:fs';
import * as util from 'node:util';
import {
readList, type Stack, type SupervisorToWorker, type Test, type WorkerToSupervisor,
} from '../base.mts';
import { createRealm, createAgent } from '../base.mts';
import {
AbruptCompletion, ObjectValue, evalQ,
setSurroundingAgent,
inspect,
Value,
IsCallable,
IsDataDescriptor,
JSStringValue,
skipDebugger,
boostTest262Harness,
ThrowCompletion,
getHostDefinedErrorStack,
CallSite,
} from '#self';
const TEST262 = process.env.TEST262 || path.resolve(import.meta.dirname, 'test262');
const TEST262_TESTS = path.join(TEST262, 'test');
const featureMap: Record<string, string> = Object.create(null);
readList(path.resolve(import.meta.dirname, 'features')).forEach((f) => {
if (f.includes('=')) {
const [k, v] = f.split('=');
featureMap[k.trim()] = v.trim();
}
});
const includeCache: Record<string, undefined | { source: string, specifier: string }> = {};
process.on('message', (test: SupervisorToWorker) => {
try {
process.send!({ status: 'RUNNING', testId: test.id } satisfies WorkerToSupervisor, handleSendError);
const result = run(test);
if (result.status === 'PASS') {
process.send!({
status: 'PASS', file: test.file, flags: test.currentTestFlag, testId: test.id,
} satisfies WorkerToSupervisor, handleSendError);
} else {
process.send!(result satisfies WorkerToSupervisor, handleSendError);
}
} catch (e) {
process.send!(fails(test, util.inspect(e), []), handleSendError);
}
});
function run(test: Test): WorkerToSupervisor {
const features = [...test.engineFeatures];
if (test.attrs.features) {
test.attrs.features.forEach((f) => {
if (featureMap[f]) {
features.push(featureMap[f]);
}
});
}
const agent = createAgent({ features });
const parsedScripts = new Map<string, string>();
setSurroundingAgent(agent);
agent.hostDefinedOptions.errorStackAttachNativeStack = true;
agent.hostDefinedOptions.onScriptParsed = (script, id) => {
parsedScripts.set(id, script.ECMAScriptCode.sourceText);
};
function fail(test: Test, error: Value): WorkerToSupervisor {
const stacks = getHostDefinedErrorStack(error);
const reportStack: Stack[] = [];
for (const stack of stacks || []) {
if (!(stack instanceof CallSite)) {
continue;
}
const scriptId = stack.getScriptId();
if (!scriptId || stack.columnNumber === null || stack.lineNumber === null) {
continue;
}
const source = parsedScripts.get(scriptId);
const record = agent.parsedSources.get(scriptId);
if (record?.HostDefined.specifier?.includes('harness')) {
continue;
}
reportStack.push({
column: stack.columnNumber,
line: stack.lineNumber,
source: source === test.content ? undefined : source,
specifier: stack.getSpecifier(),
});
}
return {
status: 'FAIL',
file: test.file,
flags: test.currentTestFlag,
testId: test.id,
description: test.attrs.description,
error: inspect(error),
stack: reportStack,
};
}
const { realm, resolverCache, setPrintHandle } = createRealm({ specifier: test.specifier });
const r = realm.scope((): WorkerToSupervisor => {
test.attrs.includes.unshift('assert.js', 'sta.js');
if (test.attrs.flags.async) {
test.attrs.includes.unshift('doneprintHandle.js');
}
for (const include of test.attrs.includes) {
if (includeCache[include] === undefined) {
const p = path.resolve(TEST262, `harness/${include}`);
includeCache[include] = {
source: fs.readFileSync(p, 'utf8'),
specifier: p,
};
}
const entry = includeCache[include];
const completion = realm.evaluateScript(entry.source, { specifier: entry.specifier });
if (completion instanceof AbruptCompletion) {
return fail(test, completion.Value);
}
}
boostTest262Harness(realm);
{
const DONE = `
function $DONE(error) {
if (error) {
if (typeof error === 'object' && error !== null && 'stack' in error) {
print('Test262:AsyncTestFailure:' + error.stack, error);
} else {
print('Test262:AsyncTestFailure:Test262Error: ' + error, error);
}
} else {
print('Test262:AsyncTestComplete');
}
}`;
const completion = realm.evaluateScript(`\
var Test262Error = class Test262Error extends Error {};
Test262Error.thrower = (...args) => {
throw new Test262Error(...args);
};
${test.attrs.flags.async ? DONE : ''}`);
if (completion instanceof AbruptCompletion) {
return fail(test, completion.Value);
}
}
let asyncResult: WorkerToSupervisor | undefined;
if (test.attrs.flags.async) {
setPrintHandle((m, value) => {
if (m === 'Test262:AsyncTestComplete') {
asyncResult = {
status: 'PASS', flags: test.currentTestFlag, testId: test.id, file: test.file,
};
} else {
asyncResult = fail(test, value);
}
setPrintHandle(undefined);
});
}
const specifier = path.resolve(TEST262_TESTS, test.file);
const completion = evalQ((Q) => {
if (test.attrs.flags.module) {
const module = Q(realm.compileModule(test.content, { specifier }));
resolverCache.set(specifier, module);
const loadModuleCompletion = module.LoadRequestedModules();
if (loadModuleCompletion.PromiseState === 'rejected') {
Q(ThrowCompletion(loadModuleCompletion.PromiseResult!));
} else if (loadModuleCompletion.PromiseState === 'pending') {
throw new Error('Internal error: .LoadRequestedModules() returned a pending promise');
}
Q(module.Link());
const evaluateCompletion = Q(skipDebugger(module.Evaluate()));
if (evaluateCompletion.PromiseState === 'rejected') {
Q(ThrowCompletion(evaluateCompletion.PromiseResult!));
}
} else {
Q(realm.evaluateScript(test.content, { specifier }));
}
});
if (completion.Type === 'throw') {
if (test.attrs.negative && isError(test.attrs.negative.type, completion.Value)) {
return {
status: 'PASS', flags: test.currentTestFlag, testId: test.id, file: test.file,
};
} else {
return fail(test, completion.Value);
}
}
if (test.attrs.flags.async) {
if (!asyncResult) {
throw new Error('missing async result');
}
return asyncResult;
}
if (test.attrs.negative) {
return fails(test, `Expected ${test.attrs.negative.type} during ${test.attrs.negative.phase}`, []);
} else {
return {
status: 'PASS', flags: test.currentTestFlag, testId: test.id, file: test.file,
};
}
});
return r;
}
function handleSendError(e: any) {
if (e) {
console.error(e);
process.exit(1);
}
}
function isError(type: string, value: unknown) {
if (!(value instanceof ObjectValue)) {
return false;
}
const proto = (value as any).Prototype;
if (!proto || !(proto instanceof ObjectValue)) {
return false;
}
const ctorDesc = proto.properties.get(Value('constructor'));
if (!ctorDesc || !IsDataDescriptor(ctorDesc)) {
return false;
}
const ctor = ctorDesc.Value;
if (!(ctor instanceof ObjectValue) || !IsCallable(ctor)) {
return false;
}
const namePropDesc = ctor.properties.get(Value('name'));
if (!namePropDesc || !IsDataDescriptor(namePropDesc)) {
return false;
}
const nameProp = namePropDesc.Value;
return nameProp instanceof JSStringValue && nameProp.stringValue() === type;
}
function fails(test: Test, error: string, stack: Stack[]): WorkerToSupervisor {
return {
status: 'FAIL',
file: test.file,
flags: test.currentTestFlag,
testId: test.id,
description: test.attrs.description,
error,
stack,
};
}
+103
View File
@@ -0,0 +1,103 @@
/* eslint-disable no-console */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { relative } from 'node:path';
import util, { styleText } from 'node:util';
import { cpus } from 'node:os';
import { link } from '../base.mts';
import { isCI } from '../tui.mts';
export const args = util.parseArgs({
args: process.argv.slice(2),
allowNegative: true,
allowPositionals: true,
strict: true,
options: {
'help': { type: 'boolean', short: 'h' },
'features': { type: 'string', short: 'f' },
'engine-features': { type: 'string', multiple: true, short: 'e' },
'update-slow': { type: 'string' },
'update-failed': { type: 'boolean', short: 'u' },
'run-slow': { type: 'boolean' },
'failed-only': { type: 'boolean', short: 'f' },
'strict-only': { type: 'boolean' },
'fast': { type: 'boolean', short: 'q', default: !!isCI },
'verbose': { type: 'boolean', short: 'v' },
'vv': { type: 'boolean', short: 'V' },
},
});
async function main() {
if (args.values.help) {
const TEST_PATTERN = styleText('gray', '[TEST-PATTERN]');
const SLOW_LIST = link('the slow list file', new URL('./slow', import.meta.url));
const LAST_FAILED_LIST = link('last-failed-list', new URL('./last-failed-list', import.meta.url));
const LOCAL_FILE = styleText('gray', '(Local file)');
const usage = `
Usage: node ${relative(process.cwd(), import.meta.filename)} ${TEST_PATTERN} ...
Run ${link('test262 tests', 'https://github.com/tc39/test262')} against engine262.
${TEST_PATTERN} supports glob syntax, and is interpreted relative to
${link('the test262 "test" subdirectory', new URL('./test262/test262/test/', import.meta.url))} or (if that fails for any pattern)
relative to the working directory. If no patterns are specified,
all tests are run.
${styleText('magentaBright', 'Environment variables:')}
${styleText('magenta', 'TEST262')} ${styleText('gray', process.env.TEST262 ? `(set to '${process.env.TEST262}')` : '(unset)')}
The test262 directory, which contains the "test" subdirectory.
If empty, it defaults to the "test262" sibling of this file.
${styleText('magenta', 'NUM_WORKERS')} ${styleText('gray', process.env.NUM_WORKERS ? `(set to '${process.env.NUM_WORKERS}')` : '(unset)')}
The count of child processes that should be created to run tests.
If empty, it defaults to ${cpus().length}.
${styleText('greenBright', 'Options:')}
${styleText('green', '--features / -f')} ${styleText('gray', '[feature]')}
Only run tests that has the specified feature.
${styleText('green', '--engine-features / -e')} ${styleText('gray', '[feature]')}
Enable specified engine features during test execution.
${styleText('green', '--update-slow')} ${styleText('gray', '[seconds]')}
Append tests that take longer than the given time to ${SLOW_LIST}.
${styleText('green', '--update-failed / -u')}
Append failed tests to ${link('the failed list', new URL('./failed', import.meta.url))}.
If test in this list passes, it will be an error.
${styleText('green', '--run-slow')}
Run slow tests that are listed in ${SLOW_LIST}.
${styleText('green', '--failed-only / -f')}
Run only the tests that failed in the previous run.
Listed in ${LAST_FAILED_LIST}.
${styleText('green', '--strict-only / --fast / --q')}
Only run strict mode tests.
${styleText('green', '--verbose / -v')}
Print why tests are skipped or failed.
${styleText('green', '--vv / -V')}
Print why tests are skipped or failed, and also print passed tests.
${styleText('yellowBright', 'Files:')}
${link(styleText('yellow', 'features'), new URL('./features', import.meta.url))}
Specifies handling of test262 features, notably which ones to skip.
${link(styleText('yellow', 'skip'), new URL('./skip', import.meta.url))}
Includes patterns of test files to skip.
${link(styleText('yellow', 'slow'), new URL('./slow', import.meta.url))}
Includes patterns of test files to skip in the absence of ${styleText('green', '--run-slow-tests')}.
${link(styleText('yellow', 'failed'), new URL('./failed', import.meta.url))}
Includes patterns of test files that are expected to fail.
${styleText('yellow', LAST_FAILED_LIST)} ${LOCAL_FILE}
The list of test files that failed in the last run.
${link(styleText('yellow', 'last-failed.log'), new URL('./last-failed.log', import.meta.url))} ${LOCAL_FILE}
The detailed log of test files that failed in the last run.
`.slice(1);
const indent = usage.match(/^\s*/)![0];
process.stdout.write(
`${usage
.trimEnd()
.split('\n')
.map((line) => line.replace(indent, ''))
.join('\n')}\n`,
);
process.exit(64);
}
await import('./test262-runner.mts');
}
main();