summaryrefslogtreecommitdiffstats
path: root/js/src/tests/test262/harness
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/test262/harness')
-rw-r--r--js/src/tests/test262/harness/assert-false.js27
-rw-r--r--js/src/tests/test262/harness/assert-notsamevalue-nan.js27
-rw-r--r--js/src/tests/test262/harness/assert-notsamevalue-notsame.js16
-rw-r--r--js/src/tests/test262/harness/assert-notsamevalue-objects.js11
-rw-r--r--js/src/tests/test262/harness/assert-notsamevalue-tostring.js26
-rw-r--r--js/src/tests/test262/harness/assert-notsamevalue-zeros.js11
-rw-r--r--js/src/tests/test262/harness/assert-obj.js27
-rw-r--r--js/src/tests/test262/harness/assert-samevalue-nan.js11
-rw-r--r--js/src/tests/test262/harness/assert-samevalue-objects.js27
-rw-r--r--js/src/tests/test262/harness/assert-samevalue-same.js20
-rw-r--r--js/src/tests/test262/harness/assert-samevalue-tostring.js26
-rw-r--r--js/src/tests/test262/harness/assert-samevalue-zeros.js28
-rw-r--r--js/src/tests/test262/harness/assert-throws-custom-typeerror.js60
-rw-r--r--js/src/tests/test262/harness/assert-throws-custom.js16
-rw-r--r--js/src/tests/test262/harness/assert-throws-incorrect-ctor.js30
-rw-r--r--js/src/tests/test262/harness/assert-throws-native.js38
-rw-r--r--js/src/tests/test262/harness/assert-throws-no-arg.js27
-rw-r--r--js/src/tests/test262/harness/assert-throws-no-error.js27
-rw-r--r--js/src/tests/test262/harness/assert-throws-null-fn.js63
-rw-r--r--js/src/tests/test262/harness/assert-throws-null.js29
-rw-r--r--js/src/tests/test262/harness/assert-throws-primitive.js28
-rw-r--r--js/src/tests/test262/harness/assert-throws-same-realm.js32
-rw-r--r--js/src/tests/test262/harness/assert-throws-single-arg.js26
-rw-r--r--js/src/tests/test262/harness/assert-tostring.js26
-rw-r--r--js/src/tests/test262/harness/assert-true.js11
-rw-r--r--js/src/tests/test262/harness/assertRelativeDateMs.js82
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-asyncTest-func-throws-sync.js20
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-asyncTest-rejects-non-callable.js21
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-asyncTest-return-not-thenable.js32
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-asyncTest-returns-undefined.js40
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-asyncTest-then-rejects.js49
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-asyncTest-then-resolves.js57
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-asyncTest-without-async-flag.js24
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-throwsAsync-custom-typeerror.js73
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-throwsAsync-custom.js20
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-throwsAsync-func-throws-sync.js53
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-throwsAsync-incorrect-ctor.js36
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-throwsAsync-invalid-func.js71
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-throwsAsync-native.js48
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-throwsAsync-no-arg.js33
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-throwsAsync-no-error.js33
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-throwsAsync-null.js35
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-throwsAsync-primitive.js35
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-throwsAsync-resolved-error.js36
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-throwsAsync-same-realm.js38
-rw-r--r--js/src/tests/test262/harness/asyncHelpers-throwsAsync-single-arg.js32
-rw-r--r--js/src/tests/test262/harness/browser.js0
-rw-r--r--js/src/tests/test262/harness/byteConversionValues.js24
-rw-r--r--js/src/tests/test262/harness/compare-array-arguments.js40
-rw-r--r--js/src/tests/test262/harness/compare-array-arraylike.js36
-rw-r--r--js/src/tests/test262/harness/compare-array-different-elements.js17
-rw-r--r--js/src/tests/test262/harness/compare-array-different-length.js19
-rw-r--r--js/src/tests/test262/harness/compare-array-empty.js12
-rw-r--r--js/src/tests/test262/harness/compare-array-falsy-arguments.js30
-rw-r--r--js/src/tests/test262/harness/compare-array-message.js25
-rw-r--r--js/src/tests/test262/harness/compare-array-same-elements-different-order.js18
-rw-r--r--js/src/tests/test262/harness/compare-array-same-elements-same-order.js16
-rw-r--r--js/src/tests/test262/harness/compare-array-samevalue.js15
-rw-r--r--js/src/tests/test262/harness/compare-array-sparse.js25
-rw-r--r--js/src/tests/test262/harness/compare-array-symbol.js25
-rw-r--r--js/src/tests/test262/harness/dateConstants.js27
-rw-r--r--js/src/tests/test262/harness/decimalToHexString.js28
-rw-r--r--js/src/tests/test262/harness/deepEqual-array.js16
-rw-r--r--js/src/tests/test262/harness/deepEqual-circular.js19
-rw-r--r--js/src/tests/test262/harness/deepEqual-deep.js15
-rw-r--r--js/src/tests/test262/harness/deepEqual-mapset.js21
-rw-r--r--js/src/tests/test262/harness/deepEqual-object.js17
-rw-r--r--js/src/tests/test262/harness/deepEqual-primitives-bigint.js17
-rw-r--r--js/src/tests/test262/harness/deepEqual-primitives.js36
-rw-r--r--js/src/tests/test262/harness/detachArrayBuffer-host-detachArrayBuffer.js45
-rw-r--r--js/src/tests/test262/harness/detachArrayBuffer.js35
-rw-r--r--js/src/tests/test262/harness/fnGlobalObject.js19
-rw-r--r--js/src/tests/test262/harness/isConstructor.js34
-rw-r--r--js/src/tests/test262/harness/nans.js26
-rw-r--r--js/src/tests/test262/harness/nativeFunctionMatcher.js62
-rw-r--r--js/src/tests/test262/harness/promiseHelper.js37
-rw-r--r--js/src/tests/test262/harness/propertyhelper-verifyconfigurable-configurable-object.js17
-rw-r--r--js/src/tests/test262/harness/propertyhelper-verifyconfigurable-configurable.js17
-rw-r--r--js/src/tests/test262/harness/propertyhelper-verifyconfigurable-not-configurable.js33
-rw-r--r--js/src/tests/test262/harness/propertyhelper-verifyenumerable-enumerable-symbol.js19
-rw-r--r--js/src/tests/test262/harness/propertyhelper-verifyenumerable-enumerable.js17
-rw-r--r--js/src/tests/test262/harness/propertyhelper-verifyenumerable-not-enumerable-symbol.js34
-rw-r--r--js/src/tests/test262/harness/propertyhelper-verifyenumerable-not-enumerable.js32
-rw-r--r--js/src/tests/test262/harness/propertyhelper-verifynotconfigurable-configurable.js32
-rw-r--r--js/src/tests/test262/harness/propertyhelper-verifynotconfigurable-not-configurable.js17
-rw-r--r--js/src/tests/test262/harness/propertyhelper-verifynotenumerable-enumerable-symbol.js36
-rw-r--r--js/src/tests/test262/harness/propertyhelper-verifynotenumerable-enumerable.js34
-rw-r--r--js/src/tests/test262/harness/propertyhelper-verifynotenumerable-not-enumerable-symbol.js20
-rw-r--r--js/src/tests/test262/harness/propertyhelper-verifynotenumerable-not-enumerable.js18
-rw-r--r--js/src/tests/test262/harness/propertyhelper-verifynotwritable-not-writable-strict.js23
-rw-r--r--js/src/tests/test262/harness/propertyhelper-verifynotwritable-writable.js32
-rw-r--r--js/src/tests/test262/harness/propertyhelper-verifywritable-array-length.js16
-rw-r--r--js/src/tests/test262/harness/propertyhelper-verifywritable-not-writable.js32
-rw-r--r--js/src/tests/test262/harness/propertyhelper-verifywritable-writable.js22
-rw-r--r--js/src/tests/test262/harness/proxytrapshelper-default.js42
-rw-r--r--js/src/tests/test262/harness/proxytrapshelper-overrides.js77
-rw-r--r--js/src/tests/test262/harness/shell.js3550
-rw-r--r--js/src/tests/test262/harness/sta.js17
-rw-r--r--js/src/tests/test262/harness/tcoHelper.js19
-rw-r--r--js/src/tests/test262/harness/temporalHelpers-cross-date-line-time-zone.js59
-rw-r--r--js/src/tests/test262/harness/temporalHelpers-one-shift-time-zone.js83
-rw-r--r--js/src/tests/test262/harness/testTypedArray-conversions-call-error.js32
-rw-r--r--js/src/tests/test262/harness/testTypedArray-conversions.js57
-rw-r--r--js/src/tests/test262/harness/testTypedArray.js34
-rw-r--r--js/src/tests/test262/harness/timer.js20
-rw-r--r--js/src/tests/test262/harness/verifyProperty-arguments.js21
-rw-r--r--js/src/tests/test262/harness/verifyProperty-configurable-object.js19
-rw-r--r--js/src/tests/test262/harness/verifyProperty-desc-is-not-object.js32
-rw-r--r--js/src/tests/test262/harness/verifyProperty-noproperty.js17
-rw-r--r--js/src/tests/test262/harness/verifyProperty-restore-accessor-symbol.js45
-rw-r--r--js/src/tests/test262/harness/verifyProperty-restore-accessor.js44
-rw-r--r--js/src/tests/test262/harness/verifyProperty-restore-symbol.js36
-rw-r--r--js/src/tests/test262/harness/verifyProperty-restore.js35
-rw-r--r--js/src/tests/test262/harness/verifyProperty-same-value.js21
-rw-r--r--js/src/tests/test262/harness/verifyProperty-string-prop.js53
-rw-r--r--js/src/tests/test262/harness/verifyProperty-symbol-prop.js54
-rw-r--r--js/src/tests/test262/harness/verifyProperty-undefined-desc.js28
-rw-r--r--js/src/tests/test262/harness/verifyProperty-value-error.js41
-rw-r--r--js/src/tests/test262/harness/verifyProperty-value.js53
119 files changed, 7234 insertions, 0 deletions
diff --git a/js/src/tests/test262/harness/assert-false.js b/js/src/tests/test262/harness/assert-false.js
new file mode 100644
index 0000000000..b34f5aea58
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-false.js
@@ -0,0 +1,27 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ `false` does not satisfy the assertion.
+---*/
+
+var threw = false;
+
+try {
+ assert(false);
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-notsamevalue-nan.js b/js/src/tests/test262/harness/assert-notsamevalue-nan.js
new file mode 100644
index 0000000000..e6974fb253
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-notsamevalue-nan.js
@@ -0,0 +1,27 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Two references to NaN do not satisfy the assertion.
+---*/
+
+var threw = false;
+
+try {
+ assert.notSameValue(NaN, NaN);
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-notsamevalue-notsame.js b/js/src/tests/test262/harness/assert-notsamevalue-notsame.js
new file mode 100644
index 0000000000..0b7188c4ad
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-notsamevalue-notsame.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Values that are not strictly equal satisfy the assertion.
+---*/
+
+assert.notSameValue(undefined, null);
+assert.notSameValue(null, undefined);
+assert.notSameValue(0, 1);
+assert.notSameValue(1, 0);
+assert.notSameValue('', 's');
+assert.notSameValue('s', '');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-notsamevalue-objects.js b/js/src/tests/test262/harness/assert-notsamevalue-objects.js
new file mode 100644
index 0000000000..ece310079e
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-notsamevalue-objects.js
@@ -0,0 +1,11 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Distinct objects satisfy the assertion.
+---*/
+
+assert.notSameValue({}, {});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-notsamevalue-tostring.js b/js/src/tests/test262/harness/assert-notsamevalue-tostring.js
new file mode 100644
index 0000000000..f8bb3339d5
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-notsamevalue-tostring.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2019 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ When composing a message, errors from ToString are handled.
+features: [async-functions]
+---*/
+
+var threw = false;
+var asyncFunProto = Object.getPrototypeOf(async function() {});
+
+try {
+ assert.notSameValue(asyncFunProto, asyncFunProto);
+} catch (err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error('Expected a Test262Error, but a "' + err.constructor.name + '" was thrown.');
+ }
+}
+
+if (!threw) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-notsamevalue-zeros.js b/js/src/tests/test262/harness/assert-notsamevalue-zeros.js
new file mode 100644
index 0000000000..80e19f407c
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-notsamevalue-zeros.js
@@ -0,0 +1,11 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Positive and negative zero satisfy the assertion.
+---*/
+
+assert.notSameValue(0, -0);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-obj.js b/js/src/tests/test262/harness/assert-obj.js
new file mode 100644
index 0000000000..521182f2d7
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-obj.js
@@ -0,0 +1,27 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ An object literal does not satisfy the assertion.
+---*/
+
+var threw = false;
+
+try {
+ assert({});
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-samevalue-nan.js b/js/src/tests/test262/harness/assert-samevalue-nan.js
new file mode 100644
index 0000000000..410c34651f
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-samevalue-nan.js
@@ -0,0 +1,11 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Two references to NaN satisfy the assertion.
+---*/
+
+assert.sameValue(NaN, NaN);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-samevalue-objects.js b/js/src/tests/test262/harness/assert-samevalue-objects.js
new file mode 100644
index 0000000000..059f6d00ca
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-samevalue-objects.js
@@ -0,0 +1,27 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Distinct objects do not satisfy the assertion.
+---*/
+
+var threw = false;
+
+try {
+ assert.sameValue({}, {});
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-samevalue-same.js b/js/src/tests/test262/harness/assert-samevalue-same.js
new file mode 100644
index 0000000000..658de38aa6
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-samevalue-same.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Values that are strictly equal satisfy the assertion.
+---*/
+var obj;
+
+assert.sameValue(undefined, undefined);
+assert.sameValue(null, null);
+assert.sameValue(0, 0);
+assert.sameValue(1, 1);
+assert.sameValue('', '');
+assert.sameValue('s', 's');
+
+obj = {};
+assert.sameValue(obj, obj);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-samevalue-tostring.js b/js/src/tests/test262/harness/assert-samevalue-tostring.js
new file mode 100644
index 0000000000..5567158d3f
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-samevalue-tostring.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2019 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ When composing a message, errors from ToString are handled.
+features: [async-functions]
+---*/
+
+var threw = false;
+var asyncFunProto = Object.getPrototypeOf(async function() {});
+
+try {
+ assert.sameValue(asyncFunProto, 1);
+} catch (err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error('Expected a Test262Error, but a "' + err.constructor.name + '" was thrown.');
+ }
+}
+
+if (!threw) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-samevalue-zeros.js b/js/src/tests/test262/harness/assert-samevalue-zeros.js
new file mode 100644
index 0000000000..b1d074ea25
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-samevalue-zeros.js
@@ -0,0 +1,28 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Positive and negative zero do not satisfy the assertion.
+---*/
+
+var threw = false;
+
+try {
+ assert.sameValue(0, -0);
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+ assert.notSameValue(err.message.indexOf('-0'), -1);
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-throws-custom-typeerror.js b/js/src/tests/test262/harness/assert-throws-custom-typeerror.js
new file mode 100644
index 0000000000..b49ae1b5a6
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-throws-custom-typeerror.js
@@ -0,0 +1,60 @@
+// Copyright (C) 2021 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Functions that throw instances of the specified constructor function
+ satisfy the assertion, without collision with error constructors of the
+ same name.
+---*/
+
+var intrinsicTypeError = TypeError;
+var threw = false;
+
+(function() {
+ function TypeError() {}
+
+ assert.throws(TypeError, function() {
+ throw new TypeError();
+ }, 'Throws an instance of the matching custom TypeError');
+
+ try {
+ assert.throws(intrinsicTypeError, function() {
+ throw new TypeError();
+ });
+ } catch (err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+ }
+
+ if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+ }
+
+ threw = false;
+
+ try {
+ assert.throws(TypeError, function() {
+ throw new intrinsicTypeError();
+ });
+ } catch (err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+ }
+
+ if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+ }
+})();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-throws-custom.js b/js/src/tests/test262/harness/assert-throws-custom.js
new file mode 100644
index 0000000000..e37f72a054
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-throws-custom.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Functions that throw instances of the specified constructor function
+ satisfy the assertion.
+---*/
+
+function MyError() {}
+
+assert.throws(MyError, function() {
+ throw new MyError();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-throws-incorrect-ctor.js b/js/src/tests/test262/harness/assert-throws-incorrect-ctor.js
new file mode 100644
index 0000000000..c49a98ddf4
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-throws-incorrect-ctor.js
@@ -0,0 +1,30 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Functions that throw values whose constructor does not match the specified
+ constructor do not satisfy the assertion.
+---*/
+
+var threw = false;
+
+try {
+ assert.throws(Error, function() {
+ throw new TypeError();
+ });
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-throws-native.js b/js/src/tests/test262/harness/assert-throws-native.js
new file mode 100644
index 0000000000..a386264fbc
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-throws-native.js
@@ -0,0 +1,38 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Functions that throw instances of the specified native Error constructor
+ satisfy the assertion.
+---*/
+
+assert.throws(Error, function() {
+ throw new Error();
+});
+
+assert.throws(EvalError, function() {
+ throw new EvalError();
+});
+
+assert.throws(RangeError, function() {
+ throw new RangeError();
+});
+
+assert.throws(ReferenceError, function() {
+ throw new ReferenceError();
+});
+
+assert.throws(SyntaxError, function() {
+ throw new SyntaxError();
+});
+
+assert.throws(TypeError, function() {
+ throw new TypeError();
+});
+
+assert.throws(URIError, function() {
+ throw new URIError();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-throws-no-arg.js b/js/src/tests/test262/harness/assert-throws-no-arg.js
new file mode 100644
index 0000000000..5a10d49ed4
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-throws-no-arg.js
@@ -0,0 +1,27 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ The assertion fails when invoked without arguments.
+---*/
+
+var threw = false;
+
+try {
+ assert.throws();
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-throws-no-error.js b/js/src/tests/test262/harness/assert-throws-no-error.js
new file mode 100644
index 0000000000..35dc32a79f
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-throws-no-error.js
@@ -0,0 +1,27 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Functions that do not throw errors do not satisfy the assertion.
+---*/
+
+var threw = false;
+
+try {
+ assert.throws(Error, function() {});
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-throws-null-fn.js b/js/src/tests/test262/harness/assert-throws-null-fn.js
new file mode 100644
index 0000000000..d37737c52f
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-throws-null-fn.js
@@ -0,0 +1,63 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Fails if second arg is not a function
+---*/
+
+var threw = false;
+
+try {
+ assert.throws(TypeError, null);
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+threw = false;
+
+try {
+ assert.throws(TypeError, {});
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+threw = false;
+
+try {
+ assert.throws(TypeError, "");
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-throws-null.js b/js/src/tests/test262/harness/assert-throws-null.js
new file mode 100644
index 0000000000..3755e86150
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-throws-null.js
@@ -0,0 +1,29 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Functions that throw the `null` value do not satisfy the assertion.
+---*/
+
+var threw = false;
+
+try {
+ assert.throws(Error, function() {
+ throw null;
+ });
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-throws-primitive.js b/js/src/tests/test262/harness/assert-throws-primitive.js
new file mode 100644
index 0000000000..e53e264021
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-throws-primitive.js
@@ -0,0 +1,28 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Functions that throw primitive values do not satisfy the assertion.
+---*/
+var threw = false;
+
+try {
+ assert.throws(Error, function() {
+ throw 3;
+ });
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-throws-same-realm.js b/js/src/tests/test262/harness/assert-throws-same-realm.js
new file mode 100644
index 0000000000..7d95dda5e4
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-throws-same-realm.js
@@ -0,0 +1,32 @@
+// Copyright (C) 2021 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Functions that throw instances of the realm specified constructor function
+ do not satisfy the assertion with cross realms collisions.
+---*/
+
+var intrinsicTypeError = TypeError;
+var threw = false;
+var realmGlobal = $262.createRealm().global;
+
+try {
+ assert.throws(TypeError, function() {
+ throw new realmGlobal.TypeError();
+ });
+} catch (err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-throws-single-arg.js b/js/src/tests/test262/harness/assert-throws-single-arg.js
new file mode 100644
index 0000000000..30e42a7c26
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-throws-single-arg.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ The assertion fails when invoked with a single argument.
+---*/
+var threw = false;
+
+try {
+ assert.throws(function() {});
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-tostring.js b/js/src/tests/test262/harness/assert-tostring.js
new file mode 100644
index 0000000000..351607b020
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-tostring.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2019 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ When composing a message, errors from ToString are handled.
+features: [async-functions]
+---*/
+
+var threw = false;
+var asyncFunProto = Object.getPrototypeOf(async function() {});
+
+try {
+ assert(asyncFunProto);
+} catch (err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error('Expected a Test262Error, but a "' + err.constructor.name + '" was thrown.');
+ }
+}
+
+if (!threw) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assert-true.js b/js/src/tests/test262/harness/assert-true.js
new file mode 100644
index 0000000000..0024290924
--- /dev/null
+++ b/js/src/tests/test262/harness/assert-true.js
@@ -0,0 +1,11 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ `true` satisfies the assertion.
+---*/
+
+assert(true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/assertRelativeDateMs.js b/js/src/tests/test262/harness/assertRelativeDateMs.js
new file mode 100644
index 0000000000..564128df73
--- /dev/null
+++ b/js/src/tests/test262/harness/assertRelativeDateMs.js
@@ -0,0 +1,82 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: >
+ Only passes when the provided date is exactly the specified number of
+ milliseconds from the Unix epoch
+includes: [assertRelativeDateMs.js]
+---*/
+
+var thrown;
+
+assertRelativeDateMs(new Date(1970, 0), 0);
+assertRelativeDateMs(new Date(1970, 0, 1, 0, 0, 0, 0), 0);
+assertRelativeDateMs(new Date(1970, 0, 1, 0, 0, 0, 1), 1);
+assertRelativeDateMs(new Date(1970, 0, 1, 0, 0, 0, -1), -1);
+assertRelativeDateMs(new Date(1970, 0, 1, 0, 0, 1, 0), 1000);
+assertRelativeDateMs(new Date(1970, 0, 1, 0, 0, -1, 0), -1000);
+assertRelativeDateMs(new Date(1970, 0, 1, 0, 2, 0, 0), 120000);
+assertRelativeDateMs(new Date(1970, 0, 1, 0, -2, 0, 0), -120000);
+assertRelativeDateMs(new Date(2016, 3, 12, 13, 21, 23, 24), 1460467283024);
+
+thrown = null;
+try {
+ assertRelativeDateMs(new Date(1), 0);
+} catch (err) {
+ thrown = err;
+}
+if (!thrown) {
+ throw new Error('Expected error, but no error was thrown.');
+} else if (thrown.constructor !== Test262Error) {
+ throw new Error('Expected error of type Test262Error.');
+}
+
+thrown = null;
+try {
+ assertRelativeDateMs(new Date(-1), 0);
+} catch (err) {
+ thrown = err;
+}
+if (!thrown) {
+ throw new Error('Expected error, but no error was thrown.');
+} else if (thrown.constructor !== Test262Error) {
+ throw new Error('Expected error of type Test262Error.');
+}
+
+thrown = null;
+try {
+ assertRelativeDateMs(new Date(1970, 0), 1);
+} catch (err) {
+ thrown = err;
+}
+if (!thrown) {
+ throw new Error('Expected error, but no error was thrown.');
+} else if (thrown.constructor !== Test262Error) {
+ throw new Error('Expected error of type Test262Error.');
+}
+
+thrown = null;
+try {
+ assertRelativeDateMs(new Date(1970, 0), -1);
+} catch (err) {
+ thrown = err;
+}
+if (!thrown) {
+ throw new Error('Expected error, but no error was thrown.');
+} else if (thrown.constructor !== Test262Error) {
+ throw new Error('Expected error of type Test262Error.');
+}
+
+thrown = null;
+try {
+ assertRelativeDateMs(new Date('invalid'), NaN);
+} catch (err) {
+ thrown = err;
+}
+if (!thrown) {
+ throw new Error('Expected error, but no error was thrown.');
+} else if (thrown.constructor !== Test262Error) {
+ throw new Error('Expected error of type Test262Error.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/asyncHelpers-asyncTest-func-throws-sync.js b/js/src/tests/test262/harness/asyncHelpers-asyncTest-func-throws-sync.js
new file mode 100644
index 0000000000..fb98ba20e5
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-asyncTest-func-throws-sync.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ The 'asyncTest' helper reports synchronous errors via $DONE.
+includes: [asyncHelpers.js]
+---*/
+var called = false;
+var msg = "Should not be rethrown";
+function $DONE(error) {
+ called = true;
+ assert(error instanceof Test262Error);
+ assert.sameValue(error.message, msg, "Should report correct error");
+}
+asyncTest(function () {
+ throw new Test262Error(msg);
+});
+assert(called, "asyncTest called $DONE with a synchronously thrown error");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/asyncHelpers-asyncTest-rejects-non-callable.js b/js/src/tests/test262/harness/asyncHelpers-asyncTest-rejects-non-callable.js
new file mode 100644
index 0000000000..6737199524
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-asyncTest-rejects-non-callable.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ The 'asyncTest' helper rejects non-callable test functions.
+includes: [asyncHelpers.js, compareArray.js]
+---*/
+
+const doneValues = [];
+function $DONE(error) {
+ doneValues.push(error instanceof Test262Error);
+}
+asyncTest(null);
+asyncTest({});
+asyncTest("string");
+asyncTest(42);
+asyncTest(undefined);
+asyncTest();
+assert.compareArray(doneValues, [true, true, true, true, true, true]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/asyncHelpers-asyncTest-return-not-thenable.js b/js/src/tests/test262/harness/asyncHelpers-asyncTest-return-not-thenable.js
new file mode 100644
index 0000000000..f752faa992
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-asyncTest-return-not-thenable.js
@@ -0,0 +1,32 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ The 'asyncTest' helper rejects test functions that do not return a thenable.
+includes: [asyncHelpers.js, compareArray.js]
+---*/
+
+const doneValues = [];
+function $DONE(error) {
+ // Will be a TypeError from trying to invoke .then() on non-thenable
+ doneValues.push(error instanceof TypeError);
+}
+asyncTest(function () {
+ return null;
+});
+asyncTest(function () {
+ return {};
+});
+asyncTest(function () {
+ return "string";
+});
+asyncTest(function () {
+ return 42;
+});
+asyncTest(function () {});
+asyncTest(function () {
+ return function () {};
+});
+assert.compareArray(doneValues, [true, true, true, true, true, true]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/asyncHelpers-asyncTest-returns-undefined.js b/js/src/tests/test262/harness/asyncHelpers-asyncTest-returns-undefined.js
new file mode 100644
index 0000000000..18d78f092a
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-asyncTest-returns-undefined.js
@@ -0,0 +1,40 @@
+// |reftest| async
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ The 'asyncTest' helper when called with async flag always returns undefined.
+flags: [async]
+includes: [asyncHelpers.js]
+---*/
+var realDone = $DONE;
+var doneCalls = 0;
+globalThis.$DONE = function () {
+ doneCalls++;
+};
+
+(async function () {
+ assert.sameValue(undefined, asyncTest({}));
+ assert.sameValue(
+ undefined,
+ asyncTest(function () {
+ return "non-thenable";
+ })
+ );
+ assert.sameValue(
+ undefined,
+ asyncTest(function () {
+ return Promise.resolve(true);
+ })
+ );
+ assert.sameValue(
+ undefined,
+ asyncTest(function () {
+ return Promise.reject(new Test262Error("oh no"));
+ })
+ );
+})()
+ .then(() => {
+ assert.sameValue(doneCalls, 4, "asyncTest must call $DONE");
+ })
+ .then(realDone, realDone);
diff --git a/js/src/tests/test262/harness/asyncHelpers-asyncTest-then-rejects.js b/js/src/tests/test262/harness/asyncHelpers-asyncTest-then-rejects.js
new file mode 100644
index 0000000000..6b20dfb2c2
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-asyncTest-then-rejects.js
@@ -0,0 +1,49 @@
+// |reftest| async
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ The 'asyncTest' helper calls $DONE with the rejection value if the test function rejects.
+flags: [async]
+includes: [asyncHelpers.js, compareArray.js]
+---*/
+const rejectionValues = [];
+var realDone = $DONE;
+globalThis.$DONE = function (mustBeDefined) {
+ rejectionValues.push(mustBeDefined);
+};
+const someObject = {};
+
+(async function () {
+ asyncTest(function () {
+ return Promise.reject(null);
+ });
+})()
+ .then(() => {
+ asyncTest(function () {
+ return Promise.reject(someObject);
+ });
+ })
+ .then(() => {
+ asyncTest(function () {
+ return Promise.reject("hi");
+ });
+ })
+ .then(() => {
+ asyncTest(function () {
+ return Promise.reject(10);
+ });
+ })
+ .then(() => {
+ asyncTest(function () {
+ return {
+ then(res, rej) {
+ rej(true);
+ },
+ };
+ });
+ })
+ .then(() => {
+ assert.compareArray(rejectionValues, [null, someObject, "hi", 10, true]);
+ })
+ .then(realDone, realDone);
diff --git a/js/src/tests/test262/harness/asyncHelpers-asyncTest-then-resolves.js b/js/src/tests/test262/harness/asyncHelpers-asyncTest-then-resolves.js
new file mode 100644
index 0000000000..ae080975ce
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-asyncTest-then-resolves.js
@@ -0,0 +1,57 @@
+// |reftest| async
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ The 'asyncTest' helper calls $DONE with undefined, regardless of what value the promise resolves with
+flags: [async]
+includes: [asyncHelpers.js]
+---*/
+var doneCalls = 0;
+var realDone = $DONE;
+globalThis.$DONE = function (noError) {
+ doneCalls++;
+ assert.sameValue(
+ noError,
+ undefined,
+ "asyncTest should discard promise's resolved value"
+ );
+};
+
+(async function () {
+ asyncTest(function () {
+ return Promise.resolve(null);
+ });
+})()
+ .then(() => {
+ assert.sameValue(doneCalls, 1, "asyncTest called $DONE with undefined");
+ asyncTest(function () {
+ return Promise.resolve({});
+ });
+ })
+ .then(() => {
+ assert.sameValue(doneCalls, 2, "asyncTest called $DONE with undefined");
+ asyncTest(function () {
+ return Promise.resolve("hi");
+ });
+ })
+ .then(() => {
+ assert.sameValue(doneCalls, 3, "asyncTest called $DONE with undefined");
+ asyncTest(function () {
+ return Promise.resolve(10);
+ });
+ })
+ .then(() => {
+ assert.sameValue(doneCalls, 4, "asyncTest called $DONE with undefined");
+ asyncTest(function () {
+ return {
+ then(res, rej) {
+ res(true);
+ },
+ };
+ });
+ })
+ .then(() => {
+ assert.sameValue(doneCalls, 5, "asyncTest called $DONE with undefined");
+ })
+ .then(realDone, realDone);
diff --git a/js/src/tests/test262/harness/asyncHelpers-asyncTest-without-async-flag.js b/js/src/tests/test262/harness/asyncHelpers-asyncTest-without-async-flag.js
new file mode 100644
index 0000000000..b7b0e4f733
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-asyncTest-without-async-flag.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ The 'asyncTest' helper checks that it is called with the 'async' flag.
+includes: [asyncHelpers.js]
+---*/
+function makePromise() {
+ return {
+ then(res, rej) {
+ // Throw a different error than Test262Error to avoid confusion about what is rejecting
+ throw new Error("Should not be evaluated");
+ },
+ };
+}
+assert(
+ !Object.hasOwn(globalThis, "$DONE"),
+ "Without 'async' flag, $DONE should not be defined"
+);
+assert.throws(Test262Error, function () {
+ asyncTest(makePromise);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/asyncHelpers-throwsAsync-custom-typeerror.js b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-custom-typeerror.js
new file mode 100644
index 0000000000..9cc1b95953
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-custom-typeerror.js
@@ -0,0 +1,73 @@
+// |reftest| async
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Thenables that reject with instances of the specified constructor function
+ satisfy the assertion, without collision with error constructors of the same name.
+flags: [async]
+includes: [asyncHelpers.js]
+---*/
+
+var intrinsicTypeError = TypeError;
+
+asyncTest(async function () {
+ function TypeError() {}
+ var caught = false;
+
+ var p = assert.throwsAsync(
+ TypeError,
+ async function () {
+ throw new TypeError();
+ },
+ "Throws an instance of the matching custom TypeError"
+ );
+ assert(p instanceof Promise);
+ await p;
+
+ p = assert.throwsAsync(intrinsicTypeError, async function () {
+ throw new TypeError();
+ });
+ assert(p instanceof Promise);
+ try {
+ await p;
+ } catch (err) {
+ caught = true;
+ assert.sameValue(
+ err.constructor,
+ Test262Error,
+ "Expected a Test262Error, but a '" +
+ err.constructor.name +
+ "' was thrown."
+ );
+ } finally {
+ assert(
+ caught,
+ "assert.throwsAsync did not reject a collision of constructor names"
+ );
+ }
+
+ caught = false;
+
+ p = assert.throwsAsync(TypeError, async function () {
+ throw new intrinsicTypeError();
+ });
+ assert(p instanceof Promise);
+ try {
+ await p;
+ } catch (err) {
+ caught = true;
+ assert.sameValue(
+ err.constructor,
+ Test262Error,
+ "Expected a Test262Error, but a '" +
+ err.constructor.name +
+ "' was thrown."
+ );
+ } finally {
+ assert(
+ caught,
+ "assert.throwsAsync did not reject a collision of constructor names"
+ );
+ }
+})
diff --git a/js/src/tests/test262/harness/asyncHelpers-throwsAsync-custom.js b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-custom.js
new file mode 100644
index 0000000000..44614a4f7f
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-custom.js
@@ -0,0 +1,20 @@
+// |reftest| async
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Thenables that reject with values of the specified constructor function
+ satisfy the assertion.
+flags: [async]
+includes: [asyncHelpers.js]
+---*/
+
+function MyError() {}
+
+asyncTest(async function () {
+ const p = assert.throwsAsync(MyError, function () {
+ return Promise.reject(new MyError());
+ });
+ assert(p instanceof Promise);
+ await p;
+});
diff --git a/js/src/tests/test262/harness/asyncHelpers-throwsAsync-func-throws-sync.js b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-func-throws-sync.js
new file mode 100644
index 0000000000..a7802e2e8e
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-func-throws-sync.js
@@ -0,0 +1,53 @@
+// |reftest| async
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ assert.throwsAsync returns a promise that rejects if func or the inner thenable synchronously throws.
+flags: [async]
+includes: [asyncHelpers.js]
+---*/
+
+async function checkRejects(func) {
+ var caught = false;
+ const p = assert.throwsAsync(Test262Error, func);
+ assert(p instanceof Promise, "assert.throwsAsync should return a promise");
+ try {
+ await p;
+ } catch (e) {
+ caught = true;
+ assert.sameValue(
+ e.constructor,
+ Test262Error,
+ "throwsAsync should reject improper function with a Test262Error"
+ );
+ } finally {
+ assert(
+ caught,
+ "assert.throwsAsync did not reject improper function " + func
+ );
+ }
+}
+
+asyncTest(async function () {
+ await checkRejects(function () {
+ throw new Error();
+ });
+ await checkRejects(function () {
+ throw new Test262Error();
+ });
+ await checkRejects(function () {
+ return {
+ then: function () {
+ throw new Error();
+ },
+ };
+ });
+ await checkRejects(function () {
+ return {
+ then: function () {
+ throw new Test262Error();
+ },
+ };
+ });
+});
diff --git a/js/src/tests/test262/harness/asyncHelpers-throwsAsync-incorrect-ctor.js b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-incorrect-ctor.js
new file mode 100644
index 0000000000..a71d27bf97
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-incorrect-ctor.js
@@ -0,0 +1,36 @@
+// |reftest| async
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Thenables that reject with values whose constructor does not match the specified
+ constructor do not satisfy the assertion.
+flags: [async]
+includes: [asyncHelpers.js]
+---*/
+
+asyncTest(async function () {
+ var caught = false;
+
+ const p = assert.throwsAsync(Error, function () {
+ return Promise.reject(new TypeError());
+ });
+ assert(p instanceof Promise);
+ try {
+ await p;
+ } catch (err) {
+ caught = true;
+ assert.sameValue(
+ err.constructor,
+ Test262Error,
+ "Expected a Test262Error, but a '" +
+ err.constructor.name +
+ "' was thrown."
+ );
+ } finally {
+ assert(
+ caught,
+ "assert.throwsAsync did not reject when a value with incorrect constructor was thrown"
+ );
+ }
+});
diff --git a/js/src/tests/test262/harness/asyncHelpers-throwsAsync-invalid-func.js b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-invalid-func.js
new file mode 100644
index 0000000000..9ada348f80
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-invalid-func.js
@@ -0,0 +1,71 @@
+// |reftest| async
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ assert.throwsAsync calls $DONE with a rejecting value if func is not a function returning a thenable.
+flags: [async]
+includes: [asyncHelpers.js]
+---*/
+
+async function checkRejects(func) {
+ var caught = false;
+ const p = assert.throwsAsync(Test262Error, func);
+ assert(p instanceof Promise, "assert.throwsAsync should return a promise");
+ try {
+ await p;
+ } catch (e) {
+ caught = true;
+ assert.sameValue(
+ e.constructor,
+ Test262Error,
+ "throwsAsync should reject improper function with a Test262Error"
+ );
+ } finally {
+ assert(
+ caught,
+ "assert.throwsAsync did not reject improper function " + func
+ );
+ }
+}
+
+asyncTest(async function () {
+ await checkRejects(null);
+ await checkRejects({});
+ await checkRejects("string");
+ await checkRejects(10);
+ await checkRejects();
+ await checkRejects({
+ then: function (res, rej) {
+ res(true);
+ },
+ });
+ await checkRejects(function () {
+ return null;
+ });
+ await checkRejects(function () {
+ return {};
+ });
+ await checkRejects(function () {
+ return "string";
+ });
+ await checkRejects(function () {
+ return 10;
+ });
+ await checkRejects(function () {});
+ await checkRejects(function () {
+ return { then: null };
+ });
+ await checkRejects(function () {
+ return { then: {} };
+ });
+ await checkRejects(function () {
+ return { then: "string" };
+ });
+ await checkRejects(function () {
+ return { then: 10 };
+ });
+ await checkRejects(function () {
+ return { then: undefined };
+ });
+});
diff --git a/js/src/tests/test262/harness/asyncHelpers-throwsAsync-native.js b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-native.js
new file mode 100644
index 0000000000..482cc4f017
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-native.js
@@ -0,0 +1,48 @@
+// |reftest| async
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Thenables that reject with instances of the specified native Error constructor
+ satisfy the assertion.
+flags: [async]
+includes: [asyncHelpers.js]
+---*/
+
+asyncTest(async function () {
+ var p = assert.throwsAsync(Error, async function () {
+ throw new Error();
+ });
+ assert(p instanceof Promise);
+ await p;
+ p = assert.throwsAsync(EvalError, async function () {
+ throw new EvalError();
+ });
+ assert(p instanceof Promise);
+ await p;
+ p = assert.throwsAsync(RangeError, async function () {
+ throw new RangeError();
+ });
+ assert(p instanceof Promise);
+ await p;
+ p = assert.throwsAsync(ReferenceError, async function () {
+ throw new ReferenceError();
+ });
+ assert(p instanceof Promise);
+ await p;
+ p = assert.throwsAsync(SyntaxError, async function () {
+ throw new SyntaxError();
+ });
+ assert(p instanceof Promise);
+ await p;
+ p = assert.throwsAsync(TypeError, async function () {
+ throw new TypeError();
+ });
+ assert(p instanceof Promise);
+ await p;
+ p = assert.throwsAsync(URIError, async function () {
+ throw new URIError();
+ });
+ assert(p instanceof Promise);
+ await p;
+});
diff --git a/js/src/tests/test262/harness/asyncHelpers-throwsAsync-no-arg.js b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-no-arg.js
new file mode 100644
index 0000000000..6efb08c864
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-no-arg.js
@@ -0,0 +1,33 @@
+// |reftest| async
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ The assertion fails when invoked without arguments.
+flags: [async]
+includes: [asyncHelpers.js]
+---*/
+
+asyncTest(async function () {
+ var caught = false;
+
+ const p = assert.throwsAsync();
+ assert(p instanceof Promise);
+ try {
+ await p;
+ } catch (err) {
+ caught = true;
+ assert.sameValue(
+ err.constructor,
+ Test262Error,
+ "Expected a Test262Error, but a '" +
+ err.constructor.name +
+ "' was thrown."
+ );
+ } finally {
+ assert(
+ caught,
+ "assert.throwsAsync did not reject when invoked without arguments"
+ );
+ }
+});
diff --git a/js/src/tests/test262/harness/asyncHelpers-throwsAsync-no-error.js b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-no-error.js
new file mode 100644
index 0000000000..5ac284248e
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-no-error.js
@@ -0,0 +1,33 @@
+// |reftest| async
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Thenables that do not reject do not satisfy the assertion.
+flags: [async]
+includes: [asyncHelpers.js]
+---*/
+
+asyncTest(async function () {
+ var caught = false;
+
+ const p = assert.throwsAsync(Error, async function () {});
+ assert(p instanceof Promise);
+ try {
+ await p;
+ } catch (err) {
+ caught = true;
+ assert.sameValue(
+ err.constructor,
+ Test262Error,
+ "Expected a Test262Error, but a '" +
+ err.constructor.name +
+ "' was thrown."
+ );
+ } finally {
+ assert(
+ caught,
+ "assert.throwsAsync did not reject when the thenable did not reject"
+ );
+ }
+});
diff --git a/js/src/tests/test262/harness/asyncHelpers-throwsAsync-null.js b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-null.js
new file mode 100644
index 0000000000..09ed3f4d75
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-null.js
@@ -0,0 +1,35 @@
+// |reftest| async
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Thenables that reject with the `null` value do not satisfy the assertion.
+flags: [async]
+includes: [asyncHelpers.js]
+---*/
+
+asyncTest(async function () {
+ var caught = false;
+
+ const p = assert.throwsAsync(Error, async function () {
+ throw null;
+ });
+ assert(p instanceof Promise);
+ try {
+ await p;
+ } catch (err) {
+ caught = true;
+ assert.sameValue(
+ err.constructor,
+ Test262Error,
+ "Expected a Test262Error, but a '" +
+ err.constructor.name +
+ "' was thrown."
+ );
+ } finally {
+ assert(
+ caught,
+ "assert.throwsAsync did not reject when null was thrown"
+ );
+ }
+});
diff --git a/js/src/tests/test262/harness/asyncHelpers-throwsAsync-primitive.js b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-primitive.js
new file mode 100644
index 0000000000..004c63c970
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-primitive.js
@@ -0,0 +1,35 @@
+// |reftest| async
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Thenables that reject with primitive values do not satisfy the assertion.
+flags: [async]
+includes: [asyncHelpers.js]
+---*/
+
+asyncTest(async function () {
+ var caught = false;
+
+ const p = assert.throwsAsync(Error, async function () {
+ throw 3;
+ });
+ assert(p instanceof Promise);
+ try {
+ await p;
+ } catch (err) {
+ caught = true;
+ assert.sameValue(
+ err.constructor,
+ Test262Error,
+ "Expected a Test262Error, but a '" +
+ err.constructor.name +
+ "' was thrown."
+ );
+ } finally {
+ assert(
+ caught,
+ "assert.throwsAsync did not reject when a primitive was thrown"
+ );
+ }
+});
diff --git a/js/src/tests/test262/harness/asyncHelpers-throwsAsync-resolved-error.js b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-resolved-error.js
new file mode 100644
index 0000000000..734b3c166c
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-resolved-error.js
@@ -0,0 +1,36 @@
+// |reftest| async
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Thenables that resolve with an error do not satisfy the assertion.
+flags: [async]
+includes: [asyncHelpers.js]
+---*/
+
+asyncTest(async function () {
+ var caught = false;
+
+ const p = assert.throwsAsync(
+ Error,
+ Promise.resolve(new Error("it's-a-me, Chris Pratt"))
+ );
+ assert(p instanceof Promise);
+ try {
+ await p;
+ } catch (err) {
+ caught = true;
+ assert.sameValue(
+ err.constructor,
+ Test262Error,
+ "Expected a Test262Error, but a '" +
+ err.constructor.name +
+ "' was thrown."
+ );
+ } finally {
+ assert(
+ caught,
+ "assert.throwsAsync did not reject when the thenable resolved with an error"
+ );
+ }
+});
diff --git a/js/src/tests/test262/harness/asyncHelpers-throwsAsync-same-realm.js b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-same-realm.js
new file mode 100644
index 0000000000..cf72bd0895
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-same-realm.js
@@ -0,0 +1,38 @@
+// |reftest| async
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Thenables that reject with instances of the realm specified constructor function
+ do not satisfy the assertion with cross realms collisions.
+flags: [async]
+includes: [asyncHelpers.js]
+---*/
+
+asyncTest(async function () {
+ var intrinsicTypeError = TypeError;
+ var caught = false;
+ var realmGlobal = $262.createRealm().global;
+
+ const p = assert.throwsAsync(TypeError, async function () {
+ throw new realmGlobal.TypeError();
+ });
+ assert(p instanceof Promise);
+ try {
+ await p;
+ } catch (err) {
+ caught = true;
+ assert.sameValue(
+ err.constructor,
+ Test262Error,
+ "Expected a Test262Error, but a '" +
+ err.constructor.name +
+ "' was thrown."
+ );
+ } finally {
+ assert(
+ caught,
+ "assert.throwsAsync did not reject when a different realm's error was thrown"
+ );
+ }
+});
diff --git a/js/src/tests/test262/harness/asyncHelpers-throwsAsync-single-arg.js b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-single-arg.js
new file mode 100644
index 0000000000..6dcf9b55e6
--- /dev/null
+++ b/js/src/tests/test262/harness/asyncHelpers-throwsAsync-single-arg.js
@@ -0,0 +1,32 @@
+// |reftest| async
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ assert.throwsAsync returns a promise that rejects when invoked with a single argument
+flags: [async]
+includes: [asyncHelpers.js]
+---*/
+
+asyncTest(async function () {
+ var caught = false;
+ const p = assert.throwsAsync(function () {});
+ assert(p instanceof Promise);
+ try {
+ await p;
+ } catch (err) {
+ caught = true;
+ assert.sameValue(
+ err.constructor,
+ Test262Error,
+ "Expected a Test262Error, but a '" +
+ err.constructor.name +
+ "' was thrown."
+ );
+ } finally {
+ assert(
+ caught,
+ "assert.throwsAsync did not reject when invoked with a single argumemnt"
+ );
+ }
+});
diff --git a/js/src/tests/test262/harness/browser.js b/js/src/tests/test262/harness/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/harness/browser.js
diff --git a/js/src/tests/test262/harness/byteConversionValues.js b/js/src/tests/test262/harness/byteConversionValues.js
new file mode 100644
index 0000000000..f7cf7449e9
--- /dev/null
+++ b/js/src/tests/test262/harness/byteConversionValues.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2016 The V8 Project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Ensure the original and expected values are set properly
+includes: [byteConversionValues.js]
+---*/
+
+var values = byteConversionValues.values;
+var expected = byteConversionValues.expected;
+
+assert(values.length > 0);
+assert.sameValue(values.length, expected.Float32.length, "Float32");
+assert.sameValue(values.length, expected.Float64.length, "Float64");
+assert.sameValue(values.length, expected.Int8.length, "Int8");
+assert.sameValue(values.length, expected.Int16.length, "Int16");
+assert.sameValue(values.length, expected.Int32.length, "Int32");
+assert.sameValue(values.length, expected.Uint8.length, "Uint8");
+assert.sameValue(values.length, expected.Uint16.length, "Uint16");
+assert.sameValue(values.length, expected.Uint32.length, "Uint32");
+assert.sameValue(values.length, expected.Uint8Clamped.length, "Uint8Clamped");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/compare-array-arguments.js b/js/src/tests/test262/harness/compare-array-arguments.js
new file mode 100644
index 0000000000..cee5cedcfd
--- /dev/null
+++ b/js/src/tests/test262/harness/compare-array-arguments.js
@@ -0,0 +1,40 @@
+// Copyright (C) 2021 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Accepts spreadable arguments
+includes: [compareArray.js]
+---*/
+
+const fixture = [0, 'a', undefined];
+
+function checkFormatOfAssertionMessage(func, errorMessage) {
+ var caught = false;
+ try {
+ func();
+ } catch (error) {
+ caught = true;
+ assert.sameValue(error.constructor, Test262Error);
+ assert.sameValue(error.message, errorMessage);
+ }
+
+ assert(caught, `Expected ${func} to throw, but it didn't.`);
+}
+
+function f() {
+ assert.compareArray(arguments, fixture);
+ assert.compareArray(fixture, arguments);
+
+ checkFormatOfAssertionMessage(() => {
+ assert.compareArray(arguments, [], 'arguments and []');
+ }, 'Expected [0, a, undefined] and [] to have the same contents. arguments and []');
+
+ checkFormatOfAssertionMessage(() => {
+ assert.compareArray([], arguments, '[] and arguments');
+ }, 'Expected [] and [0, a, undefined] to have the same contents. [] and arguments');
+}
+
+f(...fixture);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/compare-array-arraylike.js b/js/src/tests/test262/harness/compare-array-arraylike.js
new file mode 100644
index 0000000000..6f1ea8242b
--- /dev/null
+++ b/js/src/tests/test262/harness/compare-array-arraylike.js
@@ -0,0 +1,36 @@
+// Copyright (C) 2021 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Accepts spreadable arguments
+includes: [compareArray.js]
+---*/
+
+function checkFormatOfAssertionMessage(func, errorMessage) {
+ var caught = false;
+ try {
+ func();
+ } catch (error) {
+ caught = true;
+ assert.sameValue(error.constructor, Test262Error);
+ assert.sameValue(error.message, errorMessage);
+ }
+
+ assert(caught, `Expected ${func} to throw, but it didn't.`);
+}
+
+const fixture = { length: 3, 0: 0, 1: 'a', 2: undefined};
+
+assert.compareArray(fixture, [0, 'a', undefined]);
+assert.compareArray([0, 'a', undefined], fixture);
+
+checkFormatOfAssertionMessage(() => {
+ assert.compareArray(fixture, [], 'fixture and []');
+}, 'Expected [0, a, undefined] and [] to have the same contents. fixture and []');
+
+checkFormatOfAssertionMessage(() => {
+ assert.compareArray([], fixture, '[] and fixture');
+}, 'Expected [] and [0, a, undefined] to have the same contents. [] and fixture');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/compare-array-different-elements.js b/js/src/tests/test262/harness/compare-array-different-elements.js
new file mode 100644
index 0000000000..6ff8fdf048
--- /dev/null
+++ b/js/src/tests/test262/harness/compare-array-different-elements.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Arrays containing different elements are not equivalent.
+includes: [compareArray.js]
+---*/
+
+var first = [0, 'a', undefined];
+var second = [0, 'b', undefined];
+
+assert.throws(Test262Error, () => {
+ assert.compareArray(first, second);
+}, 'Arrays containing different elements are not equivalent.');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/compare-array-different-length.js b/js/src/tests/test262/harness/compare-array-different-length.js
new file mode 100644
index 0000000000..87e296ed8c
--- /dev/null
+++ b/js/src/tests/test262/harness/compare-array-different-length.js
@@ -0,0 +1,19 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Arrays of differing lengths are not equivalent.
+includes: [compareArray.js]
+---*/
+
+
+assert.throws(Test262Error, () => {
+ assert.compareArray([], [undefined]);
+}, 'Arrays of differing lengths are not equivalent.');
+
+assert.throws(Test262Error, () => {
+ assert.compareArray([undefined], []);
+}, 'Arrays of differing lengths are not equivalent.');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/compare-array-empty.js b/js/src/tests/test262/harness/compare-array-empty.js
new file mode 100644
index 0000000000..b5be3531c2
--- /dev/null
+++ b/js/src/tests/test262/harness/compare-array-empty.js
@@ -0,0 +1,12 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Empty arrays of are equivalent.
+includes: [compareArray.js]
+---*/
+
+assert.compareArray([], [], 'Empty arrays are equivalent.');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/compare-array-falsy-arguments.js b/js/src/tests/test262/harness/compare-array-falsy-arguments.js
new file mode 100644
index 0000000000..1d0354312d
--- /dev/null
+++ b/js/src/tests/test262/harness/compare-array-falsy-arguments.js
@@ -0,0 +1,30 @@
+// Copyright (C) 2020 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ compareArray gracefully handles nullish arguments.
+includes: [compareArray.js]
+---*/
+
+function assertThrows(func, errorMessage) {
+ var caught = false;
+ try {
+ func();
+ } catch (error) {
+ caught = true;
+ assert.sameValue(error.constructor, Test262Error);
+ assert.sameValue(error.message, errorMessage);
+ }
+
+ assert(caught, `Expected ${func} to throw, but it didn't.`);
+}
+
+assertThrows(() => assert.compareArray(), "First argument shouldn't be nullish. ");
+assertThrows(() => assert.compareArray(null, []), "First argument shouldn't be nullish. ");
+assertThrows(() => assert.compareArray(null, [], "foo"), "First argument shouldn't be nullish. foo");
+
+assertThrows(() => assert.compareArray([]), "Second argument shouldn't be nullish. ");
+assertThrows(() => assert.compareArray([], undefined, "foo"), "Second argument shouldn't be nullish. foo");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/compare-array-message.js b/js/src/tests/test262/harness/compare-array-message.js
new file mode 100644
index 0000000000..ae2233761a
--- /dev/null
+++ b/js/src/tests/test262/harness/compare-array-message.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2021 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ compareArray can handle any value in message arg
+includes: [compareArray.js]
+features: [BigInt, Symbol]
+---*/
+
+assert.compareArray([], [], true);
+assert.compareArray([], [], 1);
+assert.compareArray([], [], 1n);
+assert.compareArray([], [], () => {});
+assert.compareArray([], [], "test262");
+assert.compareArray([], [], Symbol("1"));
+assert.compareArray([], [], {});
+assert.compareArray([], [], []);
+assert.compareArray([], [], -1);
+assert.compareArray([], [], Infinity);
+assert.compareArray([], [], -Infinity);
+assert.compareArray([], [], 0.1);
+assert.compareArray([], [], -0.1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/compare-array-same-elements-different-order.js b/js/src/tests/test262/harness/compare-array-same-elements-different-order.js
new file mode 100644
index 0000000000..51e1506eed
--- /dev/null
+++ b/js/src/tests/test262/harness/compare-array-same-elements-different-order.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Arrays containg the same elements in different order are not equivalent.
+includes: [compareArray.js]
+---*/
+
+var obj = {};
+var first = [0, 1, '', 's', null, undefined, obj];
+var second = [0, 1, '', 's', undefined, null, obj];
+
+assert.throws(Test262Error, () => {
+ assert.compareArray(first, second);
+}, 'Arrays containing the same elements in different order are not equivalent.');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/compare-array-same-elements-same-order.js b/js/src/tests/test262/harness/compare-array-same-elements-same-order.js
new file mode 100644
index 0000000000..fd2d25b5b9
--- /dev/null
+++ b/js/src/tests/test262/harness/compare-array-same-elements-same-order.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Arrays containg the same elements in the same order are equivalent.
+includes: [compareArray.js]
+---*/
+
+var obj = {};
+var first = [0, 1, '', 's', undefined, null, obj];
+var second = [0, 1, '', 's', undefined, null, obj];
+
+assert.compareArray(first, second, 'Arrays containing the same elements in the same order are equivalent.');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/compare-array-samevalue.js b/js/src/tests/test262/harness/compare-array-samevalue.js
new file mode 100644
index 0000000000..7a17aea81c
--- /dev/null
+++ b/js/src/tests/test262/harness/compare-array-samevalue.js
@@ -0,0 +1,15 @@
+// Copyright (C) 2019 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ compareArray uses SameValue for value comparison.
+includes: [compareArray.js]
+---*/
+
+assert.compareArray([NaN], [NaN]);
+assert.throws(Test262Error, () => {
+ assert.compareArray([0], [-0]);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/compare-array-sparse.js b/js/src/tests/test262/harness/compare-array-sparse.js
new file mode 100644
index 0000000000..cbfa79d425
--- /dev/null
+++ b/js/src/tests/test262/harness/compare-array-sparse.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Spares arrays are only equivalent if they have the same length.
+includes: [compareArray.js]
+---*/
+
+
+assert.compareArray([,], [,], 'Sparse arrays of the same length are equivalent.');
+assert.throws(Test262Error, () => {
+ assert.compareArray([,], [,,]);
+}, 'Sparse arrays of differing lengths are not equivalent.');
+assert.throws(Test262Error, () => {
+ assert.compareArray([,,], [,]);
+}, 'Sparse arrays of differing lengths are not equivalent.');
+assert.throws(Test262Error, () => {
+ assert.compareArray([,], []);
+}, 'Sparse arrays are not equivalent to empty arrays.');
+assert.throws(Test262Error, () => {
+ assert.compareArray([], [,]);
+}, 'Sparse arrays are not equivalent to empty arrays.');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/compare-array-symbol.js b/js/src/tests/test262/harness/compare-array-symbol.js
new file mode 100644
index 0000000000..24108342a1
--- /dev/null
+++ b/js/src/tests/test262/harness/compare-array-symbol.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2019 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ compareArray correctly formats Symbols in error message.
+includes: [compareArray.js]
+features: [Symbol]
+---*/
+
+var threw = false;
+
+try {
+ assert.compareArray([Symbol()], [Symbol('desc')]);
+} catch (err) {
+ threw = true;
+
+ assert.sameValue(err.constructor, Test262Error);
+ assert(err.message.indexOf('[Symbol()]') !== -1);
+ assert(err.message.indexOf('[Symbol(desc)]') !== -1);
+}
+
+assert(threw);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/dateConstants.js b/js/src/tests/test262/harness/dateConstants.js
new file mode 100644
index 0000000000..878de41577
--- /dev/null
+++ b/js/src/tests/test262/harness/dateConstants.js
@@ -0,0 +1,27 @@
+// Copyright (c) 2017 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: >
+ Including dateConstants.js will expose:
+
+ var date_1899_end = -2208988800001;
+ var date_1900_start = -2208988800000;
+ var date_1969_end = -1;
+ var date_1970_start = 0;
+ var date_1999_end = 946684799999;
+ var date_2000_start = 946684800000;
+ var date_2099_end = 4102444799999;
+ var date_2100_start = 4102444800000;
+
+includes: [dateConstants.js]
+---*/
+assert.sameValue(date_1899_end, -2208988800001);
+assert.sameValue(date_1900_start, -2208988800000);
+assert.sameValue(date_1969_end, -1);
+assert.sameValue(date_1970_start, 0);
+assert.sameValue(date_1999_end, 946684799999);
+assert.sameValue(date_2000_start, 946684800000);
+assert.sameValue(date_2099_end, 4102444799999);
+assert.sameValue(date_2100_start, 4102444800000);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/decimalToHexString.js b/js/src/tests/test262/harness/decimalToHexString.js
new file mode 100644
index 0000000000..02786495ef
--- /dev/null
+++ b/js/src/tests/test262/harness/decimalToHexString.js
@@ -0,0 +1,28 @@
+// Copyright (C) 2017 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Including decimalToHexString.js will expose two functions:
+
+ decimalToHexString
+ decimalToPercentHexString
+
+includes: [decimalToHexString.js]
+---*/
+
+assert.sameValue(decimalToHexString(-1), "FFFFFFFF");
+assert.sameValue(decimalToHexString(0.5), "0000");
+assert.sameValue(decimalToHexString(1), "0001");
+assert.sameValue(decimalToHexString(100), "0064");
+assert.sameValue(decimalToHexString(65535), "FFFF");
+assert.sameValue(decimalToHexString(65536), "10000");
+
+assert.sameValue(decimalToPercentHexString(-1), "%FF");
+assert.sameValue(decimalToPercentHexString(0.5), "%00");
+assert.sameValue(decimalToPercentHexString(1), "%01");
+assert.sameValue(decimalToPercentHexString(100), "%64");
+assert.sameValue(decimalToPercentHexString(65535), "%FF");
+assert.sameValue(decimalToPercentHexString(65536), "%00");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/deepEqual-array.js b/js/src/tests/test262/harness/deepEqual-array.js
new file mode 100644
index 0000000000..774c3c0192
--- /dev/null
+++ b/js/src/tests/test262/harness/deepEqual-array.js
@@ -0,0 +1,16 @@
+// Copyright 2019 Ron Buckton. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ array values compare correctly.
+includes: [deepEqual.js]
+---*/
+
+assert.deepEqual([], []);
+assert.deepEqual([1, "a", true], [1, "a", true]);
+
+assert.throws(Test262Error, function () { assert.deepEqual([], [1]); });
+assert.throws(Test262Error, function () { assert.deepEqual([1, "a", true], [1, "a", false]); });
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/deepEqual-circular.js b/js/src/tests/test262/harness/deepEqual-circular.js
new file mode 100644
index 0000000000..c2be2c27b9
--- /dev/null
+++ b/js/src/tests/test262/harness/deepEqual-circular.js
@@ -0,0 +1,19 @@
+// Copyright 2019 Ron Buckton. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ values compare correctly with circular references.
+includes: [deepEqual.js]
+---*/
+
+var a = { x: 1 };
+var b = { x: 1 };
+a.a = a;
+a.b = b;
+b.a = b;
+b.b = a;
+
+assert.deepEqual(a, b);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/deepEqual-deep.js b/js/src/tests/test262/harness/deepEqual-deep.js
new file mode 100644
index 0000000000..60d5cd59e4
--- /dev/null
+++ b/js/src/tests/test262/harness/deepEqual-deep.js
@@ -0,0 +1,15 @@
+// Copyright 2019 Ron Buckton. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ values compare correctly.
+includes: [deepEqual.js]
+---*/
+
+assert.deepEqual({ a: { x: 1 }, b: [true] }, { a: { x: 1 }, b: [true] });
+
+assert.throws(Test262Error, function () { assert.deepEqual({}, { a: { x: 1 }, b: [true] }); });
+assert.throws(Test262Error, function () { assert.deepEqual({ a: { x: 1 }, b: [true] }, { a: { x: 1 }, b: [false] }); });
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/deepEqual-mapset.js b/js/src/tests/test262/harness/deepEqual-mapset.js
new file mode 100644
index 0000000000..b5feef9329
--- /dev/null
+++ b/js/src/tests/test262/harness/deepEqual-mapset.js
@@ -0,0 +1,21 @@
+// Copyright 2019 Ron Buckton. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ map/set values compare correctly.
+includes: [deepEqual.js]
+---*/
+
+assert.deepEqual(new Set(), new Set());
+assert.deepEqual(new Set([1, "a", true]), new Set([1, "a", true]));
+assert.deepEqual(new Map(), new Map());
+assert.deepEqual(new Map([[1, "a"], ["b", true]]), new Map([[1, "a"], ["b", true]]));
+
+assert.throws(Test262Error, function () { assert.deepEqual(new Set([]), new Set([1])); });
+assert.throws(Test262Error, function () { assert.deepEqual(new Set([1, "a", true]), new Set([1, "a", false])); });
+assert.throws(Test262Error, function () { assert.deepEqual(new Map([]), new Map([[1, "a"], ["b", true]])); });
+assert.throws(Test262Error, function () { assert.deepEqual(new Map([[1, "a"], ["b", true]]), new Map([[1, "a"], ["b", false]])); });
+assert.throws(Test262Error, function () { assert.deepEqual(new Map([[1, "a"], ["b", true]]), new Set([[1, "a"], ["b", false]])); });
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/deepEqual-object.js b/js/src/tests/test262/harness/deepEqual-object.js
new file mode 100644
index 0000000000..53ea86fd3d
--- /dev/null
+++ b/js/src/tests/test262/harness/deepEqual-object.js
@@ -0,0 +1,17 @@
+// Copyright 2019 Ron Buckton. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ object values compare correctly.
+includes: [deepEqual.js]
+---*/
+
+
+assert.deepEqual({}, {});
+assert.deepEqual({ a: 1, b: true }, { a: 1, b: true });
+
+assert.throws(Test262Error, function () { assert.deepEqual({}, { a: 1, b: true }); });
+assert.throws(Test262Error, function () { assert.deepEqual({ a: 1, b: true }, { a: 1, b: false }); });
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/deepEqual-primitives-bigint.js b/js/src/tests/test262/harness/deepEqual-primitives-bigint.js
new file mode 100644
index 0000000000..4ed5707e89
--- /dev/null
+++ b/js/src/tests/test262/harness/deepEqual-primitives-bigint.js
@@ -0,0 +1,17 @@
+// Copyright 2019 Ron Buckton. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ primitive BigInt values compare correctly.
+features: [BigInt]
+includes: [deepEqual.js]
+---*/
+
+assert.deepEqual(1n, 1n);
+assert.deepEqual(Object(1n), 1n);
+
+assert.throws(Test262Error, function () { assert.deepEqual(1n, 1); });
+assert.throws(Test262Error, function () { assert.deepEqual(1n, 2n); });
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/deepEqual-primitives.js b/js/src/tests/test262/harness/deepEqual-primitives.js
new file mode 100644
index 0000000000..7d68de21a8
--- /dev/null
+++ b/js/src/tests/test262/harness/deepEqual-primitives.js
@@ -0,0 +1,36 @@
+// Copyright 2019 Ron Buckton. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ primitive values compare correctly.
+includes: [deepEqual.js]
+---*/
+
+/// <reference path="../../harness/assert.js" />
+/// <reference path="../../harness/deepEqual.js" />
+
+var s1 = Symbol();
+var s2 = Symbol();
+assert.deepEqual(null, null);
+assert.deepEqual(undefined, undefined);
+assert.deepEqual("a", "a");
+assert.deepEqual(1, 1);
+assert.deepEqual(true, true);
+assert.deepEqual(s1, s1);
+assert.deepEqual(Object("a"), "a");
+assert.deepEqual(Object(1), 1);
+assert.deepEqual(Object(true), true);
+assert.deepEqual(Object(s1), s1);
+
+assert.throws(Test262Error, function () { assert.deepEqual(null, 0); });
+assert.throws(Test262Error, function () { assert.deepEqual(undefined, 0); });
+assert.throws(Test262Error, function () { assert.deepEqual("", 0); });
+assert.throws(Test262Error, function () { assert.deepEqual("1", 1); });
+assert.throws(Test262Error, function () { assert.deepEqual("1", "2"); });
+assert.throws(Test262Error, function () { assert.deepEqual(true, 1); });
+assert.throws(Test262Error, function () { assert.deepEqual(true, false); });
+assert.throws(Test262Error, function () { assert.deepEqual(s1, "Symbol()"); });
+assert.throws(Test262Error, function () { assert.deepEqual(s1, s2); });
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/detachArrayBuffer-host-detachArrayBuffer.js b/js/src/tests/test262/harness/detachArrayBuffer-host-detachArrayBuffer.js
new file mode 100644
index 0000000000..f8780d1fe6
--- /dev/null
+++ b/js/src/tests/test262/harness/detachArrayBuffer-host-detachArrayBuffer.js
@@ -0,0 +1,45 @@
+// Copyright (C) 2017 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: >
+ Including detachArrayBuffer.js will expose a function:
+
+ $DETACHBUFFER
+
+ $DETACHBUFFER relies on the presence of a host definition for $262.detachArrayBuffer
+
+includes: [detachArrayBuffer.js]
+---*/
+
+var $262 = {
+ detachArrayBuffer() {
+ throw new Test262Error('$262.detachArrayBuffer called.');
+ },
+ destroy() {}
+};
+
+var ab = new ArrayBuffer(1);
+var threw = false;
+
+try {
+ $DETACHBUFFER(ab);
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+ if (err.message !== '$262.detachArrayBuffer called.') {
+ throw new Error(`Expected error message: ${err.message}`);
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/detachArrayBuffer.js b/js/src/tests/test262/harness/detachArrayBuffer.js
new file mode 100644
index 0000000000..dfd8e316e4
--- /dev/null
+++ b/js/src/tests/test262/harness/detachArrayBuffer.js
@@ -0,0 +1,35 @@
+// Copyright (C) 2017 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: >
+ Including detachArrayBuffer.js will expose a function:
+
+ $DETACHBUFFER
+
+ $DETACHBUFFER relies on the presence of a definition for $262.detachArrayBuffer.
+
+ Without a definition, calling $DETACHBUFFER will result in a ReferenceError
+---*/
+
+var ab = new ArrayBuffer(1);
+var threw = false;
+
+try {
+ $DETACHBUFFER(ab);
+} catch(err) {
+ threw = true;
+ if (err.constructor !== ReferenceError) {
+ throw new Error(
+ 'Expected a ReferenceError, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a ReferenceError, but no error was thrown.');
+}
+
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/fnGlobalObject.js b/js/src/tests/test262/harness/fnGlobalObject.js
new file mode 100644
index 0000000000..721d0b2d83
--- /dev/null
+++ b/js/src/tests/test262/harness/fnGlobalObject.js
@@ -0,0 +1,19 @@
+// Copyright (C) 2017 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: >
+ Including fnGlobalObject.js will expose a function:
+
+ fnGlobalObject
+
+ fnGlobalObject returns a reference to the global object.
+
+includes: [fnGlobalObject.js]
+---*/
+
+var gO = fnGlobalObject();
+
+assert(typeof gO === "object");
+assert.sameValue(gO, this);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/isConstructor.js b/js/src/tests/test262/harness/isConstructor.js
new file mode 100644
index 0000000000..845750e270
--- /dev/null
+++ b/js/src/tests/test262/harness/isConstructor.js
@@ -0,0 +1,34 @@
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Including isConstructor.js will expose one function:
+
+ isConstructor
+
+includes: [isConstructor.js]
+features: [generators, Reflect.construct]
+---*/
+
+assert.sameValue(typeof isConstructor, "function");
+
+assert.throws(Test262Error, () => isConstructor(), "no argument");
+assert.throws(Test262Error, () => isConstructor(undefined), "undefined");
+assert.throws(Test262Error, () => isConstructor(null), "null");
+assert.throws(Test262Error, () => isConstructor(123), "number");
+assert.throws(Test262Error, () => isConstructor(true), "boolean - true");
+assert.throws(Test262Error, () => isConstructor(false), "boolean - false");
+assert.throws(Test262Error, () => isConstructor("string"), "string");
+
+assert.throws(Test262Error, () => isConstructor({}), "Object instance");
+assert.throws(Test262Error, () => isConstructor([]), "Array instance");
+
+assert.sameValue(isConstructor(function(){}), true);
+assert.sameValue(isConstructor(function*(){}), false);
+assert.sameValue(isConstructor(() => {}), false);
+
+assert.sameValue(isConstructor(Array), true);
+assert.sameValue(isConstructor(Array.prototype.map), false);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/nans.js b/js/src/tests/test262/harness/nans.js
new file mode 100644
index 0000000000..5b6e7219d2
--- /dev/null
+++ b/js/src/tests/test262/harness/nans.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2017 Rick Waldron, 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: >
+ Including nans.js will expose:
+
+ var NaNs = [
+ NaN,
+ Number.NaN,
+ NaN * 0,
+ 0/0,
+ Infinity/Infinity,
+ -(0/0),
+ Math.pow(-1, 0.5),
+ -Math.pow(-1, 0.5),
+ Number("Not-a-Number"),
+ ];
+
+includes: [nans.js]
+---*/
+
+for (var i = 0; i < NaNs.length; i++) {
+ assert.sameValue(Number.isNaN(NaNs[i]), true, "index: " + i);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/nativeFunctionMatcher.js b/js/src/tests/test262/harness/nativeFunctionMatcher.js
new file mode 100644
index 0000000000..f5903aa710
--- /dev/null
+++ b/js/src/tests/test262/harness/nativeFunctionMatcher.js
@@ -0,0 +1,62 @@
+// Copyright (C) 2016 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Ensure that the regular expression generally distinguishes between valid
+ and invalid forms of the NativeFunction grammar production.
+includes: [nativeFunctionMatcher.js]
+---*/
+
+[
+ 'function(){[native code]}',
+ 'function(){ [native code] }',
+ 'function ( ) { [ native code ] }',
+ 'function a(){ [native code] }',
+ 'function a(){ /* } */ [native code] }',
+ `function a() {
+ // test
+ [native code]
+ /* test */
+ }`,
+ 'function(a, b = function() { []; }) { [native code] }',
+ 'function [Symbol.xyz]() { [native code] }',
+ 'function [x[y][z[d]()]]() { [native code] }',
+ 'function ["]"] () { [native code] }',
+ 'function [\']\'] () { [native code] }',
+ '/* test */ function() { [native code] }',
+ 'function() { [native code] } /* test */',
+ 'function() { [native code] } // test',
+].forEach((s) => {
+ try {
+ validateNativeFunctionSource(s);
+ } catch (unused) {
+ throw new Error(`${JSON.stringify(s)} should pass`);
+ }
+});
+
+[
+ 'native code',
+ 'function() {}',
+ 'function(){ "native code" }',
+ 'function(){ [] native code }',
+ 'function()) { [native code] }',
+ 'function(() { [native code] }',
+ 'function []] () { [native code] }',
+ 'function [[] () { [native code] }',
+ 'function ["]] () { [native code] }',
+ 'function [\']] () { [native code] }',
+ 'function() { [native code] /* }',
+ '// function() { [native code] }',
+].forEach((s) => {
+ let fail = false;
+ try {
+ validateNativeFunctionSource(s);
+ fail = true;
+ } catch (unused) {}
+ if (fail) {
+ throw new Error(`${JSON.stringify(s)} should fail`);
+ }
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/promiseHelper.js b/js/src/tests/test262/harness/promiseHelper.js
new file mode 100644
index 0000000000..cc9d2323d1
--- /dev/null
+++ b/js/src/tests/test262/harness/promiseHelper.js
@@ -0,0 +1,37 @@
+// Copyright (c) 2017 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: >
+ Including promiseHelper.js will expose a function:
+
+ checkSequence
+
+ To ensure execution order of some async chain, checkSequence accepts an array
+ of numbers, each added during some operation, and verifies that they
+ are in numeric order.
+
+includes: [promiseHelper.js]
+---*/
+
+assert(checkSequence([1, 2, 3, 4, 5]));
+
+var threw = false;
+
+try {
+ checkSequence([2, 1, 3, 4, 5]);
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/propertyhelper-verifyconfigurable-configurable-object.js b/js/src/tests/test262/harness/propertyhelper-verifyconfigurable-configurable-object.js
new file mode 100644
index 0000000000..357038135c
--- /dev/null
+++ b/js/src/tests/test262/harness/propertyhelper-verifyconfigurable-configurable-object.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2019 Bocoup. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Objects whose specified property is configurable satisfy the assertion.
+includes: [propertyHelper.js]
+---*/
+
+Object.defineProperty(this, 'Object', {
+ configurable: true,
+ value: Object
+});
+
+verifyConfigurable(this, 'Object');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/propertyhelper-verifyconfigurable-configurable.js b/js/src/tests/test262/harness/propertyhelper-verifyconfigurable-configurable.js
new file mode 100644
index 0000000000..a069e39103
--- /dev/null
+++ b/js/src/tests/test262/harness/propertyhelper-verifyconfigurable-configurable.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Objects whose specified property is configurable satisfy the assertion.
+includes: [propertyHelper.js]
+---*/
+
+var obj = {};
+Object.defineProperty(obj, 'a', {
+ configurable: true
+});
+
+verifyConfigurable(obj, 'a');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/propertyhelper-verifyconfigurable-not-configurable.js b/js/src/tests/test262/harness/propertyhelper-verifyconfigurable-not-configurable.js
new file mode 100644
index 0000000000..75e0478111
--- /dev/null
+++ b/js/src/tests/test262/harness/propertyhelper-verifyconfigurable-not-configurable.js
@@ -0,0 +1,33 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Objects whose specified property is not configurable do not satisfy the
+ assertion.
+includes: [propertyHelper.js]
+---*/
+
+var threw = false;
+var obj = {};
+Object.defineProperty(obj, 'a', {
+ configurable: false
+});
+
+try {
+ verifyConfigurable(obj, 'a');
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/propertyhelper-verifyenumerable-enumerable-symbol.js b/js/src/tests/test262/harness/propertyhelper-verifyenumerable-enumerable-symbol.js
new file mode 100644
index 0000000000..bd41012038
--- /dev/null
+++ b/js/src/tests/test262/harness/propertyhelper-verifyenumerable-enumerable-symbol.js
@@ -0,0 +1,19 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Objects whose specified symbol property is enumerable satisfy the assertion.
+includes: [propertyHelper.js]
+features: [Symbol]
+---*/
+
+var obj = {};
+var s = Symbol('1');
+Object.defineProperty(obj, s, {
+ enumerable: true
+});
+
+verifyEnumerable(obj, s);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/propertyhelper-verifyenumerable-enumerable.js b/js/src/tests/test262/harness/propertyhelper-verifyenumerable-enumerable.js
new file mode 100644
index 0000000000..c8079c9e46
--- /dev/null
+++ b/js/src/tests/test262/harness/propertyhelper-verifyenumerable-enumerable.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Objects whose specified string property is enumerable satisfy the assertion.
+includes: [propertyHelper.js]
+---*/
+
+var obj = {};
+Object.defineProperty(obj, 'a', {
+ enumerable: true
+});
+
+verifyEnumerable(obj, 'a');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/propertyhelper-verifyenumerable-not-enumerable-symbol.js b/js/src/tests/test262/harness/propertyhelper-verifyenumerable-not-enumerable-symbol.js
new file mode 100644
index 0000000000..20af8c1f0c
--- /dev/null
+++ b/js/src/tests/test262/harness/propertyhelper-verifyenumerable-not-enumerable-symbol.js
@@ -0,0 +1,34 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Objects whose specified symbol property is not enumerable do not satisfy the
+ assertion.
+includes: [propertyHelper.js]
+features: [Symbol]
+---*/
+var threw = false;
+var obj = {};
+var s = Symbol('1');
+Object.defineProperty(obj, s, {
+ enumerable: false
+});
+
+try {
+ verifyEnumerable(obj, s);
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Test262Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/propertyhelper-verifyenumerable-not-enumerable.js b/js/src/tests/test262/harness/propertyhelper-verifyenumerable-not-enumerable.js
new file mode 100644
index 0000000000..782cb34e8b
--- /dev/null
+++ b/js/src/tests/test262/harness/propertyhelper-verifyenumerable-not-enumerable.js
@@ -0,0 +1,32 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Objects whose specified string property is not enumerable do not satisfy the
+ assertion.
+includes: [propertyHelper.js]
+---*/
+var threw = false;
+var obj = {};
+Object.defineProperty(obj, 'a', {
+ enumerable: false
+});
+
+try {
+ verifyEnumerable(obj, 'a');
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Test262Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/propertyhelper-verifynotconfigurable-configurable.js b/js/src/tests/test262/harness/propertyhelper-verifynotconfigurable-configurable.js
new file mode 100644
index 0000000000..64a316fcb7
--- /dev/null
+++ b/js/src/tests/test262/harness/propertyhelper-verifynotconfigurable-configurable.js
@@ -0,0 +1,32 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Objects whose specified property is configurable do not satisfy the
+ assertion.
+includes: [propertyHelper.js]
+---*/
+var threw = false;
+var obj = {};
+Object.defineProperty(obj, 'a', {
+ configurable: true
+});
+
+try {
+ verifyNotConfigurable(obj, 'a');
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/propertyhelper-verifynotconfigurable-not-configurable.js b/js/src/tests/test262/harness/propertyhelper-verifynotconfigurable-not-configurable.js
new file mode 100644
index 0000000000..8d7436ebf6
--- /dev/null
+++ b/js/src/tests/test262/harness/propertyhelper-verifynotconfigurable-not-configurable.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Objects whose specified property is not configurable satisfy the assertion.
+includes: [propertyHelper.js]
+---*/
+
+var obj = {};
+Object.defineProperty(obj, 'a', {
+ configurable: false
+});
+
+verifyNotConfigurable(obj, 'a');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/propertyhelper-verifynotenumerable-enumerable-symbol.js b/js/src/tests/test262/harness/propertyhelper-verifynotenumerable-enumerable-symbol.js
new file mode 100644
index 0000000000..99e3d0a663
--- /dev/null
+++ b/js/src/tests/test262/harness/propertyhelper-verifynotenumerable-enumerable-symbol.js
@@ -0,0 +1,36 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Objects whose specified symbol property is enumerable do not satisfy the
+ assertion.
+includes: [propertyHelper.js]
+features: [Symbol]
+---*/
+var threw = false;
+var obj = {};
+var s = Symbol('1');
+Object.defineProperty(obj, s, {
+ enumerable: true
+});
+
+try {
+ verifyNotEnumerable(obj, s);
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Test262Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Test262Error(
+ 'Expected a Test262Error, but no error was thrown for symbol key.'
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/propertyhelper-verifynotenumerable-enumerable.js b/js/src/tests/test262/harness/propertyhelper-verifynotenumerable-enumerable.js
new file mode 100644
index 0000000000..bb8afa523e
--- /dev/null
+++ b/js/src/tests/test262/harness/propertyhelper-verifynotenumerable-enumerable.js
@@ -0,0 +1,34 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Objects whose specified string property is enumerable do not satisfy the
+ assertion.
+includes: [propertyHelper.js]
+---*/
+var threw = false;
+var obj = {};
+Object.defineProperty(obj, 'a', {
+ enumerable: true
+});
+
+try {
+ verifyNotEnumerable(obj, 'a');
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Test262Error(
+ 'Expected a Test262Error, but no error was thrown for string key.'
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/propertyhelper-verifynotenumerable-not-enumerable-symbol.js b/js/src/tests/test262/harness/propertyhelper-verifynotenumerable-not-enumerable-symbol.js
new file mode 100644
index 0000000000..f79314d261
--- /dev/null
+++ b/js/src/tests/test262/harness/propertyhelper-verifynotenumerable-not-enumerable-symbol.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Objects whose specified symbol property is not enumerable satisfy the
+ assertion.
+includes: [propertyHelper.js]
+features: [Symbol]
+---*/
+
+var obj = {};
+var s = Symbol('1');
+Object.defineProperty(obj, s, {
+ enumerable: false
+});
+
+verifyNotEnumerable(obj, s);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/propertyhelper-verifynotenumerable-not-enumerable.js b/js/src/tests/test262/harness/propertyhelper-verifynotenumerable-not-enumerable.js
new file mode 100644
index 0000000000..ee8d9dc908
--- /dev/null
+++ b/js/src/tests/test262/harness/propertyhelper-verifynotenumerable-not-enumerable.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Objects whose specified string property is not enumerable satisfy the
+ assertion.
+includes: [propertyHelper.js]
+---*/
+
+var obj = {};
+Object.defineProperty(obj, 'a', {
+ enumerable: false
+});
+
+verifyNotEnumerable(obj, 'a');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/propertyhelper-verifynotwritable-not-writable-strict.js b/js/src/tests/test262/harness/propertyhelper-verifynotwritable-not-writable-strict.js
new file mode 100644
index 0000000000..e4ff2346fa
--- /dev/null
+++ b/js/src/tests/test262/harness/propertyhelper-verifynotwritable-not-writable-strict.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Objects whose specified property is not writable satisfy the assertion.
+includes: [propertyHelper.js]
+---*/
+
+var obj = {};
+
+Object.defineProperty(obj, 'a', {
+ writable: false,
+ value: 123
+});
+
+verifyNotWritable(obj, 'a');
+
+if (obj.a !== 123) {
+ throw new Error('`verifyNotWritable` should be non-destructive.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/propertyhelper-verifynotwritable-writable.js b/js/src/tests/test262/harness/propertyhelper-verifynotwritable-writable.js
new file mode 100644
index 0000000000..18b73f3243
--- /dev/null
+++ b/js/src/tests/test262/harness/propertyhelper-verifynotwritable-writable.js
@@ -0,0 +1,32 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Objects whose specified property is writable do not satisfy the assertion.
+includes: [propertyHelper.js]
+---*/
+var threw = false;
+var obj = {};
+Object.defineProperty(obj, 'a', {
+ writable: true,
+ value: 1
+});
+
+try {
+ verifyNotWritable(obj, 'a');
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/propertyhelper-verifywritable-array-length.js b/js/src/tests/test262/harness/propertyhelper-verifywritable-array-length.js
new file mode 100644
index 0000000000..d014595fe9
--- /dev/null
+++ b/js/src/tests/test262/harness/propertyhelper-verifywritable-array-length.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2020 Alexey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ "length" property of Arrays is tested with valid value.
+includes: [propertyHelper.js]
+---*/
+
+var array = [1, 2, 3];
+
+verifyWritable(array, "length");
+
+assert.sameValue(array.length, 3, '`verifyWritable` should be non-destructive.');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/propertyhelper-verifywritable-not-writable.js b/js/src/tests/test262/harness/propertyhelper-verifywritable-not-writable.js
new file mode 100644
index 0000000000..45a5df2f6b
--- /dev/null
+++ b/js/src/tests/test262/harness/propertyhelper-verifywritable-not-writable.js
@@ -0,0 +1,32 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Objects whose specified property is not writable do not satisfy the
+ assertion.
+includes: [propertyHelper.js]
+---*/
+var threw = false;
+var obj = {};
+Object.defineProperty(obj, 'a', {
+ writable: false
+});
+
+try {
+ verifyWritable(obj, 'a');
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/propertyhelper-verifywritable-writable.js b/js/src/tests/test262/harness/propertyhelper-verifywritable-writable.js
new file mode 100644
index 0000000000..8d2b69651b
--- /dev/null
+++ b/js/src/tests/test262/harness/propertyhelper-verifywritable-writable.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Objects whose specified property is writable satisfy the assertion.
+includes: [propertyHelper.js]
+---*/
+var obj = {};
+
+Object.defineProperty(obj, 'a', {
+ writable: true,
+ value: 123
+});
+
+verifyWritable(obj, 'a');
+
+if (obj.a !== 123) {
+ throw new Error('`verifyWritable` should be non-destructive.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/proxytrapshelper-default.js b/js/src/tests/test262/harness/proxytrapshelper-default.js
new file mode 100644
index 0000000000..6ccbf7cf8d
--- /dev/null
+++ b/js/src/tests/test262/harness/proxytrapshelper-default.js
@@ -0,0 +1,42 @@
+// Copyright (C) 2016 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: allowProxyTraps helper should default throw on all the proxy trap named methods being invoked
+esid: pending
+author: Jordan Harband
+includes: [proxyTrapsHelper.js]
+---*/
+
+var traps = allowProxyTraps();
+
+function assertTrapThrows(trap) {
+ if (typeof traps[trap] !== 'function') {
+ throw new Test262Error('trap ' + trap + ' is not a function');
+ }
+ var failedToThrow = false;
+ try {
+ traps[trap]();
+ failedToThrow = true;
+ } catch (e) {}
+ if (failedToThrow) {
+ throw new Test262Error('trap ' + trap + ' did not throw an error');
+ }
+}
+
+assertTrapThrows('getPrototypeOf');
+assertTrapThrows('setPrototypeOf');
+assertTrapThrows('isExtensible');
+assertTrapThrows('preventExtensions');
+assertTrapThrows('getOwnPropertyDescriptor');
+assertTrapThrows('has');
+assertTrapThrows('get');
+assertTrapThrows('set');
+assertTrapThrows('deleteProperty');
+assertTrapThrows('defineProperty');
+assertTrapThrows('enumerate');
+assertTrapThrows('ownKeys');
+assertTrapThrows('apply');
+assertTrapThrows('construct');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/proxytrapshelper-overrides.js b/js/src/tests/test262/harness/proxytrapshelper-overrides.js
new file mode 100644
index 0000000000..32616b1bc3
--- /dev/null
+++ b/js/src/tests/test262/harness/proxytrapshelper-overrides.js
@@ -0,0 +1,77 @@
+// Copyright (C) 2016 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: allowProxyTraps helper should default throw on all the proxy trap named methods being invoked
+esid: pending
+author: Jordan Harband
+includes: [proxyTrapsHelper.js]
+---*/
+var overrides = {
+ getPrototypeOf: function () {},
+ setPrototypeOf: function () {},
+ isExtensible: function () {},
+ preventExtensions: function () {},
+ getOwnPropertyDescriptor: function () {},
+ has: function () {},
+ get: function () {},
+ set: function () {},
+ deleteProperty: function () {},
+ defineProperty: function () {},
+ enumerate: function () {},
+ ownKeys: function () {},
+ apply: function () {},
+ construct: function () {},
+};
+var traps = allowProxyTraps(overrides);
+
+function assertTrapSucceeds(trap) {
+ if (typeof traps[trap] !== 'function') {
+ throw new Test262Error('trap ' + trap + ' is not a function');
+ }
+ if (traps[trap] !== overrides[trap]) {
+ throw new Test262Error('trap ' + trap + ' was not overriden in allowProxyTraps');
+ }
+ var threw = false;
+ try {
+ traps[trap]();
+ } catch (e) {
+ threw = true;
+ }
+ if (threw) {
+ throw new Test262Error('trap ' + trap + ' threw an error');
+ }
+}
+
+function assertTrapThrows(trap) {
+ if (typeof traps[trap] !== 'function') {
+ throw new Test262Error('trap ' + trap + ' is not a function');
+ }
+ var failedToThrow = false;
+ try {
+ traps[trap]();
+ failedToThrow = true;
+ } catch (e) {}
+ if (failedToThrow) {
+ throw new Test262Error('trap ' + trap + ' did not throw an error');
+ }
+}
+
+assertTrapSucceeds('getPrototypeOf');
+assertTrapSucceeds('setPrototypeOf');
+assertTrapSucceeds('isExtensible');
+assertTrapSucceeds('preventExtensions');
+assertTrapSucceeds('getOwnPropertyDescriptor');
+assertTrapSucceeds('has');
+assertTrapSucceeds('get');
+assertTrapSucceeds('set');
+assertTrapSucceeds('deleteProperty');
+assertTrapSucceeds('defineProperty');
+assertTrapSucceeds('ownKeys');
+assertTrapSucceeds('apply');
+assertTrapSucceeds('construct');
+
+// enumerate should always throw because the trap has been removed
+assertTrapThrows('enumerate');
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/shell.js b/js/src/tests/test262/harness/shell.js
new file mode 100644
index 0000000000..7b89ff0c9b
--- /dev/null
+++ b/js/src/tests/test262/harness/shell.js
@@ -0,0 +1,3550 @@
+// GENERATED, DO NOT EDIT
+// file: assertRelativeDateMs.js
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Verify that the given date object's Number representation describes the
+ correct number of milliseconds since the Unix epoch relative to the local
+ time zone (as interpreted at the specified date).
+defines: [assertRelativeDateMs]
+---*/
+
+/**
+ * @param {Date} date
+ * @param {Number} expectedMs
+ */
+function assertRelativeDateMs(date, expectedMs) {
+ var actualMs = date.valueOf();
+ var localOffset = date.getTimezoneOffset() * 60000;
+
+ if (actualMs - localOffset !== expectedMs) {
+ throw new Test262Error(
+ 'Expected ' + date + ' to be ' + expectedMs +
+ ' milliseconds from the Unix epoch'
+ );
+ }
+}
+
+// file: asyncHelpers.js
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ A collection of assertion and wrapper functions for testing asynchronous built-ins.
+defines: [asyncTest]
+---*/
+
+function asyncTest(testFunc) {
+ if (!Object.hasOwn(globalThis, "$DONE")) {
+ throw new Test262Error("asyncTest called without async flag");
+ }
+ if (typeof testFunc !== "function") {
+ $DONE(new Test262Error("asyncTest called with non-function argument"));
+ return;
+ }
+ try {
+ testFunc().then(
+ function () {
+ $DONE();
+ },
+ function (error) {
+ $DONE(error);
+ }
+ );
+ } catch (syncError) {
+ $DONE(syncError);
+ }
+}
+
+assert.throwsAsync = async function (expectedErrorConstructor, func, message) {
+ var innerThenable;
+ if (message === undefined) {
+ message = "";
+ } else {
+ message += " ";
+ }
+ if (typeof func === "function") {
+ try {
+ innerThenable = func();
+ if (
+ innerThenable === null ||
+ typeof innerThenable !== "object" ||
+ typeof innerThenable.then !== "function"
+ ) {
+ message +=
+ "Expected to obtain an inner promise that would reject with a" +
+ expectedErrorConstructor.name +
+ " but result was not a thenable";
+ throw new Test262Error(message);
+ }
+ } catch (thrown) {
+ message +=
+ "Expected a " +
+ expectedErrorConstructor.name +
+ " to be thrown asynchronously but an exception was thrown synchronously while obtaining the inner promise";
+ throw new Test262Error(message);
+ }
+ } else {
+ message +=
+ "assert.throwsAsync called with an argument that is not a function";
+ throw new Test262Error(message);
+ }
+
+ try {
+ return innerThenable.then(
+ function () {
+ message +=
+ "Expected a " +
+ expectedErrorConstructor.name +
+ " to be thrown asynchronously but no exception was thrown at all";
+ throw new Test262Error(message);
+ },
+ function (thrown) {
+ var expectedName, actualName;
+ if (typeof thrown !== "object" || thrown === null) {
+ message += "Thrown value was not an object!";
+ throw new Test262Error(message);
+ } else if (thrown.constructor !== expectedErrorConstructor) {
+ expectedName = expectedErrorConstructor.name;
+ actualName = thrown.constructor.name;
+ if (expectedName === actualName) {
+ message +=
+ "Expected a " +
+ expectedName +
+ " but got a different error constructor with the same name";
+ } else {
+ message +=
+ "Expected a " + expectedName + " but got a " + actualName;
+ }
+ throw new Test262Error(message);
+ }
+ }
+ );
+ } catch (thrown) {
+ if (typeof thrown !== "object" || thrown === null) {
+ message +=
+ "Expected a " +
+ expectedErrorConstructor.name +
+ " to be thrown asynchronously but innerThenable synchronously threw a value that was not an object ";
+ } else {
+ message +=
+ "Expected a " +
+ expectedErrorConstructor.name +
+ " to be thrown asynchronously but a " +
+ thrown.constructor.name +
+ " was thrown synchronously";
+ }
+ throw new Test262Error(message);
+ }
+};
+
+// file: byteConversionValues.js
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Provide a list for original and expected values for different byte
+ conversions.
+ This helper is mostly used on tests for TypedArray and DataView, and each
+ array from the expected values must match the original values array on every
+ index containing its original value.
+defines: [byteConversionValues]
+---*/
+var byteConversionValues = {
+ values: [
+ 127, // 2 ** 7 - 1
+ 128, // 2 ** 7
+ 32767, // 2 ** 15 - 1
+ 32768, // 2 ** 15
+ 2147483647, // 2 ** 31 - 1
+ 2147483648, // 2 ** 31
+ 255, // 2 ** 8 - 1
+ 256, // 2 ** 8
+ 65535, // 2 ** 16 - 1
+ 65536, // 2 ** 16
+ 4294967295, // 2 ** 32 - 1
+ 4294967296, // 2 ** 32
+ 9007199254740991, // 2 ** 53 - 1
+ 9007199254740992, // 2 ** 53
+ 1.1,
+ 0.1,
+ 0.5,
+ 0.50000001,
+ 0.6,
+ 0.7,
+ undefined,
+ -1,
+ -0,
+ -0.1,
+ -1.1,
+ NaN,
+ -127, // - ( 2 ** 7 - 1 )
+ -128, // - ( 2 ** 7 )
+ -32767, // - ( 2 ** 15 - 1 )
+ -32768, // - ( 2 ** 15 )
+ -2147483647, // - ( 2 ** 31 - 1 )
+ -2147483648, // - ( 2 ** 31 )
+ -255, // - ( 2 ** 8 - 1 )
+ -256, // - ( 2 ** 8 )
+ -65535, // - ( 2 ** 16 - 1 )
+ -65536, // - ( 2 ** 16 )
+ -4294967295, // - ( 2 ** 32 - 1 )
+ -4294967296, // - ( 2 ** 32 )
+ Infinity,
+ -Infinity,
+ 0
+ ],
+
+ expected: {
+ Int8: [
+ 127, // 127
+ -128, // 128
+ -1, // 32767
+ 0, // 32768
+ -1, // 2147483647
+ 0, // 2147483648
+ -1, // 255
+ 0, // 256
+ -1, // 65535
+ 0, // 65536
+ -1, // 4294967295
+ 0, // 4294967296
+ -1, // 9007199254740991
+ 0, // 9007199254740992
+ 1, // 1.1
+ 0, // 0.1
+ 0, // 0.5
+ 0, // 0.50000001,
+ 0, // 0.6
+ 0, // 0.7
+ 0, // undefined
+ -1, // -1
+ 0, // -0
+ 0, // -0.1
+ -1, // -1.1
+ 0, // NaN
+ -127, // -127
+ -128, // -128
+ 1, // -32767
+ 0, // -32768
+ 1, // -2147483647
+ 0, // -2147483648
+ 1, // -255
+ 0, // -256
+ 1, // -65535
+ 0, // -65536
+ 1, // -4294967295
+ 0, // -4294967296
+ 0, // Infinity
+ 0, // -Infinity
+ 0
+ ],
+ Uint8: [
+ 127, // 127
+ 128, // 128
+ 255, // 32767
+ 0, // 32768
+ 255, // 2147483647
+ 0, // 2147483648
+ 255, // 255
+ 0, // 256
+ 255, // 65535
+ 0, // 65536
+ 255, // 4294967295
+ 0, // 4294967296
+ 255, // 9007199254740991
+ 0, // 9007199254740992
+ 1, // 1.1
+ 0, // 0.1
+ 0, // 0.5
+ 0, // 0.50000001,
+ 0, // 0.6
+ 0, // 0.7
+ 0, // undefined
+ 255, // -1
+ 0, // -0
+ 0, // -0.1
+ 255, // -1.1
+ 0, // NaN
+ 129, // -127
+ 128, // -128
+ 1, // -32767
+ 0, // -32768
+ 1, // -2147483647
+ 0, // -2147483648
+ 1, // -255
+ 0, // -256
+ 1, // -65535
+ 0, // -65536
+ 1, // -4294967295
+ 0, // -4294967296
+ 0, // Infinity
+ 0, // -Infinity
+ 0
+ ],
+ Uint8Clamped: [
+ 127, // 127
+ 128, // 128
+ 255, // 32767
+ 255, // 32768
+ 255, // 2147483647
+ 255, // 2147483648
+ 255, // 255
+ 255, // 256
+ 255, // 65535
+ 255, // 65536
+ 255, // 4294967295
+ 255, // 4294967296
+ 255, // 9007199254740991
+ 255, // 9007199254740992
+ 1, // 1.1,
+ 0, // 0.1
+ 0, // 0.5
+ 1, // 0.50000001,
+ 1, // 0.6
+ 1, // 0.7
+ 0, // undefined
+ 0, // -1
+ 0, // -0
+ 0, // -0.1
+ 0, // -1.1
+ 0, // NaN
+ 0, // -127
+ 0, // -128
+ 0, // -32767
+ 0, // -32768
+ 0, // -2147483647
+ 0, // -2147483648
+ 0, // -255
+ 0, // -256
+ 0, // -65535
+ 0, // -65536
+ 0, // -4294967295
+ 0, // -4294967296
+ 255, // Infinity
+ 0, // -Infinity
+ 0
+ ],
+ Int16: [
+ 127, // 127
+ 128, // 128
+ 32767, // 32767
+ -32768, // 32768
+ -1, // 2147483647
+ 0, // 2147483648
+ 255, // 255
+ 256, // 256
+ -1, // 65535
+ 0, // 65536
+ -1, // 4294967295
+ 0, // 4294967296
+ -1, // 9007199254740991
+ 0, // 9007199254740992
+ 1, // 1.1
+ 0, // 0.1
+ 0, // 0.5
+ 0, // 0.50000001,
+ 0, // 0.6
+ 0, // 0.7
+ 0, // undefined
+ -1, // -1
+ 0, // -0
+ 0, // -0.1
+ -1, // -1.1
+ 0, // NaN
+ -127, // -127
+ -128, // -128
+ -32767, // -32767
+ -32768, // -32768
+ 1, // -2147483647
+ 0, // -2147483648
+ -255, // -255
+ -256, // -256
+ 1, // -65535
+ 0, // -65536
+ 1, // -4294967295
+ 0, // -4294967296
+ 0, // Infinity
+ 0, // -Infinity
+ 0
+ ],
+ Uint16: [
+ 127, // 127
+ 128, // 128
+ 32767, // 32767
+ 32768, // 32768
+ 65535, // 2147483647
+ 0, // 2147483648
+ 255, // 255
+ 256, // 256
+ 65535, // 65535
+ 0, // 65536
+ 65535, // 4294967295
+ 0, // 4294967296
+ 65535, // 9007199254740991
+ 0, // 9007199254740992
+ 1, // 1.1
+ 0, // 0.1
+ 0, // 0.5
+ 0, // 0.50000001,
+ 0, // 0.6
+ 0, // 0.7
+ 0, // undefined
+ 65535, // -1
+ 0, // -0
+ 0, // -0.1
+ 65535, // -1.1
+ 0, // NaN
+ 65409, // -127
+ 65408, // -128
+ 32769, // -32767
+ 32768, // -32768
+ 1, // -2147483647
+ 0, // -2147483648
+ 65281, // -255
+ 65280, // -256
+ 1, // -65535
+ 0, // -65536
+ 1, // -4294967295
+ 0, // -4294967296
+ 0, // Infinity
+ 0, // -Infinity
+ 0
+ ],
+ Int32: [
+ 127, // 127
+ 128, // 128
+ 32767, // 32767
+ 32768, // 32768
+ 2147483647, // 2147483647
+ -2147483648, // 2147483648
+ 255, // 255
+ 256, // 256
+ 65535, // 65535
+ 65536, // 65536
+ -1, // 4294967295
+ 0, // 4294967296
+ -1, // 9007199254740991
+ 0, // 9007199254740992
+ 1, // 1.1
+ 0, // 0.1
+ 0, // 0.5
+ 0, // 0.50000001,
+ 0, // 0.6
+ 0, // 0.7
+ 0, // undefined
+ -1, // -1
+ 0, // -0
+ 0, // -0.1
+ -1, // -1.1
+ 0, // NaN
+ -127, // -127
+ -128, // -128
+ -32767, // -32767
+ -32768, // -32768
+ -2147483647, // -2147483647
+ -2147483648, // -2147483648
+ -255, // -255
+ -256, // -256
+ -65535, // -65535
+ -65536, // -65536
+ 1, // -4294967295
+ 0, // -4294967296
+ 0, // Infinity
+ 0, // -Infinity
+ 0
+ ],
+ Uint32: [
+ 127, // 127
+ 128, // 128
+ 32767, // 32767
+ 32768, // 32768
+ 2147483647, // 2147483647
+ 2147483648, // 2147483648
+ 255, // 255
+ 256, // 256
+ 65535, // 65535
+ 65536, // 65536
+ 4294967295, // 4294967295
+ 0, // 4294967296
+ 4294967295, // 9007199254740991
+ 0, // 9007199254740992
+ 1, // 1.1
+ 0, // 0.1
+ 0, // 0.5
+ 0, // 0.50000001,
+ 0, // 0.6
+ 0, // 0.7
+ 0, // undefined
+ 4294967295, // -1
+ 0, // -0
+ 0, // -0.1
+ 4294967295, // -1.1
+ 0, // NaN
+ 4294967169, // -127
+ 4294967168, // -128
+ 4294934529, // -32767
+ 4294934528, // -32768
+ 2147483649, // -2147483647
+ 2147483648, // -2147483648
+ 4294967041, // -255
+ 4294967040, // -256
+ 4294901761, // -65535
+ 4294901760, // -65536
+ 1, // -4294967295
+ 0, // -4294967296
+ 0, // Infinity
+ 0, // -Infinity
+ 0
+ ],
+ Float32: [
+ 127, // 127
+ 128, // 128
+ 32767, // 32767
+ 32768, // 32768
+ 2147483648, // 2147483647
+ 2147483648, // 2147483648
+ 255, // 255
+ 256, // 256
+ 65535, // 65535
+ 65536, // 65536
+ 4294967296, // 4294967295
+ 4294967296, // 4294967296
+ 9007199254740992, // 9007199254740991
+ 9007199254740992, // 9007199254740992
+ 1.100000023841858, // 1.1
+ 0.10000000149011612, // 0.1
+ 0.5, // 0.5
+ 0.5, // 0.50000001,
+ 0.6000000238418579, // 0.6
+ 0.699999988079071, // 0.7
+ NaN, // undefined
+ -1, // -1
+ -0, // -0
+ -0.10000000149011612, // -0.1
+ -1.100000023841858, // -1.1
+ NaN, // NaN
+ -127, // -127
+ -128, // -128
+ -32767, // -32767
+ -32768, // -32768
+ -2147483648, // -2147483647
+ -2147483648, // -2147483648
+ -255, // -255
+ -256, // -256
+ -65535, // -65535
+ -65536, // -65536
+ -4294967296, // -4294967295
+ -4294967296, // -4294967296
+ Infinity, // Infinity
+ -Infinity, // -Infinity
+ 0
+ ],
+ Float64: [
+ 127, // 127
+ 128, // 128
+ 32767, // 32767
+ 32768, // 32768
+ 2147483647, // 2147483647
+ 2147483648, // 2147483648
+ 255, // 255
+ 256, // 256
+ 65535, // 65535
+ 65536, // 65536
+ 4294967295, // 4294967295
+ 4294967296, // 4294967296
+ 9007199254740991, // 9007199254740991
+ 9007199254740992, // 9007199254740992
+ 1.1, // 1.1
+ 0.1, // 0.1
+ 0.5, // 0.5
+ 0.50000001, // 0.50000001,
+ 0.6, // 0.6
+ 0.7, // 0.7
+ NaN, // undefined
+ -1, // -1
+ -0, // -0
+ -0.1, // -0.1
+ -1.1, // -1.1
+ NaN, // NaN
+ -127, // -127
+ -128, // -128
+ -32767, // -32767
+ -32768, // -32768
+ -2147483647, // -2147483647
+ -2147483648, // -2147483648
+ -255, // -255
+ -256, // -256
+ -65535, // -65535
+ -65536, // -65536
+ -4294967295, // -4294967295
+ -4294967296, // -4294967296
+ Infinity, // Infinity
+ -Infinity, // -Infinity
+ 0
+ ]
+ }
+};
+
+// file: dateConstants.js
+// Copyright (C) 2009 the Sputnik authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Collection of date-centric values
+defines:
+ - date_1899_end
+ - date_1900_start
+ - date_1969_end
+ - date_1970_start
+ - date_1999_end
+ - date_2000_start
+ - date_2099_end
+ - date_2100_start
+ - start_of_time
+ - end_of_time
+---*/
+
+var date_1899_end = -2208988800001;
+var date_1900_start = -2208988800000;
+var date_1969_end = -1;
+var date_1970_start = 0;
+var date_1999_end = 946684799999;
+var date_2000_start = 946684800000;
+var date_2099_end = 4102444799999;
+var date_2100_start = 4102444800000;
+
+var start_of_time = -8.64e15;
+var end_of_time = 8.64e15;
+
+// file: decimalToHexString.js
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Collection of functions used to assert the correctness of various encoding operations.
+defines: [decimalToHexString, decimalToPercentHexString]
+---*/
+
+function decimalToHexString(n) {
+ var hex = "0123456789ABCDEF";
+ n >>>= 0;
+ var s = "";
+ while (n) {
+ s = hex[n & 0xf] + s;
+ n >>>= 4;
+ }
+ while (s.length < 4) {
+ s = "0" + s;
+ }
+ return s;
+}
+
+function decimalToPercentHexString(n) {
+ var hex = "0123456789ABCDEF";
+ return "%" + hex[(n >> 4) & 0xf] + hex[n & 0xf];
+}
+
+// file: deepEqual.js
+// Copyright 2019 Ron Buckton. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: >
+ Compare two values structurally
+defines: [assert.deepEqual]
+---*/
+
+assert.deepEqual = function(actual, expected, message) {
+ var format = assert.deepEqual.format;
+ assert(
+ assert.deepEqual._compare(actual, expected),
+ `Expected ${format(actual)} to be structurally equal to ${format(expected)}. ${(message || '')}`
+ );
+};
+
+assert.deepEqual.format = function(value, seen) {
+ switch (typeof value) {
+ case 'string':
+ return typeof JSON !== "undefined" ? JSON.stringify(value) : `"${value}"`;
+ case 'number':
+ case 'boolean':
+ case 'symbol':
+ case 'bigint':
+ return value.toString();
+ case 'undefined':
+ return 'undefined';
+ case 'function':
+ return `[Function${value.name ? `: ${value.name}` : ''}]`;
+ case 'object':
+ if (value === null) return 'null';
+ if (value instanceof Date) return `Date "${value.toISOString()}"`;
+ if (value instanceof RegExp) return value.toString();
+ if (!seen) {
+ seen = {
+ counter: 0,
+ map: new Map()
+ };
+ }
+
+ let usage = seen.map.get(value);
+ if (usage) {
+ usage.used = true;
+ return `[Ref: #${usage.id}]`;
+ }
+
+ usage = { id: ++seen.counter, used: false };
+ seen.map.set(value, usage);
+
+ if (typeof Set !== "undefined" && value instanceof Set) {
+ return `Set {${Array.from(value).map(value => assert.deepEqual.format(value, seen)).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`;
+ }
+ if (typeof Map !== "undefined" && value instanceof Map) {
+ return `Map {${Array.from(value).map(pair => `${assert.deepEqual.format(pair[0], seen)} => ${assert.deepEqual.format(pair[1], seen)}}`).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`;
+ }
+ if (Array.isArray ? Array.isArray(value) : value instanceof Array) {
+ return `[${value.map(value => assert.deepEqual.format(value, seen)).join(', ')}]${usage.used ? ` as #${usage.id}` : ''}`;
+ }
+ let tag = Symbol.toStringTag in value ? value[Symbol.toStringTag] : 'Object';
+ if (tag === 'Object' && Object.getPrototypeOf(value) === null) {
+ tag = '[Object: null prototype]';
+ }
+ return `${tag ? `${tag} ` : ''}{ ${Object.keys(value).map(key => `${key.toString()}: ${assert.deepEqual.format(value[key], seen)}`).join(', ')} }${usage.used ? ` as #${usage.id}` : ''}`;
+ default:
+ return typeof value;
+ }
+};
+
+assert.deepEqual._compare = (function () {
+ var EQUAL = 1;
+ var NOT_EQUAL = -1;
+ var UNKNOWN = 0;
+
+ function deepEqual(a, b) {
+ return compareEquality(a, b) === EQUAL;
+ }
+
+ function compareEquality(a, b, cache) {
+ return compareIf(a, b, isOptional, compareOptionality)
+ || compareIf(a, b, isPrimitiveEquatable, comparePrimitiveEquality)
+ || compareIf(a, b, isObjectEquatable, compareObjectEquality, cache)
+ || NOT_EQUAL;
+ }
+
+ function compareIf(a, b, test, compare, cache) {
+ return !test(a)
+ ? !test(b) ? UNKNOWN : NOT_EQUAL
+ : !test(b) ? NOT_EQUAL : cacheComparison(a, b, compare, cache);
+ }
+
+ function tryCompareStrictEquality(a, b) {
+ return a === b ? EQUAL : UNKNOWN;
+ }
+
+ function tryCompareTypeOfEquality(a, b) {
+ return typeof a !== typeof b ? NOT_EQUAL : UNKNOWN;
+ }
+
+ function tryCompareToStringTagEquality(a, b) {
+ var aTag = Symbol.toStringTag in a ? a[Symbol.toStringTag] : undefined;
+ var bTag = Symbol.toStringTag in b ? b[Symbol.toStringTag] : undefined;
+ return aTag !== bTag ? NOT_EQUAL : UNKNOWN;
+ }
+
+ function isOptional(value) {
+ return value === undefined
+ || value === null;
+ }
+
+ function compareOptionality(a, b) {
+ return tryCompareStrictEquality(a, b)
+ || NOT_EQUAL;
+ }
+
+ function isPrimitiveEquatable(value) {
+ switch (typeof value) {
+ case 'string':
+ case 'number':
+ case 'bigint':
+ case 'boolean':
+ case 'symbol':
+ return true;
+ default:
+ return isBoxed(value);
+ }
+ }
+
+ function comparePrimitiveEquality(a, b) {
+ if (isBoxed(a)) a = a.valueOf();
+ if (isBoxed(b)) b = b.valueOf();
+ return tryCompareStrictEquality(a, b)
+ || tryCompareTypeOfEquality(a, b)
+ || compareIf(a, b, isNaNEquatable, compareNaNEquality)
+ || NOT_EQUAL;
+ }
+
+ function isNaNEquatable(value) {
+ return typeof value === 'number';
+ }
+
+ function compareNaNEquality(a, b) {
+ return isNaN(a) && isNaN(b) ? EQUAL : NOT_EQUAL;
+ }
+
+ function isObjectEquatable(value) {
+ return typeof value === 'object';
+ }
+
+ function compareObjectEquality(a, b, cache) {
+ if (!cache) cache = new Map();
+ return getCache(cache, a, b)
+ || setCache(cache, a, b, EQUAL) // consider equal for now
+ || cacheComparison(a, b, tryCompareStrictEquality, cache)
+ || cacheComparison(a, b, tryCompareToStringTagEquality, cache)
+ || compareIf(a, b, isValueOfEquatable, compareValueOfEquality)
+ || compareIf(a, b, isToStringEquatable, compareToStringEquality)
+ || compareIf(a, b, isArrayLikeEquatable, compareArrayLikeEquality, cache)
+ || compareIf(a, b, isStructurallyEquatable, compareStructuralEquality, cache)
+ || compareIf(a, b, isIterableEquatable, compareIterableEquality, cache)
+ || cacheComparison(a, b, fail, cache);
+ }
+
+ function isBoxed(value) {
+ return value instanceof String
+ || value instanceof Number
+ || value instanceof Boolean
+ || typeof Symbol === 'function' && value instanceof Symbol
+ || typeof BigInt === 'function' && value instanceof BigInt;
+ }
+
+ function isValueOfEquatable(value) {
+ return value instanceof Date;
+ }
+
+ function compareValueOfEquality(a, b) {
+ return compareIf(a.valueOf(), b.valueOf(), isPrimitiveEquatable, comparePrimitiveEquality)
+ || NOT_EQUAL;
+ }
+
+ function isToStringEquatable(value) {
+ return value instanceof RegExp;
+ }
+
+ function compareToStringEquality(a, b) {
+ return compareIf(a.toString(), b.toString(), isPrimitiveEquatable, comparePrimitiveEquality)
+ || NOT_EQUAL;
+ }
+
+ function isArrayLikeEquatable(value) {
+ return (Array.isArray ? Array.isArray(value) : value instanceof Array)
+ || (typeof Uint8Array === 'function' && value instanceof Uint8Array)
+ || (typeof Uint8ClampedArray === 'function' && value instanceof Uint8ClampedArray)
+ || (typeof Uint16Array === 'function' && value instanceof Uint16Array)
+ || (typeof Uint32Array === 'function' && value instanceof Uint32Array)
+ || (typeof Int8Array === 'function' && value instanceof Int8Array)
+ || (typeof Int16Array === 'function' && value instanceof Int16Array)
+ || (typeof Int32Array === 'function' && value instanceof Int32Array)
+ || (typeof Float32Array === 'function' && value instanceof Float32Array)
+ || (typeof Float64Array === 'function' && value instanceof Float64Array)
+ || (typeof BigUint64Array === 'function' && value instanceof BigUint64Array)
+ || (typeof BigInt64Array === 'function' && value instanceof BigInt64Array);
+ }
+
+ function compareArrayLikeEquality(a, b, cache) {
+ if (a.length !== b.length) return NOT_EQUAL;
+ for (var i = 0; i < a.length; i++) {
+ if (compareEquality(a[i], b[i], cache) === NOT_EQUAL) {
+ return NOT_EQUAL;
+ }
+ }
+ return EQUAL;
+ }
+
+ function isStructurallyEquatable(value) {
+ return !(typeof Promise === 'function' && value instanceof Promise // only comparable by reference
+ || typeof WeakMap === 'function' && value instanceof WeakMap // only comparable by reference
+ || typeof WeakSet === 'function' && value instanceof WeakSet // only comparable by reference
+ || typeof Map === 'function' && value instanceof Map // comparable via @@iterator
+ || typeof Set === 'function' && value instanceof Set); // comparable via @@iterator
+ }
+
+ function compareStructuralEquality(a, b, cache) {
+ var aKeys = [];
+ for (var key in a) aKeys.push(key);
+
+ var bKeys = [];
+ for (var key in b) bKeys.push(key);
+
+ if (aKeys.length !== bKeys.length) {
+ return NOT_EQUAL;
+ }
+
+ aKeys.sort();
+ bKeys.sort();
+
+ for (var i = 0; i < aKeys.length; i++) {
+ var aKey = aKeys[i];
+ var bKey = bKeys[i];
+ if (compareEquality(aKey, bKey, cache) === NOT_EQUAL) {
+ return NOT_EQUAL;
+ }
+ if (compareEquality(a[aKey], b[bKey], cache) === NOT_EQUAL) {
+ return NOT_EQUAL;
+ }
+ }
+
+ return compareIf(a, b, isIterableEquatable, compareIterableEquality, cache)
+ || EQUAL;
+ }
+
+ function isIterableEquatable(value) {
+ return typeof Symbol === 'function'
+ && typeof value[Symbol.iterator] === 'function';
+ }
+
+ function compareIteratorEquality(a, b, cache) {
+ if (typeof Map === 'function' && a instanceof Map && b instanceof Map ||
+ typeof Set === 'function' && a instanceof Set && b instanceof Set) {
+ if (a.size !== b.size) return NOT_EQUAL; // exit early if we detect a difference in size
+ }
+
+ var ar, br;
+ while (true) {
+ ar = a.next();
+ br = b.next();
+ if (ar.done) {
+ if (br.done) return EQUAL;
+ if (b.return) b.return();
+ return NOT_EQUAL;
+ }
+ if (br.done) {
+ if (a.return) a.return();
+ return NOT_EQUAL;
+ }
+ if (compareEquality(ar.value, br.value, cache) === NOT_EQUAL) {
+ if (a.return) a.return();
+ if (b.return) b.return();
+ return NOT_EQUAL;
+ }
+ }
+ }
+
+ function compareIterableEquality(a, b, cache) {
+ return compareIteratorEquality(a[Symbol.iterator](), b[Symbol.iterator](), cache);
+ }
+
+ function cacheComparison(a, b, compare, cache) {
+ var result = compare(a, b, cache);
+ if (cache && (result === EQUAL || result === NOT_EQUAL)) {
+ setCache(cache, a, b, /** @type {EQUAL | NOT_EQUAL} */(result));
+ }
+ return result;
+ }
+
+ function fail() {
+ return NOT_EQUAL;
+ }
+
+ function setCache(cache, left, right, result) {
+ var otherCache;
+
+ otherCache = cache.get(left);
+ if (!otherCache) cache.set(left, otherCache = new Map());
+ otherCache.set(right, result);
+
+ otherCache = cache.get(right);
+ if (!otherCache) cache.set(right, otherCache = new Map());
+ otherCache.set(left, result);
+ }
+
+ function getCache(cache, left, right) {
+ var otherCache;
+ var result;
+
+ otherCache = cache.get(left);
+ result = otherCache && otherCache.get(right);
+ if (result) return result;
+
+ otherCache = cache.get(right);
+ result = otherCache && otherCache.get(left);
+ if (result) return result;
+
+ return UNKNOWN;
+ }
+
+ return deepEqual;
+})();
+
+// file: detachArrayBuffer.js
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ A function used in the process of asserting correctness of TypedArray objects.
+
+ $262.detachArrayBuffer is defined by a host.
+defines: [$DETACHBUFFER]
+---*/
+
+function $DETACHBUFFER(buffer) {
+ if (!$262 || typeof $262.detachArrayBuffer !== "function") {
+ throw new Test262Error("No method available to detach an ArrayBuffer");
+ }
+ $262.detachArrayBuffer(buffer);
+}
+
+// file: fnGlobalObject.js
+// Copyright (C) 2017 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Produce a reliable global object
+defines: [fnGlobalObject]
+---*/
+
+var __globalObject = Function("return this;")();
+function fnGlobalObject() {
+ return __globalObject;
+}
+
+// file: isConstructor.js
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: |
+ Test if a given function is a constructor function.
+defines: [isConstructor]
+features: [Reflect.construct]
+---*/
+
+function isConstructor(f) {
+ if (typeof f !== "function") {
+ throw new Test262Error("isConstructor invoked with a non-function value");
+ }
+
+ try {
+ Reflect.construct(function(){}, [], f);
+ } catch (e) {
+ return false;
+ }
+ return true;
+}
+
+// file: nans.js
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ A collection of NaN values produced from expressions that have been observed
+ to create distinct bit representations on various platforms. These provide a
+ weak basis for assertions regarding the consistent canonicalization of NaN
+ values in Array buffers.
+defines: [NaNs]
+---*/
+
+var NaNs = [
+ NaN,
+ Number.NaN,
+ NaN * 0,
+ 0/0,
+ Infinity/Infinity,
+ -(0/0),
+ Math.pow(-1, 0.5),
+ -Math.pow(-1, 0.5),
+ Number("Not-a-Number"),
+];
+
+// file: nativeFunctionMatcher.js
+// Copyright (C) 2016 Michael Ficarra. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Assert _NativeFunction_ Syntax
+info: |
+ NativeFunction :
+ function _NativeFunctionAccessor_ opt _IdentifierName_ opt ( _FormalParameters_ ) { [ native code ] }
+ NativeFunctionAccessor :
+ get
+ set
+defines:
+ - assertToStringOrNativeFunction
+ - assertNativeFunction
+ - validateNativeFunctionSource
+---*/
+
+const validateNativeFunctionSource = function(source) {
+ // These regexes should be kept up to date with Unicode using `regexpu-core`.
+ // `/\p{ID_Start}/u`
+ const UnicodeIDStart = /(?:[A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08C7\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1878\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\u9FFC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7BF\uA7C2-\uA7CA\uA7F5-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD23\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDEB8\uDF00-\uDF1A]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCDF\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDEE0-\uDEF2\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82C[\uDC00-\uDD1E\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD838[\uDD00-\uDD2C\uDD37-\uDD3D\uDD4E\uDEC0-\uDEEB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43\uDD4B]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDEDD\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])/;
+ // `/\p{ID_Continue}/u`
+ const UnicodeIDContinue = /(?:[0-9A-Z_a-z\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05EF-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u07FD\u0800-\u082D\u0840-\u085B\u0860-\u086A\u08A0-\u08B4\u08B6-\u08C7\u08D3-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u09FC\u09FE\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B55-\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D00-\u0D0C\u0D0E-\u0D10\u0D12-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D81-\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1878\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1ABF\u1AC0\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CD0-\u1CD2\u1CD4-\u1CFA\u1D00-\u1DF9\u1DFB-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\u9FFC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7BF\uA7C2-\uA7CA\uA7F5-\uA827\uA82C\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD27\uDD30-\uDD39\uDE80-\uDEA9\uDEAB\uDEAC\uDEB0\uDEB1\uDF00-\uDF1C\uDF27\uDF30-\uDF50\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD44-\uDD47\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDC9-\uDDCC\uDDCE-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3B-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-\uDC4A\uDC50-\uDC59\uDC5E-\uDC61\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB8\uDEC0-\uDEC9\uDF00-\uDF1A\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDC00-\uDC3A\uDCA0-\uDCE9\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD35\uDD37\uDD38\uDD3B-\uDD43\uDD50-\uDD59\uDDA0-\uDDA7\uDDAA-\uDDD7\uDDDA-\uDDE1\uDDE3\uDDE4\uDE00-\uDE3E\uDE47\uDE50-\uDE99\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD8E\uDD90\uDD91\uDD93-\uDD98\uDDA0-\uDDA9\uDEE0-\uDEF6\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF4A\uDF4F-\uDF87\uDF8F-\uDF9F\uDFE0\uDFE1\uDFE3\uDFE4\uDFF0\uDFF1]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82C[\uDC00-\uDD1E\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A\uDD00-\uDD2C\uDD30-\uDD3D\uDD40-\uDD49\uDD4E\uDEC0-\uDEF9]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6\uDD00-\uDD4B\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD83E[\uDFF0-\uDFF9]|\uD869[\uDC00-\uDEDD\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A]|\uDB40[\uDD00-\uDDEF])/;
+ // `/\p{Space_Separator}/u`
+ const UnicodeSpaceSeparator = /[ \xA0\u1680\u2000-\u200A\u202F\u205F\u3000]/;
+
+ const isNewline = (c) => /[\u000A\u000D\u2028\u2029]/u.test(c);
+ const isWhitespace = (c) => /[\u0009\u000B\u000C\u0020\u00A0\uFEFF]/u.test(c) || UnicodeSpaceSeparator.test(c);
+
+ let pos = 0;
+
+ const eatWhitespace = () => {
+ while (pos < source.length) {
+ const c = source[pos];
+ if (isWhitespace(c) || isNewline(c)) {
+ pos += 1;
+ continue;
+ }
+
+ if (c === '/') {
+ if (source[pos + 1] === '/') {
+ while (pos < source.length) {
+ if (isNewline(source[pos])) {
+ break;
+ }
+ pos += 1;
+ }
+ continue;
+ }
+ if (source[pos + 1] === '*') {
+ const end = source.indexOf('*/', pos);
+ if (end === -1) {
+ throw new SyntaxError();
+ }
+ pos = end + '*/'.length;
+ continue;
+ }
+ }
+
+ break;
+ }
+ };
+
+ const getIdentifier = () => {
+ eatWhitespace();
+
+ const start = pos;
+ let end = pos;
+ switch (source[end]) {
+ case '_':
+ case '$':
+ end += 1;
+ break;
+ default:
+ if (UnicodeIDStart.test(source[end])) {
+ end += 1;
+ break;
+ }
+ return null;
+ }
+ while (end < source.length) {
+ const c = source[end];
+ switch (c) {
+ case '_':
+ case '$':
+ end += 1;
+ break;
+ default:
+ if (UnicodeIDContinue.test(c)) {
+ end += 1;
+ break;
+ }
+ return source.slice(start, end);
+ }
+ }
+ return source.slice(start, end);
+ };
+
+ const test = (s) => {
+ eatWhitespace();
+
+ if (/\w/.test(s)) {
+ return getIdentifier() === s;
+ }
+ return source.slice(pos, pos + s.length) === s;
+ };
+
+ const eat = (s) => {
+ if (test(s)) {
+ pos += s.length;
+ return true;
+ }
+ return false;
+ };
+
+ const eatIdentifier = () => {
+ const n = getIdentifier();
+ if (n !== null) {
+ pos += n.length;
+ return true;
+ }
+ return false;
+ };
+
+ const expect = (s) => {
+ if (!eat(s)) {
+ throw new SyntaxError();
+ }
+ };
+
+ const eatString = () => {
+ if (source[pos] === '\'' || source[pos] === '"') {
+ const match = source[pos];
+ pos += 1;
+ while (pos < source.length) {
+ if (source[pos] === match && source[pos - 1] !== '\\') {
+ return;
+ }
+ if (isNewline(source[pos])) {
+ throw new SyntaxError();
+ }
+ pos += 1;
+ }
+ throw new SyntaxError();
+ }
+ };
+
+ // "Stumble" through source text until matching character is found.
+ // Assumes ECMAScript syntax keeps `[]` and `()` balanced.
+ const stumbleUntil = (c) => {
+ const match = {
+ ']': '[',
+ ')': '(',
+ }[c];
+ let nesting = 1;
+ while (pos < source.length) {
+ eatWhitespace();
+ eatString(); // Strings may contain unbalanced characters.
+ if (source[pos] === match) {
+ nesting += 1;
+ } else if (source[pos] === c) {
+ nesting -= 1;
+ }
+ pos += 1;
+ if (nesting === 0) {
+ return;
+ }
+ }
+ throw new SyntaxError();
+ };
+
+ // function
+ expect('function');
+
+ // NativeFunctionAccessor
+ eat('get') || eat('set');
+
+ // PropertyName
+ if (!eatIdentifier() && eat('[')) {
+ stumbleUntil(']');
+ }
+
+ // ( FormalParameters )
+ expect('(');
+ stumbleUntil(')');
+
+ // {
+ expect('{');
+
+ // [native code]
+ expect('[');
+ expect('native');
+ expect('code');
+ expect(']');
+
+ // }
+ expect('}');
+
+ eatWhitespace();
+ if (pos !== source.length) {
+ throw new SyntaxError();
+ }
+};
+
+const assertToStringOrNativeFunction = function(fn, expected) {
+ const actual = "" + fn;
+ try {
+ assert.sameValue(actual, expected);
+ } catch (unused) {
+ assertNativeFunction(fn, expected);
+ }
+};
+
+const assertNativeFunction = function(fn, special) {
+ const actual = "" + fn;
+ try {
+ validateNativeFunctionSource(actual);
+ } catch (unused) {
+ throw new Test262Error('Conforms to NativeFunction Syntax: ' + JSON.stringify(actual) + (special ? ' (' + special + ')' : ''));
+ }
+};
+
+// file: promiseHelper.js
+// Copyright (C) 2017 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Check that an array contains a numeric sequence starting at 1
+ and incrementing by 1 for each entry in the array. Used by
+ Promise tests to assert the order of execution in deep Promise
+ resolution pipelines.
+defines: [checkSequence, checkSettledPromises]
+---*/
+
+function checkSequence(arr, message) {
+ arr.forEach(function(e, i) {
+ if (e !== (i+1)) {
+ throw new Test262Error((message ? message : "Steps in unexpected sequence:") +
+ " '" + arr.join(',') + "'");
+ }
+ });
+
+ return true;
+}
+
+function checkSettledPromises(settleds, expected, message) {
+ const prefix = message ? `${message}: ` : '';
+
+ assert.sameValue(Array.isArray(settleds), true, `${prefix}Settled values is an array`);
+
+ assert.sameValue(
+ settleds.length,
+ expected.length,
+ `${prefix}The settled values has a different length than expected`
+ );
+
+ settleds.forEach((settled, i) => {
+ assert.sameValue(
+ Object.prototype.hasOwnProperty.call(settled, 'status'),
+ true,
+ `${prefix}The settled value has a property status`
+ );
+
+ assert.sameValue(settled.status, expected[i].status, `${prefix}status for item ${i}`);
+
+ if (settled.status === 'fulfilled') {
+ assert.sameValue(
+ Object.prototype.hasOwnProperty.call(settled, 'value'),
+ true,
+ `${prefix}The fulfilled promise has a property named value`
+ );
+
+ assert.sameValue(
+ Object.prototype.hasOwnProperty.call(settled, 'reason'),
+ false,
+ `${prefix}The fulfilled promise has no property named reason`
+ );
+
+ assert.sameValue(settled.value, expected[i].value, `${prefix}value for item ${i}`);
+ } else {
+ assert.sameValue(settled.status, 'rejected', `${prefix}Valid statuses are only fulfilled or rejected`);
+
+ assert.sameValue(
+ Object.prototype.hasOwnProperty.call(settled, 'value'),
+ false,
+ `${prefix}The fulfilled promise has no property named value`
+ );
+
+ assert.sameValue(
+ Object.prototype.hasOwnProperty.call(settled, 'reason'),
+ true,
+ `${prefix}The fulfilled promise has a property named reason`
+ );
+
+ assert.sameValue(settled.reason, expected[i].reason, `${prefix}Reason value for item ${i}`);
+ }
+ });
+}
+
+// file: proxyTrapsHelper.js
+// Copyright (C) 2016 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Used to assert the correctness of object behavior in the presence
+ and context of Proxy objects.
+defines: [allowProxyTraps]
+---*/
+
+function allowProxyTraps(overrides) {
+ function throwTest262Error(msg) {
+ return function () { throw new Test262Error(msg); };
+ }
+ if (!overrides) { overrides = {}; }
+ return {
+ getPrototypeOf: overrides.getPrototypeOf || throwTest262Error('[[GetPrototypeOf]] trap called'),
+ setPrototypeOf: overrides.setPrototypeOf || throwTest262Error('[[SetPrototypeOf]] trap called'),
+ isExtensible: overrides.isExtensible || throwTest262Error('[[IsExtensible]] trap called'),
+ preventExtensions: overrides.preventExtensions || throwTest262Error('[[PreventExtensions]] trap called'),
+ getOwnPropertyDescriptor: overrides.getOwnPropertyDescriptor || throwTest262Error('[[GetOwnProperty]] trap called'),
+ has: overrides.has || throwTest262Error('[[HasProperty]] trap called'),
+ get: overrides.get || throwTest262Error('[[Get]] trap called'),
+ set: overrides.set || throwTest262Error('[[Set]] trap called'),
+ deleteProperty: overrides.deleteProperty || throwTest262Error('[[Delete]] trap called'),
+ defineProperty: overrides.defineProperty || throwTest262Error('[[DefineOwnProperty]] trap called'),
+ enumerate: throwTest262Error('[[Enumerate]] trap called: this trap has been removed'),
+ ownKeys: overrides.ownKeys || throwTest262Error('[[OwnPropertyKeys]] trap called'),
+ apply: overrides.apply || throwTest262Error('[[Call]] trap called'),
+ construct: overrides.construct || throwTest262Error('[[Construct]] trap called')
+ };
+}
+
+// file: tcoHelper.js
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ This defines the number of consecutive recursive function calls that must be
+ made in order to prove that stack frames are properly destroyed according to
+ ES2015 tail call optimization semantics.
+defines: [$MAX_ITERATIONS]
+---*/
+
+
+
+
+var $MAX_ITERATIONS = 100000;
+
+// file: temporalHelpers.js
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ This defines helper objects and functions for testing Temporal.
+defines: [TemporalHelpers]
+features: [Symbol.species, Symbol.iterator, Temporal]
+---*/
+
+function formatPropertyName(propertyKey, objectName = "") {
+ switch (typeof propertyKey) {
+ case "symbol":
+ if (Symbol.keyFor(propertyKey) !== undefined) {
+ return `${objectName}[Symbol.for('${Symbol.keyFor(propertyKey)}')]`;
+ } else if (propertyKey.description.startsWith('Symbol.')) {
+ return `${objectName}[${propertyKey.description}]`;
+ } else {
+ return `${objectName}[Symbol('${propertyKey.description}')]`
+ }
+ case "number":
+ return `${objectName}[${propertyKey}]`;
+ default:
+ // TODO: check if propertyKey is an integer index.
+ return objectName ? `${objectName}.${propertyKey}` : propertyKey;
+ }
+}
+const SKIP_SYMBOL = Symbol("Skip");
+
+var TemporalHelpers = {
+ /*
+ * assertDuration(duration, years, ..., nanoseconds[, description]):
+ *
+ * Shorthand for asserting that each field of a Temporal.Duration is equal to
+ * an expected value.
+ */
+ assertDuration(duration, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, description = "") {
+ assert(duration instanceof Temporal.Duration, `${description} instanceof`);
+ assert.sameValue(duration.years, years, `${description} years result`);
+ assert.sameValue(duration.months, months, `${description} months result`);
+ assert.sameValue(duration.weeks, weeks, `${description} weeks result`);
+ assert.sameValue(duration.days, days, `${description} days result`);
+ assert.sameValue(duration.hours, hours, `${description} hours result`);
+ assert.sameValue(duration.minutes, minutes, `${description} minutes result`);
+ assert.sameValue(duration.seconds, seconds, `${description} seconds result`);
+ assert.sameValue(duration.milliseconds, milliseconds, `${description} milliseconds result`);
+ assert.sameValue(duration.microseconds, microseconds, `${description} microseconds result`);
+ assert.sameValue(duration.nanoseconds, nanoseconds, `${description} nanoseconds result`);
+ },
+
+ /*
+ * assertDurationsEqual(actual, expected[, description]):
+ *
+ * Shorthand for asserting that each field of a Temporal.Duration is equal to
+ * the corresponding field in another Temporal.Duration.
+ */
+ assertDurationsEqual(actual, expected, description = "") {
+ assert(expected instanceof Temporal.Duration, `${description} expected value should be a Temporal.Duration`);
+ TemporalHelpers.assertDuration(actual, expected.years, expected.months, expected.weeks, expected.days, expected.hours, expected.minutes, expected.seconds, expected.milliseconds, expected.microseconds, expected.nanoseconds, description);
+ },
+
+ /*
+ * assertInstantsEqual(actual, expected[, description]):
+ *
+ * Shorthand for asserting that two Temporal.Instants are of the correct type
+ * and equal according to their equals() methods.
+ */
+ assertInstantsEqual(actual, expected, description = "") {
+ assert(expected instanceof Temporal.Instant, `${description} expected value should be a Temporal.Instant`);
+ assert(actual instanceof Temporal.Instant, `${description} instanceof`);
+ assert(actual.equals(expected), `${description} equals method`);
+ },
+
+ /*
+ * assertPlainDate(date, year, ..., nanosecond[, description[, era, eraYear]]):
+ *
+ * Shorthand for asserting that each field of a Temporal.PlainDate is equal to
+ * an expected value. (Except the `calendar` property, since callers may want
+ * to assert either object equality with an object they put in there, or the
+ * result of date.calendar.toString().)
+ */
+ assertPlainDate(date, year, month, monthCode, day, description = "", era = undefined, eraYear = undefined) {
+ assert(date instanceof Temporal.PlainDate, `${description} instanceof`);
+ assert.sameValue(date.era, era, `${description} era result`);
+ assert.sameValue(date.eraYear, eraYear, `${description} eraYear result`);
+ assert.sameValue(date.year, year, `${description} year result`);
+ assert.sameValue(date.month, month, `${description} month result`);
+ assert.sameValue(date.monthCode, monthCode, `${description} monthCode result`);
+ assert.sameValue(date.day, day, `${description} day result`);
+ },
+
+ /*
+ * assertPlainDateTime(datetime, year, ..., nanosecond[, description[, era, eraYear]]):
+ *
+ * Shorthand for asserting that each field of a Temporal.PlainDateTime is
+ * equal to an expected value. (Except the `calendar` property, since callers
+ * may want to assert either object equality with an object they put in there,
+ * or the result of datetime.calendar.toString().)
+ */
+ assertPlainDateTime(datetime, year, month, monthCode, day, hour, minute, second, millisecond, microsecond, nanosecond, description = "", era = undefined, eraYear = undefined) {
+ assert(datetime instanceof Temporal.PlainDateTime, `${description} instanceof`);
+ assert.sameValue(datetime.era, era, `${description} era result`);
+ assert.sameValue(datetime.eraYear, eraYear, `${description} eraYear result`);
+ assert.sameValue(datetime.year, year, `${description} year result`);
+ assert.sameValue(datetime.month, month, `${description} month result`);
+ assert.sameValue(datetime.monthCode, monthCode, `${description} monthCode result`);
+ assert.sameValue(datetime.day, day, `${description} day result`);
+ assert.sameValue(datetime.hour, hour, `${description} hour result`);
+ assert.sameValue(datetime.minute, minute, `${description} minute result`);
+ assert.sameValue(datetime.second, second, `${description} second result`);
+ assert.sameValue(datetime.millisecond, millisecond, `${description} millisecond result`);
+ assert.sameValue(datetime.microsecond, microsecond, `${description} microsecond result`);
+ assert.sameValue(datetime.nanosecond, nanosecond, `${description} nanosecond result`);
+ },
+
+ /*
+ * assertPlainDateTimesEqual(actual, expected[, description]):
+ *
+ * Shorthand for asserting that two Temporal.PlainDateTimes are of the correct
+ * type, equal according to their equals() methods, and additionally that
+ * their calendars are the same value.
+ */
+ assertPlainDateTimesEqual(actual, expected, description = "") {
+ assert(expected instanceof Temporal.PlainDateTime, `${description} expected value should be a Temporal.PlainDateTime`);
+ assert(actual instanceof Temporal.PlainDateTime, `${description} instanceof`);
+ assert(actual.equals(expected), `${description} equals method`);
+ assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`);
+ },
+
+ /*
+ * assertPlainMonthDay(monthDay, monthCode, day[, description [, referenceISOYear]]):
+ *
+ * Shorthand for asserting that each field of a Temporal.PlainMonthDay is
+ * equal to an expected value. (Except the `calendar` property, since callers
+ * may want to assert either object equality with an object they put in there,
+ * or the result of monthDay.calendar.toString().)
+ */
+ assertPlainMonthDay(monthDay, monthCode, day, description = "", referenceISOYear = 1972) {
+ assert(monthDay instanceof Temporal.PlainMonthDay, `${description} instanceof`);
+ assert.sameValue(monthDay.monthCode, monthCode, `${description} monthCode result`);
+ assert.sameValue(monthDay.day, day, `${description} day result`);
+ assert.sameValue(monthDay.getISOFields().isoYear, referenceISOYear, `${description} referenceISOYear result`);
+ },
+
+ /*
+ * assertPlainTime(time, hour, ..., nanosecond[, description]):
+ *
+ * Shorthand for asserting that each field of a Temporal.PlainTime is equal to
+ * an expected value.
+ */
+ assertPlainTime(time, hour, minute, second, millisecond, microsecond, nanosecond, description = "") {
+ assert(time instanceof Temporal.PlainTime, `${description} instanceof`);
+ assert.sameValue(time.hour, hour, `${description} hour result`);
+ assert.sameValue(time.minute, minute, `${description} minute result`);
+ assert.sameValue(time.second, second, `${description} second result`);
+ assert.sameValue(time.millisecond, millisecond, `${description} millisecond result`);
+ assert.sameValue(time.microsecond, microsecond, `${description} microsecond result`);
+ assert.sameValue(time.nanosecond, nanosecond, `${description} nanosecond result`);
+ },
+
+ /*
+ * assertPlainTimesEqual(actual, expected[, description]):
+ *
+ * Shorthand for asserting that two Temporal.PlainTimes are of the correct
+ * type and equal according to their equals() methods.
+ */
+ assertPlainTimesEqual(actual, expected, description = "") {
+ assert(expected instanceof Temporal.PlainTime, `${description} expected value should be a Temporal.PlainTime`);
+ assert(actual instanceof Temporal.PlainTime, `${description} instanceof`);
+ assert(actual.equals(expected), `${description} equals method`);
+ },
+
+ /*
+ * assertPlainYearMonth(yearMonth, year, month, monthCode[, description[, era, eraYear, referenceISODay]]):
+ *
+ * Shorthand for asserting that each field of a Temporal.PlainYearMonth is
+ * equal to an expected value. (Except the `calendar` property, since callers
+ * may want to assert either object equality with an object they put in there,
+ * or the result of yearMonth.calendar.toString().)
+ */
+ assertPlainYearMonth(yearMonth, year, month, monthCode, description = "", era = undefined, eraYear = undefined, referenceISODay = 1) {
+ assert(yearMonth instanceof Temporal.PlainYearMonth, `${description} instanceof`);
+ assert.sameValue(yearMonth.era, era, `${description} era result`);
+ assert.sameValue(yearMonth.eraYear, eraYear, `${description} eraYear result`);
+ assert.sameValue(yearMonth.year, year, `${description} year result`);
+ assert.sameValue(yearMonth.month, month, `${description} month result`);
+ assert.sameValue(yearMonth.monthCode, monthCode, `${description} monthCode result`);
+ assert.sameValue(yearMonth.getISOFields().isoDay, referenceISODay, `${description} referenceISODay result`);
+ },
+
+ /*
+ * assertZonedDateTimesEqual(actual, expected[, description]):
+ *
+ * Shorthand for asserting that two Temporal.ZonedDateTimes are of the correct
+ * type, equal according to their equals() methods, and additionally that
+ * their time zones and calendars are the same value.
+ */
+ assertZonedDateTimesEqual(actual, expected, description = "") {
+ assert(expected instanceof Temporal.ZonedDateTime, `${description} expected value should be a Temporal.ZonedDateTime`);
+ assert(actual instanceof Temporal.ZonedDateTime, `${description} instanceof`);
+ assert(actual.equals(expected), `${description} equals method`);
+ assert.sameValue(actual.timeZone, expected.timeZone, `${description} time zone same value`);
+ assert.sameValue(actual.calendar, expected.calendar, `${description} calendar same value`);
+ },
+
+ /*
+ * assertUnreachable(description):
+ *
+ * Helper for asserting that code is not executed. This is useful for
+ * assertions that methods of user calendars and time zones are not called.
+ */
+ assertUnreachable(description) {
+ let message = "This code should not be executed";
+ if (description) {
+ message = `${message}: ${description}`;
+ }
+ throw new Test262Error(message);
+ },
+
+ /*
+ * checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls):
+ *
+ * When an options object with a largestUnit property is synthesized inside
+ * Temporal and passed to user code such as calendar.dateUntil(), the value of
+ * the largestUnit property should be in the singular form, even if the input
+ * was given in the plural form.
+ * (This doesn't apply when the options object is passed through verbatim.)
+ *
+ * func(calendar, largestUnit, index) is the operation under test. It's called
+ * with an instance of a calendar that keeps track of which largestUnit is
+ * passed to dateUntil(), each key of expectedLargestUnitCalls in turn, and
+ * the key's numerical index in case the function needs to generate test data
+ * based on the index. At the end, the actual values passed to dateUntil() are
+ * compared with the array values of expectedLargestUnitCalls.
+ */
+ checkCalendarDateUntilLargestUnitSingular(func, expectedLargestUnitCalls) {
+ const actual = [];
+
+ class DateUntilOptionsCalendar extends Temporal.Calendar {
+ constructor() {
+ super("iso8601");
+ }
+
+ dateUntil(earlier, later, options) {
+ actual.push(options.largestUnit);
+ return super.dateUntil(earlier, later, options);
+ }
+
+ toString() {
+ return "date-until-options";
+ }
+ }
+
+ const calendar = new DateUntilOptionsCalendar();
+ Object.entries(expectedLargestUnitCalls).forEach(([largestUnit, expected], index) => {
+ func(calendar, largestUnit, index);
+ assert.compareArray(actual, expected, `largestUnit passed to calendar.dateUntil() for largestUnit ${largestUnit}`);
+ actual.splice(0); // empty it for the next check
+ });
+ },
+
+ /*
+ * checkPlainDateTimeConversionFastPath(func):
+ *
+ * ToTemporalDate and ToTemporalTime should both, if given a
+ * Temporal.PlainDateTime instance, convert to the desired type by reading the
+ * PlainDateTime's internal slots, rather than calling any getters.
+ *
+ * func(datetime, calendar) is the actual operation to test, that must
+ * internally call the abstract operation ToTemporalDate or ToTemporalTime.
+ * It is passed a Temporal.PlainDateTime instance, as well as the instance's
+ * calendar object (so that it doesn't have to call the calendar getter itself
+ * if it wants to make any assertions about the calendar.)
+ */
+ checkPlainDateTimeConversionFastPath(func, message = "checkPlainDateTimeConversionFastPath") {
+ const actual = [];
+ const expected = [];
+
+ const calendar = new Temporal.Calendar("iso8601");
+ const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar);
+ const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDateTime.prototype);
+ ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => {
+ Object.defineProperty(datetime, property, {
+ get() {
+ actual.push(`get ${formatPropertyName(property)}`);
+ const value = prototypeDescrs[property].get.call(this);
+ return {
+ toString() {
+ actual.push(`toString ${formatPropertyName(property)}`);
+ return value.toString();
+ },
+ valueOf() {
+ actual.push(`valueOf ${formatPropertyName(property)}`);
+ return value;
+ },
+ };
+ },
+ });
+ });
+ Object.defineProperty(datetime, "calendar", {
+ get() {
+ actual.push("get calendar");
+ return calendar;
+ },
+ });
+
+ func(datetime, calendar);
+ assert.compareArray(actual, expected, `${message}: property getters not called`);
+ },
+
+ /*
+ * Check that an options bag that accepts units written in the singular form,
+ * also accepts the same units written in the plural form.
+ * func(unit) should call the method with the appropriate options bag
+ * containing unit as a value. This will be called twice for each element of
+ * validSingularUnits, once with singular and once with plural, and the
+ * results of each pair should be the same (whether a Temporal object or a
+ * primitive value.)
+ */
+ checkPluralUnitsAccepted(func, validSingularUnits) {
+ const plurals = {
+ year: 'years',
+ month: 'months',
+ week: 'weeks',
+ day: 'days',
+ hour: 'hours',
+ minute: 'minutes',
+ second: 'seconds',
+ millisecond: 'milliseconds',
+ microsecond: 'microseconds',
+ nanosecond: 'nanoseconds',
+ };
+
+ validSingularUnits.forEach((unit) => {
+ const singularValue = func(unit);
+ const pluralValue = func(plurals[unit]);
+ const desc = `Plural ${plurals[unit]} produces the same result as singular ${unit}`;
+ if (singularValue instanceof Temporal.Duration) {
+ TemporalHelpers.assertDurationsEqual(pluralValue, singularValue, desc);
+ } else if (singularValue instanceof Temporal.Instant) {
+ TemporalHelpers.assertInstantsEqual(pluralValue, singularValue, desc);
+ } else if (singularValue instanceof Temporal.PlainDateTime) {
+ TemporalHelpers.assertPlainDateTimesEqual(pluralValue, singularValue, desc);
+ } else if (singularValue instanceof Temporal.PlainTime) {
+ TemporalHelpers.assertPlainTimesEqual(pluralValue, singularValue, desc);
+ } else if (singularValue instanceof Temporal.ZonedDateTime) {
+ TemporalHelpers.assertZonedDateTimesEqual(pluralValue, singularValue, desc);
+ } else {
+ assert.sameValue(pluralValue, singularValue);
+ }
+ });
+ },
+
+ /*
+ * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc):
+ *
+ * Checks the type handling of the roundingIncrement option.
+ * checkFunc(roundingIncrement) is a function which takes the value of
+ * roundingIncrement to test, and calls the method under test with it,
+ * returning the result. assertTrueResultFunc(result, description) should
+ * assert that result is the expected result with roundingIncrement: true, and
+ * assertObjectResultFunc(result, description) should assert that result is
+ * the expected result with roundingIncrement being an object with a valueOf()
+ * method.
+ */
+ checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) {
+ // null converts to 0, which is out of range
+ assert.throws(RangeError, () => checkFunc(null), "null");
+ // Booleans convert to either 0 or 1, and 1 is allowed
+ const trueResult = checkFunc(true);
+ assertTrueResultFunc(trueResult, "true");
+ assert.throws(RangeError, () => checkFunc(false), "false");
+ // Symbols and BigInts cannot convert to numbers
+ assert.throws(TypeError, () => checkFunc(Symbol()), "symbol");
+ assert.throws(TypeError, () => checkFunc(2n), "bigint");
+
+ // Objects prefer their valueOf() methods when converting to a number
+ assert.throws(RangeError, () => checkFunc({}), "plain object");
+
+ const expected = [
+ "get roundingIncrement.valueOf",
+ "call roundingIncrement.valueOf",
+ ];
+ const actual = [];
+ const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement");
+ const objectResult = checkFunc(observer);
+ assertObjectResultFunc(objectResult, "object with valueOf");
+ assert.compareArray(actual, expected, "order of operations");
+ },
+
+ /*
+ * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc):
+ *
+ * Checks the type handling of a string option, of which there are several in
+ * Temporal.
+ * propertyName is the name of the option, and value is the value that
+ * assertFunc should expect it to have.
+ * checkFunc(value) is a function which takes the value of the option to test,
+ * and calls the method under test with it, returning the result.
+ * assertFunc(result, description) should assert that result is the expected
+ * result with the option value being an object with a toString() method
+ * which returns the given value.
+ */
+ checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) {
+ // null converts to the string "null", which is an invalid string value
+ assert.throws(RangeError, () => checkFunc(null), "null");
+ // Booleans convert to the strings "true" or "false", which are invalid
+ assert.throws(RangeError, () => checkFunc(true), "true");
+ assert.throws(RangeError, () => checkFunc(false), "false");
+ // Symbols cannot convert to strings
+ assert.throws(TypeError, () => checkFunc(Symbol()), "symbol");
+ // Numbers convert to strings which are invalid
+ assert.throws(RangeError, () => checkFunc(2), "number");
+ // BigInts convert to strings which are invalid
+ assert.throws(RangeError, () => checkFunc(2n), "bigint");
+
+ // Objects prefer their toString() methods when converting to a string
+ assert.throws(RangeError, () => checkFunc({}), "plain object");
+
+ const expected = [
+ `get ${propertyName}.toString`,
+ `call ${propertyName}.toString`,
+ ];
+ const actual = [];
+ const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName);
+ const result = checkFunc(observer);
+ assertFunc(result, "object with toString");
+ assert.compareArray(actual, expected, "order of operations");
+ },
+
+ /*
+ * checkSubclassingIgnored(construct, constructArgs, method, methodArgs,
+ * resultAssertions):
+ *
+ * Methods of Temporal classes that return a new instance of the same class,
+ * must not take the constructor of a subclass into account, nor the @@species
+ * property. This helper runs tests to ensure this.
+ *
+ * construct(...constructArgs) must yield a valid instance of the Temporal
+ * class. instance[method](...methodArgs) is the method call under test, which
+ * must also yield a valid instance of the same Temporal class, not a
+ * subclass. See below for the individual tests that this runs.
+ * resultAssertions() is a function that performs additional assertions on the
+ * instance returned by the method under test.
+ */
+ checkSubclassingIgnored(...args) {
+ this.checkSubclassConstructorNotObject(...args);
+ this.checkSubclassConstructorUndefined(...args);
+ this.checkSubclassConstructorThrows(...args);
+ this.checkSubclassConstructorNotCalled(...args);
+ this.checkSubclassSpeciesInvalidResult(...args);
+ this.checkSubclassSpeciesNotAConstructor(...args);
+ this.checkSubclassSpeciesNull(...args);
+ this.checkSubclassSpeciesUndefined(...args);
+ this.checkSubclassSpeciesThrows(...args);
+ },
+
+ /*
+ * Checks that replacing the 'constructor' property of the instance with
+ * various primitive values does not affect the returned new instance.
+ */
+ checkSubclassConstructorNotObject(construct, constructArgs, method, methodArgs, resultAssertions) {
+ function check(value, description) {
+ const instance = new construct(...constructArgs);
+ instance.constructor = value;
+ const result = instance[method](...methodArgs);
+ assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description);
+ resultAssertions(result);
+ }
+
+ check(null, "null");
+ check(true, "true");
+ check("test", "string");
+ check(Symbol(), "Symbol");
+ check(7, "number");
+ check(7n, "bigint");
+ },
+
+ /*
+ * Checks that replacing the 'constructor' property of the subclass with
+ * undefined does not affect the returned new instance.
+ */
+ checkSubclassConstructorUndefined(construct, constructArgs, method, methodArgs, resultAssertions) {
+ let called = 0;
+
+ class MySubclass extends construct {
+ constructor() {
+ ++called;
+ super(...constructArgs);
+ }
+ }
+
+ const instance = new MySubclass();
+ assert.sameValue(called, 1);
+
+ MySubclass.prototype.constructor = undefined;
+
+ const result = instance[method](...methodArgs);
+ assert.sameValue(called, 1);
+ assert.sameValue(Object.getPrototypeOf(result), construct.prototype);
+ resultAssertions(result);
+ },
+
+ /*
+ * Checks that making the 'constructor' property of the instance throw when
+ * called does not affect the returned new instance.
+ */
+ checkSubclassConstructorThrows(construct, constructArgs, method, methodArgs, resultAssertions) {
+ function CustomError() {}
+ const instance = new construct(...constructArgs);
+ Object.defineProperty(instance, "constructor", {
+ get() {
+ throw new CustomError();
+ }
+ });
+ const result = instance[method](...methodArgs);
+ assert.sameValue(Object.getPrototypeOf(result), construct.prototype);
+ resultAssertions(result);
+ },
+
+ /*
+ * Checks that when subclassing, the subclass constructor is not called by
+ * the method under test.
+ */
+ checkSubclassConstructorNotCalled(construct, constructArgs, method, methodArgs, resultAssertions) {
+ let called = 0;
+
+ class MySubclass extends construct {
+ constructor() {
+ ++called;
+ super(...constructArgs);
+ }
+ }
+
+ const instance = new MySubclass();
+ assert.sameValue(called, 1);
+
+ const result = instance[method](...methodArgs);
+ assert.sameValue(called, 1);
+ assert.sameValue(Object.getPrototypeOf(result), construct.prototype);
+ resultAssertions(result);
+ },
+
+ /*
+ * Check that the constructor's @@species property is ignored when it's a
+ * constructor that returns a non-object value.
+ */
+ checkSubclassSpeciesInvalidResult(construct, constructArgs, method, methodArgs, resultAssertions) {
+ function check(value, description) {
+ const instance = new construct(...constructArgs);
+ instance.constructor = {
+ [Symbol.species]: function() {
+ return value;
+ },
+ };
+ const result = instance[method](...methodArgs);
+ assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description);
+ resultAssertions(result);
+ }
+
+ check(undefined, "undefined");
+ check(null, "null");
+ check(true, "true");
+ check("test", "string");
+ check(Symbol(), "Symbol");
+ check(7, "number");
+ check(7n, "bigint");
+ check({}, "plain object");
+ },
+
+ /*
+ * Check that the constructor's @@species property is ignored when it's not a
+ * constructor.
+ */
+ checkSubclassSpeciesNotAConstructor(construct, constructArgs, method, methodArgs, resultAssertions) {
+ function check(value, description) {
+ const instance = new construct(...constructArgs);
+ instance.constructor = {
+ [Symbol.species]: value,
+ };
+ const result = instance[method](...methodArgs);
+ assert.sameValue(Object.getPrototypeOf(result), construct.prototype, description);
+ resultAssertions(result);
+ }
+
+ check(true, "true");
+ check("test", "string");
+ check(Symbol(), "Symbol");
+ check(7, "number");
+ check(7n, "bigint");
+ check({}, "plain object");
+ },
+
+ /*
+ * Check that the constructor's @@species property is ignored when it's null.
+ */
+ checkSubclassSpeciesNull(construct, constructArgs, method, methodArgs, resultAssertions) {
+ let called = 0;
+
+ class MySubclass extends construct {
+ constructor() {
+ ++called;
+ super(...constructArgs);
+ }
+ }
+
+ const instance = new MySubclass();
+ assert.sameValue(called, 1);
+
+ MySubclass.prototype.constructor = {
+ [Symbol.species]: null,
+ };
+
+ const result = instance[method](...methodArgs);
+ assert.sameValue(called, 1);
+ assert.sameValue(Object.getPrototypeOf(result), construct.prototype);
+ resultAssertions(result);
+ },
+
+ /*
+ * Check that the constructor's @@species property is ignored when it's
+ * undefined.
+ */
+ checkSubclassSpeciesUndefined(construct, constructArgs, method, methodArgs, resultAssertions) {
+ let called = 0;
+
+ class MySubclass extends construct {
+ constructor() {
+ ++called;
+ super(...constructArgs);
+ }
+ }
+
+ const instance = new MySubclass();
+ assert.sameValue(called, 1);
+
+ MySubclass.prototype.constructor = {
+ [Symbol.species]: undefined,
+ };
+
+ const result = instance[method](...methodArgs);
+ assert.sameValue(called, 1);
+ assert.sameValue(Object.getPrototypeOf(result), construct.prototype);
+ resultAssertions(result);
+ },
+
+ /*
+ * Check that the constructor's @@species property is ignored when it throws,
+ * i.e. it is not called at all.
+ */
+ checkSubclassSpeciesThrows(construct, constructArgs, method, methodArgs, resultAssertions) {
+ function CustomError() {}
+
+ const instance = new construct(...constructArgs);
+ instance.constructor = {
+ get [Symbol.species]() {
+ throw new CustomError();
+ },
+ };
+
+ const result = instance[method](...methodArgs);
+ assert.sameValue(Object.getPrototypeOf(result), construct.prototype);
+ },
+
+ /*
+ * checkSubclassingIgnoredStatic(construct, method, methodArgs, resultAssertions):
+ *
+ * Static methods of Temporal classes that return a new instance of the class,
+ * must not use the this-value as a constructor. This helper runs tests to
+ * ensure this.
+ *
+ * construct[method](...methodArgs) is the static method call under test, and
+ * must yield a valid instance of the Temporal class, not a subclass. See
+ * below for the individual tests that this runs.
+ * resultAssertions() is a function that performs additional assertions on the
+ * instance returned by the method under test.
+ */
+ checkSubclassingIgnoredStatic(...args) {
+ this.checkStaticInvalidReceiver(...args);
+ this.checkStaticReceiverNotCalled(...args);
+ this.checkThisValueNotCalled(...args);
+ },
+
+ /*
+ * Check that calling the static method with a receiver that's not callable,
+ * still calls the intrinsic constructor.
+ */
+ checkStaticInvalidReceiver(construct, method, methodArgs, resultAssertions) {
+ function check(value, description) {
+ const result = construct[method].apply(value, methodArgs);
+ assert.sameValue(Object.getPrototypeOf(result), construct.prototype);
+ resultAssertions(result);
+ }
+
+ check(undefined, "undefined");
+ check(null, "null");
+ check(true, "true");
+ check("test", "string");
+ check(Symbol(), "symbol");
+ check(7, "number");
+ check(7n, "bigint");
+ check({}, "Non-callable object");
+ },
+
+ /*
+ * Check that calling the static method with a receiver that returns a value
+ * that's not callable, still calls the intrinsic constructor.
+ */
+ checkStaticReceiverNotCalled(construct, method, methodArgs, resultAssertions) {
+ function check(value, description) {
+ const receiver = function () {
+ return value;
+ };
+ const result = construct[method].apply(receiver, methodArgs);
+ assert.sameValue(Object.getPrototypeOf(result), construct.prototype);
+ resultAssertions(result);
+ }
+
+ check(undefined, "undefined");
+ check(null, "null");
+ check(true, "true");
+ check("test", "string");
+ check(Symbol(), "symbol");
+ check(7, "number");
+ check(7n, "bigint");
+ check({}, "Non-callable object");
+ },
+
+ /*
+ * Check that the receiver isn't called.
+ */
+ checkThisValueNotCalled(construct, method, methodArgs, resultAssertions) {
+ let called = false;
+
+ class MySubclass extends construct {
+ constructor(...args) {
+ called = true;
+ super(...args);
+ }
+ }
+
+ const result = MySubclass[method](...methodArgs);
+ assert.sameValue(called, false);
+ assert.sameValue(Object.getPrototypeOf(result), construct.prototype);
+ resultAssertions(result);
+ },
+
+ /*
+ * Check that any iterable returned from a custom time zone's
+ * getPossibleInstantsFor() method is exhausted.
+ * The custom time zone object is passed in to func().
+ * expected is an array of strings representing the expected calls to the
+ * getPossibleInstantsFor() method. The PlainDateTimes that it is called with,
+ * are compared (using their toString() results) with the array.
+ */
+ checkTimeZonePossibleInstantsIterable(func, expected) {
+ // A custom time zone that returns an iterable instead of an array from its
+ // getPossibleInstantsFor() method, and for testing purposes skips
+ // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on
+ // January 3, 2030. Otherwise identical to the UTC time zone.
+ class TimeZonePossibleInstantsIterable extends Temporal.TimeZone {
+ constructor() {
+ super("UTC");
+ this.getPossibleInstantsForCallCount = 0;
+ this.getPossibleInstantsForCalledWith = [];
+ this.getPossibleInstantsForReturns = [];
+ this.iteratorExhausted = [];
+ }
+
+ toString() {
+ return "Custom/Iterable";
+ }
+
+ getOffsetNanosecondsFor(instant) {
+ if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 &&
+ Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) {
+ return 3600_000_000_000;
+ } else {
+ return 0;
+ }
+ }
+
+ getPossibleInstantsFor(dateTime) {
+ this.getPossibleInstantsForCallCount++;
+ this.getPossibleInstantsForCalledWith.push(dateTime);
+
+ // Fake DST transition
+ let retval = super.getPossibleInstantsFor(dateTime);
+ if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) {
+ retval = [];
+ } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) {
+ retval.push(retval[0].subtract({ hours: 1 }));
+ } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) {
+ retval[0] = retval[0].subtract({ hours: 1 });
+ }
+
+ this.getPossibleInstantsForReturns.push(retval);
+ this.iteratorExhausted.push(false);
+ return {
+ callIndex: this.getPossibleInstantsForCallCount - 1,
+ timeZone: this,
+ *[Symbol.iterator]() {
+ yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex];
+ this.timeZone.iteratorExhausted[this.callIndex] = true;
+ },
+ };
+ }
+ }
+
+ const timeZone = new TimeZonePossibleInstantsIterable();
+ func(timeZone);
+
+ assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times");
+
+ for (let index = 0; index < expected.length; index++) {
+ assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime");
+ assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable");
+ }
+ },
+
+ /*
+ * Check that any calendar-carrying Temporal object has its [[Calendar]]
+ * internal slot read by ToTemporalCalendar, and does not fetch the calendar
+ * by calling getters.
+ * The custom calendar object is passed in to func() so that it can do its
+ * own additional assertions involving the calendar if necessary. (Sometimes
+ * there is nothing to assert as the calendar isn't stored anywhere that can
+ * be asserted about.)
+ */
+ checkToTemporalCalendarFastPath(func) {
+ class CalendarFastPathCheck extends Temporal.Calendar {
+ constructor() {
+ super("iso8601");
+ }
+
+ toString() {
+ return "fast-path-check";
+ }
+ }
+ const calendar = new CalendarFastPathCheck();
+
+ const plainDate = new Temporal.PlainDate(2000, 5, 2, calendar);
+ const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar);
+ const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar);
+ const plainYearMonth = new Temporal.PlainYearMonth(2000, 5, calendar);
+ const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar);
+
+ [plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((temporalObject) => {
+ const actual = [];
+ const expected = [];
+
+ Object.defineProperty(temporalObject, "calendar", {
+ get() {
+ actual.push("get calendar");
+ return calendar;
+ },
+ });
+
+ func(temporalObject, calendar);
+ assert.compareArray(actual, expected, "calendar getter not called");
+ });
+ },
+
+ checkToTemporalInstantFastPath(func) {
+ const actual = [];
+ const expected = [];
+
+ const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+ Object.defineProperty(datetime, 'toString', {
+ get() {
+ actual.push("get toString");
+ return function (options) {
+ actual.push("call toString");
+ return Temporal.ZonedDateTime.prototype.toString.call(this, options);
+ };
+ },
+ });
+
+ func(datetime);
+ assert.compareArray(actual, expected, "toString not called");
+ },
+
+ checkToTemporalPlainDateTimeFastPath(func) {
+ const actual = [];
+ const expected = [];
+
+ const calendar = new Temporal.Calendar("iso8601");
+ const date = new Temporal.PlainDate(2000, 5, 2, calendar);
+ const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.PlainDate.prototype);
+ ["year", "month", "monthCode", "day"].forEach((property) => {
+ Object.defineProperty(date, property, {
+ get() {
+ actual.push(`get ${formatPropertyName(property)}`);
+ const value = prototypeDescrs[property].get.call(this);
+ return TemporalHelpers.toPrimitiveObserver(actual, value, property);
+ },
+ });
+ });
+ ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((property) => {
+ Object.defineProperty(date, property, {
+ get() {
+ actual.push(`get ${formatPropertyName(property)}`);
+ return undefined;
+ },
+ });
+ });
+ Object.defineProperty(date, "calendar", {
+ get() {
+ actual.push("get calendar");
+ return calendar;
+ },
+ });
+
+ func(date, calendar);
+ assert.compareArray(actual, expected, "property getters not called");
+ },
+
+ /*
+ * A custom calendar used in prototype pollution checks. Verifies that the
+ * fromFields methods are always called with a null-prototype fields object.
+ */
+ calendarCheckFieldsPrototypePollution() {
+ class CalendarCheckFieldsPrototypePollution extends Temporal.Calendar {
+ constructor() {
+ super("iso8601");
+ this.dateFromFieldsCallCount = 0;
+ this.yearMonthFromFieldsCallCount = 0;
+ this.monthDayFromFieldsCallCount = 0;
+ }
+
+ // toString must remain "iso8601", so that some methods don't throw due to
+ // incompatible calendars
+
+ dateFromFields(fields, options = {}) {
+ this.dateFromFieldsCallCount++;
+ assert.sameValue(Object.getPrototypeOf(fields), null, "dateFromFields should be called with null-prototype fields object");
+ return super.dateFromFields(fields, options);
+ }
+
+ yearMonthFromFields(fields, options = {}) {
+ this.yearMonthFromFieldsCallCount++;
+ assert.sameValue(Object.getPrototypeOf(fields), null, "yearMonthFromFields should be called with null-prototype fields object");
+ return super.yearMonthFromFields(fields, options);
+ }
+
+ monthDayFromFields(fields, options = {}) {
+ this.monthDayFromFieldsCallCount++;
+ assert.sameValue(Object.getPrototypeOf(fields), null, "monthDayFromFields should be called with null-prototype fields object");
+ return super.monthDayFromFields(fields, options);
+ }
+ }
+
+ return new CalendarCheckFieldsPrototypePollution();
+ },
+
+ /*
+ * A custom calendar used in prototype pollution checks. Verifies that the
+ * mergeFields() method is always called with null-prototype fields objects.
+ */
+ calendarCheckMergeFieldsPrototypePollution() {
+ class CalendarCheckMergeFieldsPrototypePollution extends Temporal.Calendar {
+ constructor() {
+ super("iso8601");
+ this.mergeFieldsCallCount = 0;
+ }
+
+ toString() {
+ return "merge-fields-null-proto";
+ }
+
+ mergeFields(fields, additionalFields) {
+ this.mergeFieldsCallCount++;
+ assert.sameValue(Object.getPrototypeOf(fields), null, "mergeFields should be called with null-prototype fields object (first argument)");
+ assert.sameValue(Object.getPrototypeOf(additionalFields), null, "mergeFields should be called with null-prototype fields object (second argument)");
+ return super.mergeFields(fields, additionalFields);
+ }
+ }
+
+ return new CalendarCheckMergeFieldsPrototypePollution();
+ },
+
+ /*
+ * A custom calendar used in prototype pollution checks. Verifies that methods
+ * are always called with a null-prototype options object.
+ */
+ calendarCheckOptionsPrototypePollution() {
+ class CalendarCheckOptionsPrototypePollution extends Temporal.Calendar {
+ constructor() {
+ super("iso8601");
+ this.yearMonthFromFieldsCallCount = 0;
+ this.dateUntilCallCount = 0;
+ }
+
+ toString() {
+ return "options-null-proto";
+ }
+
+ yearMonthFromFields(fields, options) {
+ this.yearMonthFromFieldsCallCount++;
+ assert.sameValue(Object.getPrototypeOf(options), null, "yearMonthFromFields should be called with null-prototype options");
+ return super.yearMonthFromFields(fields, options);
+ }
+
+ dateUntil(one, two, options) {
+ this.dateUntilCallCount++;
+ assert.sameValue(Object.getPrototypeOf(options), null, "dateUntil should be called with null-prototype options");
+ return super.dateUntil(one, two, options);
+ }
+ }
+
+ return new CalendarCheckOptionsPrototypePollution();
+ },
+
+ /*
+ * A custom calendar that asserts its dateAdd() method is called with the
+ * options parameter having the value undefined.
+ */
+ calendarDateAddUndefinedOptions() {
+ class CalendarDateAddUndefinedOptions extends Temporal.Calendar {
+ constructor() {
+ super("iso8601");
+ this.dateAddCallCount = 0;
+ }
+
+ toString() {
+ return "dateadd-undef-options";
+ }
+
+ dateAdd(date, duration, options) {
+ this.dateAddCallCount++;
+ assert.sameValue(options, undefined, "dateAdd shouldn't be called with options");
+ return super.dateAdd(date, duration, options);
+ }
+ }
+ return new CalendarDateAddUndefinedOptions();
+ },
+
+ /*
+ * A custom calendar that asserts its dateAdd() method is called with a
+ * PlainDate instance. Optionally, it also asserts that the PlainDate instance
+ * is the specific object `this.specificPlainDate`, if it is set by the
+ * calling code.
+ */
+ calendarDateAddPlainDateInstance() {
+ class CalendarDateAddPlainDateInstance extends Temporal.Calendar {
+ constructor() {
+ super("iso8601");
+ this.dateAddCallCount = 0;
+ this.specificPlainDate = undefined;
+ }
+
+ toString() {
+ return "dateadd-plain-date-instance";
+ }
+
+ dateAdd(date, duration, options) {
+ this.dateAddCallCount++;
+ assert(date instanceof Temporal.PlainDate, "dateAdd() should be called with a PlainDate instance");
+ if (this.dateAddCallCount === 1 && this.specificPlainDate) {
+ assert.sameValue(date, this.specificPlainDate, `dateAdd() should be called first with the specific PlainDate instance ${this.specificPlainDate}`);
+ }
+ return super.dateAdd(date, duration, options);
+ }
+ }
+ return new CalendarDateAddPlainDateInstance();
+ },
+
+ /*
+ * A custom calendar that returns @returnValue from its dateUntil() method,
+ * recording the call in @calls.
+ */
+ calendarDateUntilObservable(calls, returnValue) {
+ class CalendarDateUntilObservable extends Temporal.Calendar {
+ constructor() {
+ super("iso8601");
+ }
+
+ dateUntil() {
+ calls.push("call dateUntil");
+ return returnValue;
+ }
+ }
+
+ return new CalendarDateUntilObservable();
+ },
+
+ /*
+ * A custom calendar that returns an iterable instead of an array from its
+ * fields() method, otherwise identical to the ISO calendar.
+ */
+ calendarFieldsIterable() {
+ class CalendarFieldsIterable extends Temporal.Calendar {
+ constructor() {
+ super("iso8601");
+ this.fieldsCallCount = 0;
+ this.fieldsCalledWith = [];
+ this.iteratorExhausted = [];
+ }
+
+ toString() {
+ return "fields-iterable";
+ }
+
+ fields(fieldNames) {
+ this.fieldsCallCount++;
+ this.fieldsCalledWith.push(fieldNames.slice());
+ this.iteratorExhausted.push(false);
+ return {
+ callIndex: this.fieldsCallCount - 1,
+ calendar: this,
+ *[Symbol.iterator]() {
+ yield* this.calendar.fieldsCalledWith[this.callIndex];
+ this.calendar.iteratorExhausted[this.callIndex] = true;
+ },
+ };
+ }
+ }
+ return new CalendarFieldsIterable();
+ },
+
+ /*
+ * A custom calendar that asserts its ...FromFields() methods are called with
+ * the options parameter having the value undefined.
+ */
+ calendarFromFieldsUndefinedOptions() {
+ class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar {
+ constructor() {
+ super("iso8601");
+ this.dateFromFieldsCallCount = 0;
+ this.monthDayFromFieldsCallCount = 0;
+ this.yearMonthFromFieldsCallCount = 0;
+ }
+
+ toString() {
+ return "from-fields-undef-options";
+ }
+
+ dateFromFields(fields, options) {
+ this.dateFromFieldsCallCount++;
+ assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options");
+ return super.dateFromFields(fields, options);
+ }
+
+ yearMonthFromFields(fields, options) {
+ this.yearMonthFromFieldsCallCount++;
+ assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options");
+ return super.yearMonthFromFields(fields, options);
+ }
+
+ monthDayFromFields(fields, options) {
+ this.monthDayFromFieldsCallCount++;
+ assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options");
+ return super.monthDayFromFields(fields, options);
+ }
+ }
+ return new CalendarFromFieldsUndefinedOptions();
+ },
+
+ /*
+ * A custom calendar that modifies the fields object passed in to
+ * dateFromFields, sabotaging its time properties.
+ */
+ calendarMakeInfinityTime() {
+ class CalendarMakeInfinityTime extends Temporal.Calendar {
+ constructor() {
+ super("iso8601");
+ }
+
+ dateFromFields(fields, options) {
+ const retval = super.dateFromFields(fields, options);
+ fields.hour = Infinity;
+ fields.minute = Infinity;
+ fields.second = Infinity;
+ fields.millisecond = Infinity;
+ fields.microsecond = Infinity;
+ fields.nanosecond = Infinity;
+ return retval;
+ }
+ }
+ return new CalendarMakeInfinityTime();
+ },
+
+ /*
+ * A custom calendar that defines getters on the fields object passed into
+ * dateFromFields that throw, sabotaging its time properties.
+ */
+ calendarMakeInvalidGettersTime() {
+ class CalendarMakeInvalidGettersTime extends Temporal.Calendar {
+ constructor() {
+ super("iso8601");
+ }
+
+ dateFromFields(fields, options) {
+ const retval = super.dateFromFields(fields, options);
+ const throwingDescriptor = {
+ get() {
+ throw new Test262Error("reading a sabotaged time field");
+ },
+ };
+ Object.defineProperties(fields, {
+ hour: throwingDescriptor,
+ minute: throwingDescriptor,
+ second: throwingDescriptor,
+ millisecond: throwingDescriptor,
+ microsecond: throwingDescriptor,
+ nanosecond: throwingDescriptor,
+ });
+ return retval;
+ }
+ }
+ return new CalendarMakeInvalidGettersTime();
+ },
+
+ /*
+ * A custom calendar whose mergeFields() method returns a proxy object with
+ * all of its Get and HasProperty operations observable, as well as adding a
+ * "shouldNotBeCopied": true property.
+ */
+ calendarMergeFieldsGetters() {
+ class CalendarMergeFieldsGetters extends Temporal.Calendar {
+ constructor() {
+ super("iso8601");
+ this.mergeFieldsReturnOperations = [];
+ }
+
+ toString() {
+ return "merge-fields-getters";
+ }
+
+ dateFromFields(fields, options) {
+ assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied");
+ return super.dateFromFields(fields, options);
+ }
+
+ yearMonthFromFields(fields, options) {
+ assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied");
+ return super.yearMonthFromFields(fields, options);
+ }
+
+ monthDayFromFields(fields, options) {
+ assert.sameValue(fields.shouldNotBeCopied, undefined, "extra fields should not be copied");
+ return super.monthDayFromFields(fields, options);
+ }
+
+ mergeFields(fields, additionalFields) {
+ const retval = super.mergeFields(fields, additionalFields);
+ retval._calendar = this;
+ retval.shouldNotBeCopied = true;
+ return new Proxy(retval, {
+ get(target, key) {
+ target._calendar.mergeFieldsReturnOperations.push(`get ${key}`);
+ const result = target[key];
+ if (result === undefined) {
+ return undefined;
+ }
+ return TemporalHelpers.toPrimitiveObserver(target._calendar.mergeFieldsReturnOperations, result, key);
+ },
+ has(target, key) {
+ target._calendar.mergeFieldsReturnOperations.push(`has ${key}`);
+ return key in target;
+ },
+ });
+ }
+ }
+ return new CalendarMergeFieldsGetters();
+ },
+
+ /*
+ * A custom calendar whose mergeFields() method returns a primitive value,
+ * given by @primitive, and which records the number of calls made to its
+ * dateFromFields(), yearMonthFromFields(), and monthDayFromFields() methods.
+ */
+ calendarMergeFieldsReturnsPrimitive(primitive) {
+ class CalendarMergeFieldsPrimitive extends Temporal.Calendar {
+ constructor(mergeFieldsReturnValue) {
+ super("iso8601");
+ this._mergeFieldsReturnValue = mergeFieldsReturnValue;
+ this.dateFromFieldsCallCount = 0;
+ this.monthDayFromFieldsCallCount = 0;
+ this.yearMonthFromFieldsCallCount = 0;
+ }
+
+ toString() {
+ return "merge-fields-primitive";
+ }
+
+ dateFromFields(fields, options) {
+ this.dateFromFieldsCallCount++;
+ return super.dateFromFields(fields, options);
+ }
+
+ yearMonthFromFields(fields, options) {
+ this.yearMonthFromFieldsCallCount++;
+ return super.yearMonthFromFields(fields, options);
+ }
+
+ monthDayFromFields(fields, options) {
+ this.monthDayFromFieldsCallCount++;
+ return super.monthDayFromFields(fields, options);
+ }
+
+ mergeFields() {
+ return this._mergeFieldsReturnValue;
+ }
+ }
+ return new CalendarMergeFieldsPrimitive(primitive);
+ },
+
+ /*
+ * crossDateLineTimeZone():
+ *
+ * This returns an instance of a custom time zone class that implements one
+ * single transition where the time zone moves from one side of the
+ * International Date Line to the other, for the purpose of testing time zone
+ * calculations without depending on system time zone data.
+ *
+ * The transition occurs at epoch second 1325239200 and goes from offset
+ * -10:00 to +14:00. In other words, the time zone skips the whole calendar
+ * day of 2011-12-30. This is the same as the real-life transition in the
+ * Pacific/Apia time zone.
+ */
+ crossDateLineTimeZone() {
+ const { compare } = Temporal.PlainDateTime;
+ const skippedDay = new Temporal.PlainDate(2011, 12, 30);
+ const transitionEpoch = 1325239200_000_000_000n;
+ const beforeOffset = new Temporal.TimeZone("-10:00");
+ const afterOffset = new Temporal.TimeZone("+14:00");
+
+ class CrossDateLineTimeZone extends Temporal.TimeZone {
+ constructor() {
+ super("+14:00");
+ }
+
+ getOffsetNanosecondsFor(instant) {
+ if (instant.epochNanoseconds < transitionEpoch) {
+ return beforeOffset.getOffsetNanosecondsFor(instant);
+ }
+ return afterOffset.getOffsetNanosecondsFor(instant);
+ }
+
+ getPossibleInstantsFor(datetime) {
+ const comparison = Temporal.PlainDate.compare(datetime.toPlainDate(), skippedDay);
+ if (comparison === 0) {
+ return [];
+ }
+ if (comparison < 0) {
+ return [beforeOffset.getInstantFor(datetime)];
+ }
+ return [afterOffset.getInstantFor(datetime)];
+ }
+
+ getPreviousTransition(instant) {
+ if (instant.epochNanoseconds > transitionEpoch) return new Temporal.Instant(transitionEpoch);
+ return null;
+ }
+
+ getNextTransition(instant) {
+ if (instant.epochNanoseconds < transitionEpoch) return new Temporal.Instant(transitionEpoch);
+ return null;
+ }
+
+ toString() {
+ return "Custom/Date_Line";
+ }
+ }
+ return new CrossDateLineTimeZone();
+ },
+
+ /*
+ * observeProperty(calls, object, propertyName, value):
+ *
+ * Defines an own property @object.@propertyName with value @value, that
+ * will log any calls to its accessors to the array @calls.
+ */
+ observeProperty(calls, object, propertyName, value, objectName = "") {
+ Object.defineProperty(object, propertyName, {
+ get() {
+ calls.push(`get ${formatPropertyName(propertyName, objectName)}`);
+ return value;
+ },
+ set(v) {
+ calls.push(`set ${formatPropertyName(propertyName, objectName)}`);
+ }
+ });
+ },
+
+ /*
+ * observeMethod(calls, object, propertyName, value):
+ *
+ * Defines an own property @object.@propertyName with value @value, that
+ * will log any calls of @value to the array @calls.
+ */
+ observeMethod(calls, object, propertyName, objectName = "") {
+ const method = object[propertyName];
+ object[propertyName] = function () {
+ calls.push(`call ${formatPropertyName(propertyName, objectName)}`);
+ return method.apply(object, arguments);
+ };
+ },
+
+ /*
+ * Used for substituteMethod to indicate default behavior instead of a
+ * substituted value
+ */
+ SUBSTITUTE_SKIP: SKIP_SYMBOL,
+
+ /*
+ * substituteMethod(object, propertyName, values):
+ *
+ * Defines an own property @object.@propertyName that will, for each
+ * subsequent call to the method previously defined as
+ * @object.@propertyName:
+ * - Call the method, if no more values remain
+ * - Call the method, if the value in @values for the corresponding call
+ * is SUBSTITUTE_SKIP
+ * - Otherwise, return the corresponding value in @value
+ */
+ substituteMethod(object, propertyName, values) {
+ let calls = 0;
+ const method = object[propertyName];
+ object[propertyName] = function () {
+ if (calls >= values.length) {
+ return method.apply(object, arguments);
+ } else if (values[calls] === SKIP_SYMBOL) {
+ calls++;
+ return method.apply(object, arguments);
+ } else {
+ return values[calls++];
+ }
+ };
+ },
+
+ /*
+ * calendarObserver:
+ * A custom calendar that behaves exactly like the ISO 8601 calendar but
+ * tracks calls to any of its methods, and Get/Has operations on its
+ * properties, by appending messages to an array. This is for the purpose of
+ * testing order of operations that are observable from user code.
+ * objectName is used in the log.
+ */
+ calendarObserver(calls, objectName, methodOverrides = {}) {
+ const iso8601 = new Temporal.Calendar("iso8601");
+ const trackingMethods = {
+ dateFromFields(...args) {
+ calls.push(`call ${objectName}.dateFromFields`);
+ if ('dateFromFields' in methodOverrides) {
+ const value = methodOverrides.dateFromFields;
+ return typeof value === "function" ? value(...args) : value;
+ }
+ const originalResult = iso8601.dateFromFields(...args);
+ // Replace the calendar in the result with the call-tracking calendar
+ const {isoYear, isoMonth, isoDay} = originalResult.getISOFields();
+ const result = new Temporal.PlainDate(isoYear, isoMonth, isoDay, this);
+ // Remove the HasProperty check resulting from the above constructor call
+ assert.sameValue(calls.pop(), `has ${objectName}.calendar`);
+ return result;
+ },
+ yearMonthFromFields(...args) {
+ calls.push(`call ${objectName}.yearMonthFromFields`);
+ if ('yearMonthFromFields' in methodOverrides) {
+ const value = methodOverrides.yearMonthFromFields;
+ return typeof value === "function" ? value(...args) : value;
+ }
+ const originalResult = iso8601.yearMonthFromFields(...args);
+ // Replace the calendar in the result with the call-tracking calendar
+ const {isoYear, isoMonth, isoDay} = originalResult.getISOFields();
+ const result = new Temporal.PlainYearMonth(isoYear, isoMonth, this, isoDay);
+ // Remove the HasProperty check resulting from the above constructor call
+ assert.sameValue(calls.pop(), `has ${objectName}.calendar`);
+ return result;
+ },
+ monthDayFromFields(...args) {
+ calls.push(`call ${objectName}.monthDayFromFields`);
+ if ('monthDayFromFields' in methodOverrides) {
+ const value = methodOverrides.monthDayFromFields;
+ return typeof value === "function" ? value(...args) : value;
+ }
+ const originalResult = iso8601.monthDayFromFields(...args);
+ // Replace the calendar in the result with the call-tracking calendar
+ const {isoYear, isoMonth, isoDay} = originalResult.getISOFields();
+ const result = new Temporal.PlainMonthDay(isoMonth, isoDay, this, isoYear);
+ // Remove the HasProperty check resulting from the above constructor call
+ assert.sameValue(calls.pop(), `has ${objectName}.calendar`);
+ return result;
+ },
+ dateAdd(...args) {
+ calls.push(`call ${objectName}.dateAdd`);
+ if ('dateAdd' in methodOverrides) {
+ const value = methodOverrides.dateAdd;
+ return typeof value === "function" ? value(...args) : value;
+ }
+ const originalResult = iso8601.dateAdd(...args);
+ const {isoYear, isoMonth, isoDay} = originalResult.getISOFields();
+ const result = new Temporal.PlainDate(isoYear, isoMonth, isoDay, this);
+ // Remove the HasProperty check resulting from the above constructor call
+ assert.sameValue(calls.pop(), `has ${objectName}.calendar`);
+ return result;
+ }
+ };
+ // Automatically generate the other methods that don't need any custom code
+ ["toString", "dateUntil", "era", "eraYear", "year", "month", "monthCode", "day", "daysInMonth", "fields", "mergeFields"].forEach((methodName) => {
+ trackingMethods[methodName] = function (...args) {
+ calls.push(`call ${formatPropertyName(methodName, objectName)}`);
+ if (methodName in methodOverrides) {
+ const value = methodOverrides[methodName];
+ return typeof value === "function" ? value(...args) : value;
+ }
+ return iso8601[methodName](...args);
+ };
+ });
+ return new Proxy(trackingMethods, {
+ get(target, key, receiver) {
+ const result = Reflect.get(target, key, receiver);
+ calls.push(`get ${formatPropertyName(key, objectName)}`);
+ return result;
+ },
+ has(target, key) {
+ calls.push(`has ${formatPropertyName(key, objectName)}`);
+ return Reflect.has(target, key);
+ },
+ });
+ },
+
+ /*
+ * A custom calendar that does not allow any of its methods to be called, for
+ * the purpose of asserting that a particular operation does not call into
+ * user code.
+ */
+ calendarThrowEverything() {
+ class CalendarThrowEverything extends Temporal.Calendar {
+ constructor() {
+ super("iso8601");
+ }
+ toString() {
+ TemporalHelpers.assertUnreachable("toString should not be called");
+ }
+ dateFromFields() {
+ TemporalHelpers.assertUnreachable("dateFromFields should not be called");
+ }
+ yearMonthFromFields() {
+ TemporalHelpers.assertUnreachable("yearMonthFromFields should not be called");
+ }
+ monthDayFromFields() {
+ TemporalHelpers.assertUnreachable("monthDayFromFields should not be called");
+ }
+ dateAdd() {
+ TemporalHelpers.assertUnreachable("dateAdd should not be called");
+ }
+ dateUntil() {
+ TemporalHelpers.assertUnreachable("dateUntil should not be called");
+ }
+ era() {
+ TemporalHelpers.assertUnreachable("era should not be called");
+ }
+ eraYear() {
+ TemporalHelpers.assertUnreachable("eraYear should not be called");
+ }
+ year() {
+ TemporalHelpers.assertUnreachable("year should not be called");
+ }
+ month() {
+ TemporalHelpers.assertUnreachable("month should not be called");
+ }
+ monthCode() {
+ TemporalHelpers.assertUnreachable("monthCode should not be called");
+ }
+ day() {
+ TemporalHelpers.assertUnreachable("day should not be called");
+ }
+ fields() {
+ TemporalHelpers.assertUnreachable("fields should not be called");
+ }
+ mergeFields() {
+ TemporalHelpers.assertUnreachable("mergeFields should not be called");
+ }
+ }
+
+ return new CalendarThrowEverything();
+ },
+
+ /*
+ * oneShiftTimeZone(shiftInstant, shiftNanoseconds):
+ *
+ * In the case of a spring-forward time zone offset transition (skipped time),
+ * and disambiguation === 'earlier', BuiltinTimeZoneGetInstantFor subtracts a
+ * negative number of nanoseconds from a PlainDateTime, which should balance
+ * with the microseconds field.
+ *
+ * This returns an instance of a custom time zone class which skips a length
+ * of time equal to shiftNanoseconds (a number), at the Temporal.Instant
+ * shiftInstant. Before shiftInstant, it's identical to UTC, and after
+ * shiftInstant it's a constant-offset time zone.
+ *
+ * It provides a getPossibleInstantsForCalledWith member which is an array
+ * with the result of calling toString() on any PlainDateTimes passed to
+ * getPossibleInstantsFor().
+ */
+ oneShiftTimeZone(shiftInstant, shiftNanoseconds) {
+ class OneShiftTimeZone extends Temporal.TimeZone {
+ constructor(shiftInstant, shiftNanoseconds) {
+ super("+00:00");
+ this._shiftInstant = shiftInstant;
+ this._epoch1 = shiftInstant.epochNanoseconds;
+ this._epoch2 = this._epoch1 + BigInt(shiftNanoseconds);
+ this._shiftNanoseconds = shiftNanoseconds;
+ this._shift = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, this._shiftNanoseconds);
+ this.getPossibleInstantsForCalledWith = [];
+ }
+
+ _isBeforeShift(instant) {
+ return instant.epochNanoseconds < this._epoch1;
+ }
+
+ getOffsetNanosecondsFor(instant) {
+ return this._isBeforeShift(instant) ? 0 : this._shiftNanoseconds;
+ }
+
+ getPossibleInstantsFor(plainDateTime) {
+ this.getPossibleInstantsForCalledWith.push(plainDateTime.toString());
+ const [instant] = super.getPossibleInstantsFor(plainDateTime);
+ if (this._shiftNanoseconds > 0) {
+ if (this._isBeforeShift(instant)) return [instant];
+ if (instant.epochNanoseconds < this._epoch2) return [];
+ return [instant.subtract(this._shift)];
+ }
+ if (instant.epochNanoseconds < this._epoch2) return [instant];
+ const shifted = instant.subtract(this._shift);
+ if (this._isBeforeShift(instant)) return [instant, shifted];
+ return [shifted];
+ }
+
+ getNextTransition(instant) {
+ return this._isBeforeShift(instant) ? this._shiftInstant : null;
+ }
+
+ getPreviousTransition(instant) {
+ return this._isBeforeShift(instant) ? null : this._shiftInstant;
+ }
+
+ toString() {
+ return "Custom/One_Shift";
+ }
+ }
+ return new OneShiftTimeZone(shiftInstant, shiftNanoseconds);
+ },
+
+ /*
+ * propertyBagObserver():
+ * Returns an object that behaves like the given propertyBag but tracks Get
+ * and Has operations on any of its properties, by appending messages to an
+ * array. If the value of a property in propertyBag is a primitive, the value
+ * of the returned object's property will additionally be a
+ * TemporalHelpers.toPrimitiveObserver that will track calls to its toString
+ * and valueOf methods in the same array. This is for the purpose of testing
+ * order of operations that are observable from user code. objectName is used
+ * in the log.
+ */
+ propertyBagObserver(calls, propertyBag, objectName) {
+ return new Proxy(propertyBag, {
+ ownKeys(target) {
+ calls.push(`ownKeys ${objectName}`);
+ return Reflect.ownKeys(target);
+ },
+ getOwnPropertyDescriptor(target, key) {
+ calls.push(`getOwnPropertyDescriptor ${formatPropertyName(key, objectName)}`);
+ return Reflect.getOwnPropertyDescriptor(target, key);
+ },
+ get(target, key, receiver) {
+ calls.push(`get ${formatPropertyName(key, objectName)}`);
+ const result = Reflect.get(target, key, receiver);
+ if (result === undefined) {
+ return undefined;
+ }
+ if ((result !== null && typeof result === "object") || typeof result === "function") {
+ return result;
+ }
+ return TemporalHelpers.toPrimitiveObserver(calls, result, `${formatPropertyName(key, objectName)}`);
+ },
+ has(target, key) {
+ calls.push(`has ${formatPropertyName(key, objectName)}`);
+ return Reflect.has(target, key);
+ },
+ });
+ },
+
+ /*
+ * specificOffsetTimeZone():
+ *
+ * This returns an instance of a custom time zone class, which returns a
+ * specific custom value from its getOffsetNanosecondsFrom() method. This is
+ * for the purpose of testing the validation of what this method returns.
+ *
+ * It also returns an empty array from getPossibleInstantsFor(), so as to
+ * trigger calls to getOffsetNanosecondsFor() when used from the
+ * BuiltinTimeZoneGetInstantFor operation.
+ */
+ specificOffsetTimeZone(offsetValue) {
+ class SpecificOffsetTimeZone extends Temporal.TimeZone {
+ constructor(offsetValue) {
+ super("UTC");
+ this._offsetValue = offsetValue;
+ }
+
+ getOffsetNanosecondsFor() {
+ return this._offsetValue;
+ }
+
+ getPossibleInstantsFor() {
+ return [];
+ }
+ }
+ return new SpecificOffsetTimeZone(offsetValue);
+ },
+
+ /*
+ * springForwardFallBackTimeZone():
+ *
+ * This returns an instance of a custom time zone class that implements one
+ * single spring-forward/fall-back transition, for the purpose of testing the
+ * disambiguation option, without depending on system time zone data.
+ *
+ * The spring-forward occurs at epoch second 954669600 (2000-04-02T02:00
+ * local) and goes from offset -08:00 to -07:00.
+ *
+ * The fall-back occurs at epoch second 972810000 (2000-10-29T02:00 local) and
+ * goes from offset -07:00 to -08:00.
+ */
+ springForwardFallBackTimeZone() {
+ const { compare } = Temporal.PlainDateTime;
+ const springForwardLocal = new Temporal.PlainDateTime(2000, 4, 2, 2);
+ const springForwardEpoch = 954669600_000_000_000n;
+ const fallBackLocal = new Temporal.PlainDateTime(2000, 10, 29, 1);
+ const fallBackEpoch = 972810000_000_000_000n;
+ const winterOffset = new Temporal.TimeZone('-08:00');
+ const summerOffset = new Temporal.TimeZone('-07:00');
+
+ class SpringForwardFallBackTimeZone extends Temporal.TimeZone {
+ constructor() {
+ super("-08:00");
+ }
+
+ getOffsetNanosecondsFor(instant) {
+ if (instant.epochNanoseconds < springForwardEpoch ||
+ instant.epochNanoseconds >= fallBackEpoch) {
+ return winterOffset.getOffsetNanosecondsFor(instant);
+ }
+ return summerOffset.getOffsetNanosecondsFor(instant);
+ }
+
+ getPossibleInstantsFor(datetime) {
+ if (compare(datetime, springForwardLocal) >= 0 && compare(datetime, springForwardLocal.add({ hours: 1 })) < 0) {
+ return [];
+ }
+ if (compare(datetime, fallBackLocal) >= 0 && compare(datetime, fallBackLocal.add({ hours: 1 })) < 0) {
+ return [summerOffset.getInstantFor(datetime), winterOffset.getInstantFor(datetime)];
+ }
+ if (compare(datetime, springForwardLocal) < 0 || compare(datetime, fallBackLocal) >= 0) {
+ return [winterOffset.getInstantFor(datetime)];
+ }
+ return [summerOffset.getInstantFor(datetime)];
+ }
+
+ getPreviousTransition(instant) {
+ if (instant.epochNanoseconds > fallBackEpoch) return new Temporal.Instant(fallBackEpoch);
+ if (instant.epochNanoseconds > springForwardEpoch) return new Temporal.Instant(springForwardEpoch);
+ return null;
+ }
+
+ getNextTransition(instant) {
+ if (instant.epochNanoseconds < springForwardEpoch) return new Temporal.Instant(springForwardEpoch);
+ if (instant.epochNanoseconds < fallBackEpoch) return new Temporal.Instant(fallBackEpoch);
+ return null;
+ }
+
+ toString() {
+ return "Custom/Spring_Fall";
+ }
+ }
+ return new SpringForwardFallBackTimeZone();
+ },
+
+ /*
+ * timeZoneObserver:
+ * A custom calendar that behaves exactly like the UTC time zone but tracks
+ * calls to any of its methods, and Get/Has operations on its properties, by
+ * appending messages to an array. This is for the purpose of testing order of
+ * operations that are observable from user code. objectName is used in the
+ * log. methodOverrides is an optional object containing properties with the
+ * same name as Temporal.TimeZone methods. If the property value is a function
+ * it will be called with the proper arguments instead of the UTC method.
+ * Otherwise, the property value will be returned directly.
+ */
+ timeZoneObserver(calls, objectName, methodOverrides = {}) {
+ const utc = new Temporal.TimeZone("UTC");
+ const trackingMethods = {};
+ // Automatically generate the methods
+ ["getOffsetNanosecondsFor", "getPossibleInstantsFor", "toString"].forEach((methodName) => {
+ trackingMethods[methodName] = function (...args) {
+ calls.push(`call ${formatPropertyName(methodName, objectName)}`);
+ if (methodName in methodOverrides) {
+ const value = methodOverrides[methodName];
+ return typeof value === "function" ? value(...args) : value;
+ }
+ return utc[methodName](...args);
+ };
+ });
+ return new Proxy(trackingMethods, {
+ get(target, key, receiver) {
+ const result = Reflect.get(target, key, receiver);
+ calls.push(`get ${formatPropertyName(key, objectName)}`);
+ return result;
+ },
+ has(target, key) {
+ calls.push(`has ${formatPropertyName(key, objectName)}`);
+ return Reflect.has(target, key);
+ },
+ });
+ },
+
+ /*
+ * Returns an object that will append logs of any Gets or Calls of its valueOf
+ * or toString properties to the array calls. Both valueOf and toString will
+ * return the actual primitiveValue. propertyName is used in the log.
+ */
+ toPrimitiveObserver(calls, primitiveValue, propertyName) {
+ return {
+ get valueOf() {
+ calls.push(`get ${propertyName}.valueOf`);
+ return function () {
+ calls.push(`call ${propertyName}.valueOf`);
+ return primitiveValue;
+ };
+ },
+ get toString() {
+ calls.push(`get ${propertyName}.toString`);
+ return function () {
+ calls.push(`call ${propertyName}.toString`);
+ if (primitiveValue === undefined) return undefined;
+ return primitiveValue.toString();
+ };
+ },
+ };
+ },
+
+ /*
+ * An object containing further methods that return arrays of ISO strings, for
+ * testing parsers.
+ */
+ ISO: {
+ /*
+ * PlainMonthDay strings that are not valid.
+ */
+ plainMonthDayStringsInvalid() {
+ return [
+ "11-18junk",
+ ];
+ },
+
+ /*
+ * PlainMonthDay strings that are valid and that should produce October 1st.
+ */
+ plainMonthDayStringsValid() {
+ return [
+ "10-01",
+ "1001",
+ "1965-10-01",
+ "1976-10-01T152330.1+00:00",
+ "19761001T15:23:30.1+00:00",
+ "1976-10-01T15:23:30.1+0000",
+ "1976-10-01T152330.1+0000",
+ "19761001T15:23:30.1+0000",
+ "19761001T152330.1+00:00",
+ "19761001T152330.1+0000",
+ "+001976-10-01T152330.1+00:00",
+ "+0019761001T15:23:30.1+00:00",
+ "+001976-10-01T15:23:30.1+0000",
+ "+001976-10-01T152330.1+0000",
+ "+0019761001T15:23:30.1+0000",
+ "+0019761001T152330.1+00:00",
+ "+0019761001T152330.1+0000",
+ "1976-10-01T15:23:00",
+ "1976-10-01T15:23",
+ "1976-10-01T15",
+ "1976-10-01",
+ "--10-01",
+ "--1001",
+ ];
+ },
+
+ /*
+ * PlainTime strings that may be mistaken for PlainMonthDay or
+ * PlainYearMonth strings, and so require a time designator.
+ */
+ plainTimeStringsAmbiguous() {
+ const ambiguousStrings = [
+ "2021-12", // ambiguity between YYYY-MM and HHMM-UU
+ "2021-12[-12:00]", // ditto, TZ does not disambiguate
+ "1214", // ambiguity between MMDD and HHMM
+ "0229", // ditto, including MMDD that doesn't occur every year
+ "1130", // ditto, including DD that doesn't occur in every month
+ "12-14", // ambiguity between MM-DD and HH-UU
+ "12-14[-14:00]", // ditto, TZ does not disambiguate
+ "202112", // ambiguity between YYYYMM and HHMMSS
+ "202112[UTC]", // ditto, TZ does not disambiguate
+ ];
+ // Adding a calendar annotation to one of these strings must not cause
+ // disambiguation in favour of time.
+ const stringsWithCalendar = ambiguousStrings.map((s) => s + '[u-ca=iso8601]');
+ return ambiguousStrings.concat(stringsWithCalendar);
+ },
+
+ /*
+ * PlainTime strings that are of similar form to PlainMonthDay and
+ * PlainYearMonth strings, but are not ambiguous due to components that
+ * aren't valid as months or days.
+ */
+ plainTimeStringsUnambiguous() {
+ return [
+ "2021-13", // 13 is not a month
+ "202113", // ditto
+ "2021-13[-13:00]", // ditto
+ "202113[-13:00]", // ditto
+ "0000-00", // 0 is not a month
+ "000000", // ditto
+ "0000-00[UTC]", // ditto
+ "000000[UTC]", // ditto
+ "1314", // 13 is not a month
+ "13-14", // ditto
+ "1232", // 32 is not a day
+ "0230", // 30 is not a day in February
+ "0631", // 31 is not a day in June
+ "0000", // 0 is neither a month nor a day
+ "00-00", // ditto
+ ];
+ },
+
+ /*
+ * PlainYearMonth-like strings that are not valid.
+ */
+ plainYearMonthStringsInvalid() {
+ return [
+ "2020-13",
+ ];
+ },
+
+ /*
+ * PlainYearMonth-like strings that are valid and should produce November
+ * 1976 in the ISO 8601 calendar.
+ */
+ plainYearMonthStringsValid() {
+ return [
+ "1976-11",
+ "1976-11-10",
+ "1976-11-01T09:00:00+00:00",
+ "1976-11-01T00:00:00+05:00",
+ "197611",
+ "+00197611",
+ "1976-11-18T15:23:30.1\u221202:00",
+ "1976-11-18T152330.1+00:00",
+ "19761118T15:23:30.1+00:00",
+ "1976-11-18T15:23:30.1+0000",
+ "1976-11-18T152330.1+0000",
+ "19761118T15:23:30.1+0000",
+ "19761118T152330.1+00:00",
+ "19761118T152330.1+0000",
+ "+001976-11-18T152330.1+00:00",
+ "+0019761118T15:23:30.1+00:00",
+ "+001976-11-18T15:23:30.1+0000",
+ "+001976-11-18T152330.1+0000",
+ "+0019761118T15:23:30.1+0000",
+ "+0019761118T152330.1+00:00",
+ "+0019761118T152330.1+0000",
+ "1976-11-18T15:23",
+ "1976-11-18T15",
+ "1976-11-18",
+ ];
+ },
+
+ /*
+ * PlainYearMonth-like strings that are valid and should produce November of
+ * the ISO year -9999.
+ */
+ plainYearMonthStringsValidNegativeYear() {
+ return [
+ "\u2212009999-11",
+ ];
+ },
+ }
+};
+
+// file: testTypedArray.js
+// Copyright (C) 2015 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Collection of functions used to assert the correctness of TypedArray objects.
+defines:
+ - typedArrayConstructors
+ - floatArrayConstructors
+ - intArrayConstructors
+ - TypedArray
+ - testWithTypedArrayConstructors
+ - testWithAtomicsFriendlyTypedArrayConstructors
+ - testWithNonAtomicsFriendlyTypedArrayConstructors
+ - testTypedArrayConversions
+---*/
+
+/**
+ * Array containing every typed array constructor.
+ */
+var typedArrayConstructors = [
+ Float64Array,
+ Float32Array,
+ Int32Array,
+ Int16Array,
+ Int8Array,
+ Uint32Array,
+ Uint16Array,
+ Uint8Array,
+ Uint8ClampedArray
+];
+
+var floatArrayConstructors = typedArrayConstructors.slice(0, 2);
+var intArrayConstructors = typedArrayConstructors.slice(2, 7);
+
+/**
+ * The %TypedArray% intrinsic constructor function.
+ */
+var TypedArray = Object.getPrototypeOf(Int8Array);
+
+/**
+ * Callback for testing a typed array constructor.
+ *
+ * @callback typedArrayConstructorCallback
+ * @param {Function} Constructor the constructor object to test with.
+ */
+
+/**
+ * Calls the provided function for every typed array constructor.
+ *
+ * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor.
+ * @param {Array} selected - An optional Array with filtered typed arrays
+ */
+function testWithTypedArrayConstructors(f, selected) {
+ var constructors = selected || typedArrayConstructors;
+ for (var i = 0; i < constructors.length; ++i) {
+ var constructor = constructors[i];
+ try {
+ f(constructor);
+ } catch (e) {
+ e.message += " (Testing with " + constructor.name + ".)";
+ throw e;
+ }
+ }
+}
+
+/**
+ * Calls the provided function for every non-"Atomics Friendly" typed array constructor.
+ *
+ * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor.
+ * @param {Array} selected - An optional Array with filtered typed arrays
+ */
+function testWithNonAtomicsFriendlyTypedArrayConstructors(f) {
+ testWithTypedArrayConstructors(f, [
+ Float64Array,
+ Float32Array,
+ Uint8ClampedArray
+ ]);
+}
+
+/**
+ * Calls the provided function for every "Atomics Friendly" typed array constructor.
+ *
+ * @param {typedArrayConstructorCallback} f - the function to call for each typed array constructor.
+ * @param {Array} selected - An optional Array with filtered typed arrays
+ */
+function testWithAtomicsFriendlyTypedArrayConstructors(f) {
+ testWithTypedArrayConstructors(f, [
+ Int32Array,
+ Int16Array,
+ Int8Array,
+ Uint32Array,
+ Uint16Array,
+ Uint8Array,
+ ]);
+}
+
+/**
+ * Helper for conversion operations on TypedArrays, the expected values
+ * properties are indexed in order to match the respective value for each
+ * TypedArray constructor
+ * @param {Function} fn - the function to call for each constructor and value.
+ * will be called with the constructor, value, expected
+ * value, and a initial value that can be used to avoid
+ * a false positive with an equivalent expected value.
+ */
+function testTypedArrayConversions(byteConversionValues, fn) {
+ var values = byteConversionValues.values;
+ var expected = byteConversionValues.expected;
+
+ testWithTypedArrayConstructors(function(TA) {
+ var name = TA.name.slice(0, -5);
+
+ return values.forEach(function(value, index) {
+ var exp = expected[name][index];
+ var initial = 0;
+ if (exp === 0) {
+ initial = 1;
+ }
+ fn(TA, value, exp, initial);
+ });
+ });
+}
+
+// file: timer.js
+// Copyright (C) 2017 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Used in website/scripts/sth.js
+defines: [setTimeout]
+---*/
+//setTimeout is not available, hence this script was loaded
+if (Promise === undefined && this.setTimeout === undefined) {
+ if(/\$DONE()/.test(code))
+ throw new Test262Error("Async test capability is not supported in your test environment");
+}
+
+if (Promise !== undefined && this.setTimeout === undefined) {
+ (function(that) {
+ that.setTimeout = function(callback, delay) {
+ var p = Promise.resolve();
+ var start = Date.now();
+ var end = start + delay;
+ function check(){
+ var timeLeft = end - Date.now();
+ if(timeLeft > 0)
+ p.then(check);
+ else
+ callback();
+ }
+ p.then(check);
+ }
+ })(this);
+}
diff --git a/js/src/tests/test262/harness/sta.js b/js/src/tests/test262/harness/sta.js
new file mode 100644
index 0000000000..2ae8f2e213
--- /dev/null
+++ b/js/src/tests/test262/harness/sta.js
@@ -0,0 +1,17 @@
+// Copyright (c) 2017 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: >
+ Including sta.js will expose three functions:
+
+ Test262Error
+ Test262Error.thrower
+ $DONOTEVALUATE
+---*/
+
+assert(typeof Test262Error === "function");
+assert(typeof Test262Error.prototype.toString === "function");
+assert(typeof Test262Error.thrower === "function");
+assert(typeof $DONOTEVALUATE === "function");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/tcoHelper.js b/js/src/tests/test262/harness/tcoHelper.js
new file mode 100644
index 0000000000..3c19379340
--- /dev/null
+++ b/js/src/tests/test262/harness/tcoHelper.js
@@ -0,0 +1,19 @@
+// Copyright (c) 2017 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: >
+ Including tcoHelper.js will expose:
+
+ var $MAX_ITERATIONS = 100000;
+
+ This defines the number of consecutive recursive function calls that must be
+ made in order to prove that stack frames are properly destroyed according to
+ ES2015 tail call optimization semantics.
+
+includes: [tcoHelper.js]
+---*/
+
+
+assert.sameValue($MAX_ITERATIONS, 100000);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/temporalHelpers-cross-date-line-time-zone.js b/js/src/tests/test262/harness/temporalHelpers-cross-date-line-time-zone.js
new file mode 100644
index 0000000000..b2c0abd294
--- /dev/null
+++ b/js/src/tests/test262/harness/temporalHelpers-cross-date-line-time-zone.js
@@ -0,0 +1,59 @@
+// |reftest| skip -- Temporal is not supported
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Verify the time zone arithmetic used in
+ TemporalHelpers.crossDateLineTimeZone() against the Pacific/Apia time zone in
+ the implementation's time zone database
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+// No need to test this on hosts that don't provide an Intl object. It's
+// sufficient that the logic is tested on at least one host.
+if (typeof globalThis.Intl !== "undefined") {
+ const tz = TemporalHelpers.crossDateLineTimeZone();
+ const realTz = new Temporal.TimeZone('Pacific/Apia');
+ const shiftInstant = Temporal.Instant.from('2011-12-30T10:00:00Z');
+
+ assert.sameValue(
+ tz.getOffsetNanosecondsFor(shiftInstant),
+ realTz.getOffsetNanosecondsFor(shiftInstant),
+ 'offset at shift instant'
+ );
+ const minus1 = shiftInstant.subtract({ hours: 1 });
+ assert.sameValue(
+ tz.getOffsetNanosecondsFor(minus1),
+ realTz.getOffsetNanosecondsFor(minus1),
+ 'offset at 1 hour before shift'
+ );
+ const plus1 = shiftInstant.add({ hours: 1 });
+ assert.sameValue(
+ tz.getOffsetNanosecondsFor(plus1),
+ realTz.getOffsetNanosecondsFor(plus1),
+ 'offset at 1 hour after shift'
+ );
+
+ const middleOfSkippedDayWallTime = Temporal.PlainDateTime.from("2011-12-30T12:00");
+ assert.compareArray(
+ tz.getPossibleInstantsFor(middleOfSkippedDayWallTime).map((i) => i.epochNanoseconds),
+ realTz.getPossibleInstantsFor(middleOfSkippedDayWallTime).map((i) => i.epochNanoseconds),
+ 'possible instants for middle of skipped day wall time'
+ );
+ const before1 = middleOfSkippedDayWallTime.subtract({ days: 1 });
+ assert.compareArray(
+ tz.getPossibleInstantsFor(before1).map((i) => i.epochNanoseconds),
+ realTz.getPossibleInstantsFor(before1).map((i) => i.epochNanoseconds),
+ 'possible instants for 1 day before skipped day'
+ );
+ const after1 = middleOfSkippedDayWallTime.add({ days: 1 });
+ assert.compareArray(
+ tz.getPossibleInstantsFor(after1).map((i) => i.epochNanoseconds),
+ realTz.getPossibleInstantsFor(after1).map((i) => i.epochNanoseconds),
+ 'possible instants for 1 day after skipped day'
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/temporalHelpers-one-shift-time-zone.js b/js/src/tests/test262/harness/temporalHelpers-one-shift-time-zone.js
new file mode 100644
index 0000000000..0452d30111
--- /dev/null
+++ b/js/src/tests/test262/harness/temporalHelpers-one-shift-time-zone.js
@@ -0,0 +1,83 @@
+// |reftest| skip -- Temporal is not supported
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Verify the time zone arithmetic used in TemporalHelpers.oneShiftTimeZone()
+ against known cases in the implementation's time zone database
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+function checkTimeZoneArithmetic(shiftInstant, shiftNs, realTimeZoneName, shiftWallTime) {
+ // No need to test this on hosts that don't provide an Intl object. It's
+ // sufficient that the logic is tested on at least one host.
+ if (typeof globalThis.Intl === "undefined")
+ return;
+
+ const tz = TemporalHelpers.oneShiftTimeZone(shiftInstant, shiftNs);
+ const realTz = new Temporal.TimeZone(realTimeZoneName);
+
+ assert.sameValue(
+ tz.getOffsetNanosecondsFor(shiftInstant),
+ realTz.getOffsetNanosecondsFor(shiftInstant),
+ 'offset at shift instant'
+ );
+ const minus1 = shiftInstant.subtract({ hours: 1 });
+ assert.sameValue(
+ tz.getOffsetNanosecondsFor(minus1),
+ realTz.getOffsetNanosecondsFor(minus1),
+ 'offset at 1 hour before shift'
+ );
+ const plus1 = shiftInstant.add({ hours: 1 });
+ assert.sameValue(
+ tz.getOffsetNanosecondsFor(plus1),
+ realTz.getOffsetNanosecondsFor(plus1),
+ 'offset at 1 hour after shift'
+ );
+
+ assert.compareArray(
+ tz.getPossibleInstantsFor(shiftWallTime).map((i) => i.epochNanoseconds),
+ realTz.getPossibleInstantsFor(shiftWallTime).map((i) => i.epochNanoseconds),
+ 'possible instants for wall time'
+ );
+ const before1 = shiftWallTime.subtract({ hours: 1 });
+ assert.compareArray(
+ tz.getPossibleInstantsFor(before1).map((i) => i.epochNanoseconds),
+ realTz.getPossibleInstantsFor(before1).map((i) => i.epochNanoseconds),
+ 'possible instants for 1 hour before wall time'
+ );
+ const after1 = shiftWallTime.add({ hours: 1 });
+ assert.compareArray(
+ tz.getPossibleInstantsFor(after1).map((i) => i.epochNanoseconds),
+ realTz.getPossibleInstantsFor(after1).map((i) => i.epochNanoseconds),
+ 'possible instants for 1 hour after wall time'
+ );
+}
+
+// Check a positive DST shift from +00:00 to +01:00
+checkTimeZoneArithmetic(
+ new Temporal.Instant(1616893200000000000n),
+ 3600e9,
+ 'Europe/London',
+ new Temporal.PlainDateTime(2021, 3, 28, 1)
+);
+
+// Check a negative DST shift from +00:00 to -01:00
+checkTimeZoneArithmetic(
+ new Temporal.Instant(1635642000000000000n),
+ -3600e9,
+ 'Atlantic/Azores',
+ new Temporal.PlainDateTime(2021, 10, 31, 1)
+);
+
+// Check the no-shift case
+checkTimeZoneArithmetic(
+ new Temporal.Instant(0n),
+ 0,
+ 'UTC',
+ new Temporal.PlainDateTime(1970, 1, 1)
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/testTypedArray-conversions-call-error.js b/js/src/tests/test262/harness/testTypedArray-conversions-call-error.js
new file mode 100644
index 0000000000..6d22f1460c
--- /dev/null
+++ b/js/src/tests/test262/harness/testTypedArray-conversions-call-error.js
@@ -0,0 +1,32 @@
+// Copyright (c) 2017 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: >
+ Including testTypedArray.js will expose:
+
+ testTypedArrayConversions()
+
+includes: [testTypedArray.js]
+features: [TypedArray]
+---*/
+var threw = false;
+
+try {
+ testTypedArrayConversions({}, () => {});
+} catch(err) {
+ threw = true;
+ if (err.constructor !== TypeError) {
+ throw new Error(
+ 'Expected a TypeError, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a TypeError, but no error was thrown.');
+}
+
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/testTypedArray-conversions.js b/js/src/tests/test262/harness/testTypedArray-conversions.js
new file mode 100644
index 0000000000..3af4b6a528
--- /dev/null
+++ b/js/src/tests/test262/harness/testTypedArray-conversions.js
@@ -0,0 +1,57 @@
+// Copyright (c) 2017 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: >
+ Including testTypedArray.js will expose:
+
+ testTypedArrayConversions()
+
+includes: [testTypedArray.js]
+features: [TypedArray]
+---*/
+var callCount = 0;
+var bcv = {
+ values: [
+ 127,
+ ],
+ expected: {
+ Int8: [
+ 127,
+ ],
+ Uint8: [
+ 127,
+ ],
+ Uint8Clamped: [
+ 127,
+ ],
+ Int16: [
+ 127,
+ ],
+ Uint16: [
+ 127,
+ ],
+ Int32: [
+ 127,
+ ],
+ Uint32: [
+ 127,
+ ],
+ Float32: [
+ 127,
+ ],
+ Float64: [
+ 127,
+ ]
+ }
+};
+
+testTypedArrayConversions(bcv, function(TA, value, expected, initial) {
+ var sample = new TA([initial]);
+ sample.fill(value);
+ assert.sameValue(initial, 0);
+ assert.sameValue(sample[0], expected);
+ callCount++;
+});
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/testTypedArray.js b/js/src/tests/test262/harness/testTypedArray.js
new file mode 100644
index 0000000000..1c7bfb7303
--- /dev/null
+++ b/js/src/tests/test262/harness/testTypedArray.js
@@ -0,0 +1,34 @@
+// Copyright (c) 2017 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: >
+ Including testTypedArray.js will expose:
+
+ var typedArrayConstructors = [ array of TypedArray constructors ]
+ var TypedArray
+
+ testWithTypedArrayConstructors()
+ testTypedArrayConversions()
+
+includes: [testTypedArray.js]
+features: [TypedArray]
+---*/
+
+assert(typeof TypedArray === "function");
+assert.sameValue(TypedArray, Object.getPrototypeOf(Uint8Array));
+
+var callCount = 0;
+testWithTypedArrayConstructors(() => callCount++);
+assert.sameValue(callCount, 9);
+
+assert.sameValue(typedArrayConstructors[0], Float64Array);
+assert.sameValue(typedArrayConstructors[1], Float32Array);
+assert.sameValue(typedArrayConstructors[2], Int32Array);
+assert.sameValue(typedArrayConstructors[3], Int16Array);
+assert.sameValue(typedArrayConstructors[4], Int8Array);
+assert.sameValue(typedArrayConstructors[5], Uint32Array);
+assert.sameValue(typedArrayConstructors[6], Uint16Array);
+assert.sameValue(typedArrayConstructors[7], Uint8Array);
+assert.sameValue(typedArrayConstructors[8], Uint8ClampedArray);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/timer.js b/js/src/tests/test262/harness/timer.js
new file mode 100644
index 0000000000..083d52ae83
--- /dev/null
+++ b/js/src/tests/test262/harness/timer.js
@@ -0,0 +1,20 @@
+// Copyright (c) 2017 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: >
+ Including timer.js will expose:
+
+ setTimeout()
+
+includes: [timer.js,fnGlobalObject.js]
+---*/
+
+var gO = fnGlobalObject();
+
+assert(typeof setTimeout === "function");
+assert(typeof gO.setTimeout === "function");
+assert.sameValue(gO.setTimeout, setTimeout);
+
+// TODO: assert semantics
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/verifyProperty-arguments.js b/js/src/tests/test262/harness/verifyProperty-arguments.js
new file mode 100644
index 0000000000..91fe42de5c
--- /dev/null
+++ b/js/src/tests/test262/harness/verifyProperty-arguments.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2017 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ verifyProperty should receive at least 3 arguments: obj, name, and descriptor
+includes: [propertyHelper.js]
+---*/
+assert.throws(Test262Error, () => {
+ verifyProperty();
+}, "0 arguments");
+
+assert.throws(Test262Error, () => {
+ verifyProperty(Object);
+}, "1 argument");
+
+assert.throws(Test262Error, () => {
+ verifyProperty(Object, 'foo');
+}, "2 arguments");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/verifyProperty-configurable-object.js b/js/src/tests/test262/harness/verifyProperty-configurable-object.js
new file mode 100644
index 0000000000..94989b6061
--- /dev/null
+++ b/js/src/tests/test262/harness/verifyProperty-configurable-object.js
@@ -0,0 +1,19 @@
+// Copyright (C) 2019 Bocoup. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Objects whose specified property is configurable satisfy the assertion.
+includes: [propertyHelper.js]
+---*/
+
+Object.defineProperty(this, 'Object', {
+ configurable: true,
+ value: Object
+});
+
+verifyProperty(this, 'Object', {
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/verifyProperty-desc-is-not-object.js b/js/src/tests/test262/harness/verifyProperty-desc-is-not-object.js
new file mode 100644
index 0000000000..faf1b69f27
--- /dev/null
+++ b/js/src/tests/test262/harness/verifyProperty-desc-is-not-object.js
@@ -0,0 +1,32 @@
+// Copyright (C) 2017 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ The desc argument should be an object or undefined
+includes: [propertyHelper.js]
+features: [Symbol]
+---*/
+var sample = { foo: 42 };
+
+assert.throws(Test262Error, () => {
+ verifyProperty(sample, "foo", 'configurable');
+}, "string");
+
+assert.throws(Test262Error, () => {
+ verifyProperty(sample, 'foo', true);
+}, "boolean");
+
+assert.throws(Test262Error, () => {
+ verifyProperty(sample, 'foo', 42);
+}, "number");
+
+assert.throws(Test262Error, () => {
+ verifyProperty(sample, 'foo', null);
+}, "null");
+
+assert.throws(Test262Error, () => {
+ verifyProperty(sample, 'foo', Symbol(1));
+}, "symbol");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/verifyProperty-noproperty.js b/js/src/tests/test262/harness/verifyProperty-noproperty.js
new file mode 100644
index 0000000000..b40d69854b
--- /dev/null
+++ b/js/src/tests/test262/harness/verifyProperty-noproperty.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2017 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ The first argument should have an own property
+includes: [propertyHelper.js]
+---*/
+assert.throws(Test262Error, () => {
+ verifyProperty(Object, 'JeanPaulSartre', {});
+}, "inexisting property");
+
+assert.throws(Test262Error, () => {
+ verifyProperty({}, 'hasOwnProperty', {});
+}, "inexisting own property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/verifyProperty-restore-accessor-symbol.js b/js/src/tests/test262/harness/verifyProperty-restore-accessor-symbol.js
new file mode 100644
index 0000000000..b500856137
--- /dev/null
+++ b/js/src/tests/test262/harness/verifyProperty-restore-accessor-symbol.js
@@ -0,0 +1,45 @@
+// Copyright (C) 2017 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ verifyProperty allows restoring the original accessor descriptor
+includes: [propertyHelper.js]
+features: [Symbol]
+---*/
+
+var obj;
+var prop = Symbol(1);
+var desc = { enumerable: true, configurable: true, get() { return 42; }, set() {} };
+
+obj = {};
+Object.defineProperty(obj, prop, desc);
+
+verifyProperty(obj, prop, desc);
+
+assert.sameValue(
+ Object.prototype.hasOwnProperty.call(obj, prop),
+ false
+);
+
+obj = {};
+Object.defineProperty(obj, prop, desc);
+
+verifyProperty(obj, prop, desc, { restore: true });
+
+assert.sameValue(
+ Object.prototype.hasOwnProperty.call(obj, prop),
+ true
+);
+assert.sameValue(obj[prop], 42);
+assert.sameValue(
+ Object.getOwnPropertyDescriptor(obj, prop).get,
+ desc.get
+);
+
+assert.sameValue(
+ Object.getOwnPropertyDescriptor(obj, prop).set,
+ desc.set
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/verifyProperty-restore-accessor.js b/js/src/tests/test262/harness/verifyProperty-restore-accessor.js
new file mode 100644
index 0000000000..056f994b69
--- /dev/null
+++ b/js/src/tests/test262/harness/verifyProperty-restore-accessor.js
@@ -0,0 +1,44 @@
+// Copyright (C) 2017 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ verifyProperty allows restoring the original accessor descriptor
+includes: [propertyHelper.js]
+---*/
+
+var obj;
+var prop = "prop";
+var desc = { enumerable: true, configurable: true, get() { return 42; }, set() {} };
+
+obj = {};
+Object.defineProperty(obj, prop, desc);
+
+verifyProperty(obj, prop, desc);
+
+assert.sameValue(
+ Object.prototype.hasOwnProperty.call(obj, prop),
+ false
+);
+
+obj = {};
+Object.defineProperty(obj, prop, desc);
+
+verifyProperty(obj, prop, desc, { restore: true });
+
+assert.sameValue(
+ Object.prototype.hasOwnProperty.call(obj, prop),
+ true
+);
+assert.sameValue(obj[prop], 42);
+assert.sameValue(
+ Object.getOwnPropertyDescriptor(obj, prop).get,
+ desc.get
+);
+
+assert.sameValue(
+ Object.getOwnPropertyDescriptor(obj, prop).set,
+ desc.set
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/verifyProperty-restore-symbol.js b/js/src/tests/test262/harness/verifyProperty-restore-symbol.js
new file mode 100644
index 0000000000..a8d0e28f03
--- /dev/null
+++ b/js/src/tests/test262/harness/verifyProperty-restore-symbol.js
@@ -0,0 +1,36 @@
+// Copyright (C) 2017 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ verifyProperty allows restoring the original descriptor
+includes: [propertyHelper.js]
+features: [Symbol]
+---*/
+
+var obj;
+var prop = Symbol(1);
+var desc = { enumerable: true, configurable: true, writable: true, value: 42 };
+
+obj = {};
+Object.defineProperty(obj, prop, desc);
+
+verifyProperty(obj, prop, desc);
+
+assert.sameValue(
+ Object.prototype.hasOwnProperty.call(obj, prop),
+ false
+);
+
+obj = {};
+Object.defineProperty(obj, prop, desc);
+
+verifyProperty(obj, prop, desc, { restore: true });
+
+assert.sameValue(
+ Object.prototype.hasOwnProperty.call(obj, prop),
+ true
+);
+assert.sameValue(obj[prop], 42);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/verifyProperty-restore.js b/js/src/tests/test262/harness/verifyProperty-restore.js
new file mode 100644
index 0000000000..9a480f7f4b
--- /dev/null
+++ b/js/src/tests/test262/harness/verifyProperty-restore.js
@@ -0,0 +1,35 @@
+// Copyright (C) 2017 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ verifyProperty allows restoring the original descriptor
+includes: [propertyHelper.js]
+---*/
+
+var obj;
+var prop = 'prop';
+var desc = { enumerable: true, configurable: true, writable: true, value: 42 };
+
+obj = {};
+Object.defineProperty(obj, prop, desc);
+
+verifyProperty(obj, prop, desc);
+
+assert.sameValue(
+ Object.prototype.hasOwnProperty.call(obj, prop),
+ false
+);
+
+obj = {};
+Object.defineProperty(obj, prop, desc);
+
+verifyProperty(obj, prop, desc, { restore: true });
+
+assert.sameValue(
+ Object.prototype.hasOwnProperty.call(obj, prop),
+ true
+);
+assert.sameValue(obj[prop], 42);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/verifyProperty-same-value.js b/js/src/tests/test262/harness/verifyProperty-same-value.js
new file mode 100644
index 0000000000..fccc90074b
--- /dev/null
+++ b/js/src/tests/test262/harness/verifyProperty-same-value.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2019 Aleksey Shvayka. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: >
+ verifyProperty uses SameValue for value comparison.
+includes: [propertyHelper.js]
+---*/
+
+var obj = {
+ a: NaN,
+ b: -0,
+};
+
+assert(verifyProperty(obj, 'a', { value: NaN }));
+assert(verifyProperty(obj, 'b', { value: -0 }));
+
+assert.throws(Test262Error, function() {
+ verifyProperty(obj, 'b', { value: 0 });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/verifyProperty-string-prop.js b/js/src/tests/test262/harness/verifyProperty-string-prop.js
new file mode 100644
index 0000000000..0823cbf7ec
--- /dev/null
+++ b/js/src/tests/test262/harness/verifyProperty-string-prop.js
@@ -0,0 +1,53 @@
+// Copyright (C) 2017 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Verify property descriptor
+includes: [propertyHelper.js]
+---*/
+
+var obj;
+var prop = 'prop';
+
+function reset(desc) {
+ obj = {};
+ Object.defineProperty(obj, prop, desc);
+}
+
+function checkDesc(desc) {
+ reset(desc);
+ assert(verifyProperty(obj, prop, desc));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { enumerable: desc.enumerable }));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { writable: desc.writable }));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { configurable: desc.configurable }));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { configurable: desc.configurable, enumerable: desc.enumerable }));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { configurable: desc.configurable, writable: desc.writable }));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { writable: desc.writable, enumerable: desc.enumerable }));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { enumerable: desc.enumerable, configurable: desc.configurable }));
+}
+
+checkDesc({ enumerable: true, configurable: true, writable: true });
+checkDesc({ enumerable: false, writable: false, configurable: false });
+checkDesc({ enumerable: true, writable: false, configurable: false });
+checkDesc({ enumerable: false, writable: true, configurable: false });
+checkDesc({ enumerable: false, writable: false, configurable: true });
+checkDesc({ enumerable: true, writable: false, configurable: true });
+checkDesc({ enumerable: true, writable: true, configurable: false });
+checkDesc({ enumerable: false, writable: true, configurable: true });
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/verifyProperty-symbol-prop.js b/js/src/tests/test262/harness/verifyProperty-symbol-prop.js
new file mode 100644
index 0000000000..69ab8e6edd
--- /dev/null
+++ b/js/src/tests/test262/harness/verifyProperty-symbol-prop.js
@@ -0,0 +1,54 @@
+// Copyright (C) 2017 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Verify symbol named property descriptor
+includes: [propertyHelper.js]
+features: [Symbol]
+---*/
+
+var obj;
+var prop = Symbol(1);
+
+function reset(desc) {
+ obj = {};
+ Object.defineProperty(obj, prop, desc);
+}
+
+function checkDesc(desc) {
+ reset(desc);
+ assert(verifyProperty(obj, prop, desc));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { enumerable: desc.enumerable }));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { writable: desc.writable }));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { configurable: desc.configurable }));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { configurable: desc.configurable, enumerable: desc.enumerable }));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { configurable: desc.configurable, writable: desc.writable }));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { writable: desc.writable, enumerable: desc.enumerable }));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { enumerable: desc.enumerable, configurable: desc.configurable }));
+}
+
+checkDesc({ enumerable: true, configurable: true, writable: true });
+checkDesc({ enumerable: false, writable: false, configurable: false });
+checkDesc({ enumerable: true, writable: false, configurable: false });
+checkDesc({ enumerable: false, writable: true, configurable: false });
+checkDesc({ enumerable: false, writable: false, configurable: true });
+checkDesc({ enumerable: true, writable: false, configurable: true });
+checkDesc({ enumerable: true, writable: true, configurable: false });
+checkDesc({ enumerable: false, writable: true, configurable: true });
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/verifyProperty-undefined-desc.js b/js/src/tests/test262/harness/verifyProperty-undefined-desc.js
new file mode 100644
index 0000000000..0e0daed8b0
--- /dev/null
+++ b/js/src/tests/test262/harness/verifyProperty-undefined-desc.js
@@ -0,0 +1,28 @@
+// Copyright (C) 2017 Leo Balter. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Verify an undefined descriptor
+includes: [propertyHelper.js]
+---*/
+var sample = {
+ bar: undefined,
+ get baz() {}
+};
+
+assert.sameValue(
+ verifyProperty(sample, "foo", undefined),
+ true,
+ "returns true if desc and property descriptor are both undefined"
+);
+
+assert.throws(Test262Error, () => {
+ verifyProperty(sample, 'bar', undefined);
+}, "dataDescriptor value is undefined");
+
+assert.throws(Test262Error, () => {
+ verifyProperty(sample, 'baz', undefined);
+}, "accessor returns undefined");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/verifyProperty-value-error.js b/js/src/tests/test262/harness/verifyProperty-value-error.js
new file mode 100644
index 0000000000..f32c137033
--- /dev/null
+++ b/js/src/tests/test262/harness/verifyProperty-value-error.js
@@ -0,0 +1,41 @@
+// Copyright (C) 2017 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Including propertyHelper.js will expose:
+
+ verifyProperty()
+ ...
+
+includes: [propertyHelper.js]
+---*/
+
+var threw = false;
+var object = Object.defineProperty({}, "prop", {
+ value: 1
+});
+
+try {
+ verifyProperty(object, "prop", {
+ value: 2
+ });
+} catch(err) {
+ threw = true;
+ if (err.constructor !== Test262Error) {
+ throw new Error(
+ 'Expected a Test262Error, but a "' + err.constructor.name +
+ '" was thrown.'
+ );
+ }
+
+ if (err.message !== 'descriptor value should be 2') {
+ throw new Error('The error thrown did not define the specified message.');
+ }
+}
+
+if (threw === false) {
+ throw new Error('Expected a Test262Error, but no error was thrown.');
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/harness/verifyProperty-value.js b/js/src/tests/test262/harness/verifyProperty-value.js
new file mode 100644
index 0000000000..0ce4e86d1e
--- /dev/null
+++ b/js/src/tests/test262/harness/verifyProperty-value.js
@@ -0,0 +1,53 @@
+// Copyright (C) 2017 Rick Waldron. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: >
+ Verify property descriptor
+includes: [propertyHelper.js]
+---*/
+
+var obj;
+var prop = 'prop';
+
+function reset(desc) {
+ desc.value = prop;
+ obj = Object.defineProperty({}, prop, desc);
+}
+
+function checkDesc(desc) {
+ reset(desc);
+ assert(verifyProperty(obj, prop, desc));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { value: 'prop', enumerable: desc.enumerable }));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { value: 'prop', writable: desc.writable }));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { value: 'prop', configurable: desc.configurable }));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { value: 'prop', configurable: desc.configurable, enumerable: desc.enumerable }));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { value: 'prop', configurable: desc.configurable, writable: desc.writable }));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { value: 'prop', writable: desc.writable, enumerable: desc.enumerable }));
+
+ reset(desc);
+ assert(verifyProperty(obj, prop, { value: 'prop', enumerable: desc.enumerable, configurable: desc.configurable }));
+}
+
+checkDesc({ enumerable: true, configurable: true, writable: true });
+checkDesc({ enumerable: false, writable: false, configurable: false });
+checkDesc({ enumerable: true, writable: false, configurable: false });
+checkDesc({ enumerable: false, writable: true, configurable: false });
+checkDesc({ enumerable: false, writable: false, configurable: true });
+checkDesc({ enumerable: true, writable: false, configurable: true });
+checkDesc({ enumerable: true, writable: true, configurable: false });
+checkDesc({ enumerable: false, writable: true, configurable: true });
+
+reportCompare(0, 0);