summaryrefslogtreecommitdiffstats
path: root/js/src/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:34:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:34:50 +0000
commitdef92d1b8e9d373e2f6f27c366d578d97d8960c6 (patch)
tree2ef34b9ad8bb9a9220e05d60352558b15f513894 /js/src/tests
parentAdding debian version 125.0.3-1. (diff)
downloadfirefox-def92d1b8e9d373e2f6f27c366d578d97d8960c6.tar.xz
firefox-def92d1b8e9d373e2f6f27c366d578d97d8960c6.zip
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/tests')
-rw-r--r--js/src/tests/jstests.list10
-rwxr-xr-xjs/src/tests/lib/jittests.py7
-rw-r--r--js/src/tests/non262/Date/parse-day-of-week.js2
-rw-r--r--js/src/tests/non262/Iterator/proto.js9
-rw-r--r--js/src/tests/non262/JSON/parse-with-source.js112
-rw-r--r--js/src/tests/non262/PrivateName/nested-class-in-computed-property-key.js17
-rw-r--r--js/src/tests/non262/module/bug1689499.js2
-rwxr-xr-xjs/src/tests/test262-update.py5
-rw-r--r--js/src/tests/test262/prs/3994/browser.js0
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/browser.js0
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/alphabet.js25
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/browser.js0
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/descriptor.js18
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/ignores-receiver.js22
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/illegal-characters.js26
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/last-chunk-handling.js67
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/length.js19
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/name.js19
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/nonconstructor.js18
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/option-coercion.js62
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/results.js30
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/shell.js24
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/string-coercion.js44
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/whitespace.js25
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/browser.js0
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/descriptor.js18
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/ignores-receiver.js22
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/illegal-characters.js28
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/length.js19
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/name.js19
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/nonconstructor.js18
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/odd-length-input.js14
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/results.js31
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/shell.js24
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/string-coercion.js23
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/browser.js0
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/alphabet.js44
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/browser.js0
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/descriptor.js18
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/detached-buffer.js32
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/illegal-characters.js27
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/last-chunk-handling.js156
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/length.js19
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/name.js19
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/nonconstructor.js19
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/option-coercion.js72
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/results.js33
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/shell.js42
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/string-coercion.js46
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/subarray.js20
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/target-size.js67
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/whitespace.js26
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/browser.js0
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/descriptor.js18
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/detached-buffer.js17
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/illegal-characters.js29
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/length.js19
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/name.js19
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/nonconstructor.js19
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/results.js34
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/shell.js42
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/string-coercion.js24
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/subarray.js20
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/target-size.js32
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/shell.js0
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/alphabet.js20
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/browser.js0
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/descriptor.js18
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/detached-buffer.js42
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/length.js19
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/name.js19
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/nonconstructor.js19
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/option-coercion.js51
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/receiver-not-uint8array.js36
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/results.js19
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/shell.js203
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/browser.js0
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/descriptor.js18
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/detached-buffer.js18
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/length.js19
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/name.js19
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/nonconstructor.js19
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/receiver-not-uint8array.js29
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/results.js18
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/shell.js203
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/Uint8Array/shell.js0
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/browser.js0
-rw-r--r--js/src/tests/test262/prs/3994/built-ins/shell.js0
-rw-r--r--js/src/tests/test262/prs/3994/shell.js723
-rw-r--r--js/src/tests/test262/staging/JSON/json-parse-with-source-snapshot.js2
-rw-r--r--js/src/tests/test262/staging/JSON/json-parse-with-source.js2
91 files changed, 3156 insertions, 52 deletions
diff --git a/js/src/tests/jstests.list b/js/src/tests/jstests.list
index 55ffc65f6f..dbe3bd555e 100644
--- a/js/src/tests/jstests.list
+++ b/js/src/tests/jstests.list
@@ -1368,16 +1368,6 @@ skip script test262/built-ins/Temporal/ZonedDateTime/prototype/since/normalized-
skip script test262/built-ins/Temporal/ZonedDateTime/prototype/hoursInDay/precision-exact-mathematical-values-2.js
##############################################
-# Iterator helper tests #
-##############################################
-
-# Failures with --enable-iterator-helpers, see bug 1877831.
-shell-option(--enable-iterator-helpers) skip script test262/built-ins/Iterator/prototype/constructor/prop-desc.js
-shell-option(--enable-iterator-helpers) skip script test262/built-ins/Iterator/prototype/constructor/weird-setter.js
-shell-option(--enable-iterator-helpers) skip script test262/built-ins/Iterator/prototype/Symbol.toStringTag/prop-desc.js
-shell-option(--enable-iterator-helpers) skip script test262/built-ins/Iterator/prototype/Symbol.toStringTag/weird-setter.js
-
-##############################################
# AsyncFromSyncIteratorPrototype tests #
##############################################
diff --git a/js/src/tests/lib/jittests.py b/js/src/tests/lib/jittests.py
index 4e7be87255..7d79ba9f2a 100755
--- a/js/src/tests/lib/jittests.py
+++ b/js/src/tests/lib/jittests.py
@@ -343,6 +343,13 @@ class JitTest:
elif name.startswith("--"):
# // |jit-test| --ion-gvn=off; --no-sse4
test.jitflags.append(name)
+ elif name.startswith("-P"):
+ prefAndValue = name.split()
+ assert (
+ len(prefAndValue) == 2
+ ), f"{name}: failed to parse preference"
+ # // |jit-test| -P pref(=value)?
+ test.jitflags.append("--setpref=" + prefAndValue[1])
else:
print(
"{}: warning: unrecognized |jit-test| attribute"
diff --git a/js/src/tests/non262/Date/parse-day-of-week.js b/js/src/tests/non262/Date/parse-day-of-week.js
index 08bcd3ee05..52a8c6339a 100644
--- a/js/src/tests/non262/Date/parse-day-of-week.js
+++ b/js/src/tests/non262/Date/parse-day-of-week.js
@@ -63,6 +63,8 @@ const rejected = [
"Sep 26 1995 foo",
"1995 foo Sep 26",
"foo2 Sep 26 1995",
+ "Tuesday_Sep 26 1995",
+ "foo_12",
];
for (const format of formats) {
diff --git a/js/src/tests/non262/Iterator/proto.js b/js/src/tests/non262/Iterator/proto.js
index 642e48d171..5b32f5d34b 100644
--- a/js/src/tests/non262/Iterator/proto.js
+++ b/js/src/tests/non262/Iterator/proto.js
@@ -10,14 +10,5 @@ assertEq(propDesc.writable, false);
assertEq(propDesc.enumerable, false);
assertEq(propDesc.configurable, false);
-// Make sure @@toStringTag has been set.
-const toStringTagDesc = Reflect.getOwnPropertyDescriptor(Iterator.prototype, Symbol.toStringTag);
-assertDeepEq(toStringTagDesc, {
- value: "Iterator",
- writable: true,
- enumerable: false,
- configurable: true,
-});
-
if (typeof reportCompare === 'function')
reportCompare(0, 0);
diff --git a/js/src/tests/non262/JSON/parse-with-source.js b/js/src/tests/non262/JSON/parse-with-source.js
index 96e9550706..5e144bd6a4 100644
--- a/js/src/tests/non262/JSON/parse-with-source.js
+++ b/js/src/tests/non262/JSON/parse-with-source.js
@@ -1,49 +1,103 @@
-// |reftest| skip-if(!(this.hasOwnProperty('getBuildConfiguration')&&getBuildConfiguration('json-parse-with-source'))) shell-option(--enable-json-parse-with-source)
+// |reftest| shell-option(--enable-json-parse-with-source) skip-if(!JSON.hasOwnProperty('isRawJSON')||!xulRuntime.shell)
var actual;
function reviver(key, value, context) {
assertEq(arguments.length, 3);
- assertEq("source" in context, true);
- actual = context["source"];
+ if ("source" in context) {
+ actual.push(context["source"]);
+ } else { // objects and arrays have no "source"
+ actual.push(null);
+ }
}
let tests = [
// STRINGS
- {input: '""', expected: '""'},
- {input: '"str"', expected: '"str"'},
- {input: '"str" ', expected: '"str"'},
- {input: ' "str" ', expected: '"str"'},
- {input: ' " str"', expected: '" str"'},
- {input: '"\uD83D\uDE0A\u2764\u2FC1"', expected: '"\uD83D\uDE0A\u2764\u2FC1"'},
+ {input: '""', expected: ['""']},
+ {input: '"str"', expected: ['"str"']},
+ {input: '"str" ', expected: ['"str"']},
+ {input: ' "str" ', expected: ['"str"']},
+ {input: ' " str"', expected: ['" str"']},
+ {input: '"\uD83D\uDE0A\u2764\u2FC1"', expected: ['"\uD83D\uDE0A\u2764\u2FC1"']},
// NUMBERS
- {input: '1', expected: '1'},
- {input: ' 1', expected: '1'},
- {input: '4.2', expected: '4.2'},
- {input: '4.2 ', expected: '4.2'},
- {input: '4.2000 ', expected: '4.2000'},
- {input: '4e2000 ', expected: '4e2000'},
- {input: '4.4e2000 ', expected: '4.4e2000'},
- {input: '9007199254740999', expected: '9007199254740999'},
- {input: '-31', expected: '-31'},
- {input: '-3.1', expected: '-3.1'},
- {input: ' -31 ', expected: '-31'},
+ {input: '1', expected: ['1']},
+ {input: ' 1', expected: ['1']},
+ {input: '4.2', expected: ['4.2']},
+ {input: '4.2 ', expected: ['4.2']},
+ {input: '4.2000 ', expected: ['4.2000']},
+ {input: '4e2000 ', expected: ['4e2000']},
+ {input: '4.4e2000 ', expected: ['4.4e2000']},
+ {input: '9007199254740999', expected: ['9007199254740999']},
+ {input: '-31', expected: ['-31']},
+ {input: '-3.1', expected: ['-3.1']},
+ {input: ' -31 ', expected: ['-31']},
// BOOLEANS
- {input: 'true', expected: 'true'},
- {input: 'true ', expected: 'true'},
- {input: 'false', expected: 'false'},
- {input: ' false', expected: 'false'},
+ {input: 'true', expected: ['true']},
+ {input: 'true ', expected: ['true']},
+ {input: 'false', expected: ['false']},
+ {input: ' false', expected: ['false']},
// NULL
- {input: 'null', expected: 'null'},
- {input: ' null', expected: 'null'},
- {input: '\tnull ', expected: 'null'},
- {input: 'null\t', expected: 'null'},
+ {input: 'null', expected: ['null']},
+ {input: ' null', expected: ['null']},
+ {input: '\tnull ', expected: ['null']},
+ {input: 'null\t', expected: ['null']},
+ // OBJECTS
+ {input: '{ }', expected: [null]},
+ {input: '{ "4": 1 }', expected: ['1', null]},
+ {input: '{ "a": 1 }', expected: ['1', null]},
+ {input: '{ "b": 2, "a": 1 }', expected: ['2', '1', null]},
+ {input: '{ "b": 2, "1": 1 }', expected: ['1', '2', null]},
+ {input: '{ "b": 2, "c": null }', expected: ['2', 'null', null]},
+ {input: '{ "b": 2, "b": 1, "b": 4 }', expected: ['4', null]},
+ {input: '{ "b": 2, "a": "1" }', expected: ['2', '"1"', null]},
+ {input: '{ "b": { "c": 3 }, "a": 1 }', expected: ['3', null, '1', null]},
+ // ARRAYS
+ {input: '[]', expected: [null]},
+ {input: '[1, 5, 2]', expected: ['1', '5', '2', null]},
+ {input: '[1, null, 2]', expected: ['1', 'null', '2', null]},
+ {input: '[1, {"a":2}, "7"]', expected: ['1', '2', null, '"7"', null]},
+ {input: '[1, [2, [3, [4, 5], [6, 7], 8], 9], 10]', expected: ['1', '2', '3', '4', '5', null, '6', '7', null, '8', null, '9', null, '10', null]},
+ {input: '[1, [2, [3, [4, 5, 6, 7, 8, 9, 10], []]]]', expected: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', null, null, null, null, null]},
+ {input: '{"a": [1, {"b":2}, "7"], "c": 8}', expected: ['1', '2', null, '"7"', null, '8', null]},
];
for (const test of tests) {
print("Testing " + JSON.stringify(test));
+ actual = [];
JSON.parse(test.input, reviver);
- assertEq(actual, test.expected);
+ assertDeepEq(actual, test.expected);
}
+// If the constructed object is modified but the result of the modification is
+// the same as the original, we should still provide the source
+function replace_c_with_same_val(key, value, context) {
+ if (key === "a") {
+ this["c"] = "ABCDEABCDE";
+ }
+ if (key) {
+ assertEq("source" in context, true);
+ }
+ return value;
+}
+JSON.parse('{ "a": "b", "c": "ABCDEABCDE" }', replace_c_with_same_val);
+
+// rawJSON
+function assertIsRawJson(rawJson, expectedRawJsonValue) {
+ assertEq(null, Object.getPrototypeOf(rawJson));
+ assertEq(true, Object.hasOwn(rawJson, 'rawJSON'));
+ assertDeepEq(['rawJSON'], Object.getOwnPropertyNames(rawJson));
+ assertDeepEq([], Object.getOwnPropertySymbols(rawJson));
+ assertEq(expectedRawJsonValue, rawJson.rawJSON);
+}
+
+assertEq(true, Object.isFrozen(JSON.rawJSON('"shouldBeFrozen"')));
+assertThrowsInstanceOf(() => JSON.rawJSON(), SyntaxError);
+assertIsRawJson(JSON.rawJSON(1, 2), '1');
+
+// isRawJSON
+assertEq(false, JSON.isRawJSON());
+assertEq(false, JSON.isRawJSON({}, {}));
+assertEq(false, JSON.isRawJSON({}, JSON.rawJSON(2)));
+assertEq(true, JSON.isRawJSON(JSON.rawJSON(1), JSON.rawJSON(2)));
+
if (typeof reportCompare == 'function')
reportCompare(0, 0); \ No newline at end of file
diff --git a/js/src/tests/non262/PrivateName/nested-class-in-computed-property-key.js b/js/src/tests/non262/PrivateName/nested-class-in-computed-property-key.js
new file mode 100644
index 0000000000..7596dfe542
--- /dev/null
+++ b/js/src/tests/non262/PrivateName/nested-class-in-computed-property-key.js
@@ -0,0 +1,17 @@
+let capturedPrivateAccess;
+class A {
+ // Declare private name in outer class.
+ static #x = 42;
+
+ static [(
+ // Inner class in computed property key.
+ class {},
+
+ // Access to private name from outer class.
+ capturedPrivateAccess = () => A.#x
+ )];
+}
+assertEq(capturedPrivateAccess(), 42);
+
+if (typeof reportCompare === 'function')
+ reportCompare(0, 0);
diff --git a/js/src/tests/non262/module/bug1689499.js b/js/src/tests/non262/module/bug1689499.js
index 859cd6f64f..2547c88d16 100644
--- a/js/src/tests/non262/module/bug1689499.js
+++ b/js/src/tests/non262/module/bug1689499.js
@@ -1,4 +1,4 @@
-// |reftest| skip-if(!xulRuntime.shell) module async -- needs drainJobQueue
+// |reftest| skip-if(!xulRuntime.shell) async -- needs drainJobQueue
async function test() {
try {
diff --git a/js/src/tests/test262-update.py b/js/src/tests/test262-update.py
index fc6fa62c45..d45d639ebb 100755
--- a/js/src/tests/test262-update.py
+++ b/js/src/tests/test262-update.py
@@ -24,7 +24,6 @@ UNSUPPORTED_FEATURES = set(
"Atomics.waitAsync", # Bug 1467846
"legacy-regexp", # Bug 1306461
"regexp-duplicate-named-groups", # Bug 1773135
- "json-parse-with-source", # Bug 1658310
"set-methods", # Bug 1805038
]
)
@@ -38,6 +37,8 @@ FEATURE_CHECK_NEEDED = {
"iterator-helpers": "!this.hasOwnProperty('Iterator')", # Bug 1568906
"Intl.Segmenter": "!Intl.Segmenter", # Bug 1423593
"resizable-arraybuffer": "!ArrayBuffer.prototype.resize", # Bug 1670026
+ "uint8array-base64": "!Uint8Array.fromBase64", # Bug 1862220
+ "json-parse-with-source": "!JSON.hasOwnProperty('isRawJSON')", # Bug 1658310
}
RELEASE_OR_BETA = set(
[
@@ -51,6 +52,8 @@ SHELL_OPTIONS = {
"iterator-helpers": "--enable-iterator-helpers",
"symbols-as-weakmap-keys": "--enable-symbols-as-weakmap-keys",
"resizable-arraybuffer": "--enable-arraybuffer-resizable",
+ "uint8array-base64": "--enable-uint8array-base64",
+ "json-parse-with-source": "--enable-json-parse-with-source",
}
diff --git a/js/src/tests/test262/prs/3994/browser.js b/js/src/tests/test262/prs/3994/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/browser.js
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/browser.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/browser.js
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/alphabet.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/alphabet.js
new file mode 100644
index 0000000000..c893bf952a
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/alphabet.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.frombase64
+description: Conversion of base64 strings to Uint8Arrays exercising the alphabet option
+includes: [compareArray.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+assert.compareArray(Uint8Array.fromBase64('x+/y'), [199, 239, 242]);
+assert.compareArray(Uint8Array.fromBase64('x+/y', { alphabet: 'base64' }), [199, 239, 242]);
+assert.throws(SyntaxError, function() {
+ Uint8Array.fromBase64('x+/y', { alphabet: 'base64url' });
+});
+
+assert.compareArray(Uint8Array.fromBase64('x-_y', { alphabet: 'base64url' }), [199, 239, 242]);
+assert.throws(SyntaxError, function() {
+ Uint8Array.fromBase64('x-_y');
+});
+assert.throws(SyntaxError, function() {
+ Uint8Array.fromBase64('x-_y', { alphabet: 'base64' });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/browser.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/browser.js
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/descriptor.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/descriptor.js
new file mode 100644
index 0000000000..a0e843cfaf
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/descriptor.js
@@ -0,0 +1,18 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.frombase64
+description: >
+ Uint8Array.fromBase64 has default data property attributes.
+includes: [propertyHelper.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+verifyProperty(Uint8Array, 'fromBase64', {
+ enumerable: false,
+ writable: true,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/ignores-receiver.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/ignores-receiver.js
new file mode 100644
index 0000000000..0847653d63
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/ignores-receiver.js
@@ -0,0 +1,22 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.frombase64
+description: Uint8Array.fromBase64 ignores its receiver
+features: [uint8array-base64, TypedArray]
+---*/
+
+var fromBase64 = Uint8Array.fromBase64;
+var noReceiver = fromBase64("Zg==");
+assert.sameValue(Object.getPrototypeOf(noReceiver), Uint8Array.prototype);
+
+class Subclass extends Uint8Array {
+ constructor() {
+ throw new Test262Error("subclass constructor called");
+ }
+}
+var fromSubclass = Subclass.fromBase64("Zg==");
+assert.sameValue(Object.getPrototypeOf(fromSubclass), Uint8Array.prototype);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/illegal-characters.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/illegal-characters.js
new file mode 100644
index 0000000000..6c2d6eef4a
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/illegal-characters.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.frombase64
+description: Uint8Array.fromBase64 throws a SyntaxError when input has non-base64, non-ascii-whitespace characters
+features: [uint8array-base64, TypedArray]
+---*/
+
+var illegal = [
+ 'Zm.9v',
+ 'Zm9v^',
+ 'Zg==&',
+ 'Z−==', // U+2212 'Minus Sign'
+ 'Z+==', // U+FF0B 'Fullwidth Plus Sign'
+ 'Zg\u00A0==', // nbsp
+ 'Zg\u2009==', // thin space
+ 'Zg\u2028==', // line separator
+];
+illegal.forEach(function(value) {
+ assert.throws(SyntaxError, function() {
+ Uint8Array.fromBase64(value)
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/last-chunk-handling.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/last-chunk-handling.js
new file mode 100644
index 0000000000..c78d15e869
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/last-chunk-handling.js
@@ -0,0 +1,67 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.frombase64
+description: Handling of final chunks in Uint8Array.fromBase64
+includes: [compareArray.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+// padding
+assert.compareArray(Uint8Array.fromBase64('ZXhhZg=='), [101, 120, 97, 102]);
+assert.compareArray(Uint8Array.fromBase64('ZXhhZg==', { lastChunkHandling: 'loose' }), [101, 120, 97, 102]);
+assert.compareArray(Uint8Array.fromBase64('ZXhhZg==', { lastChunkHandling: 'stop-before-partial' }), [101, 120, 97, 102]);
+assert.compareArray(Uint8Array.fromBase64('ZXhhZg==', { lastChunkHandling: 'strict' }), [101, 120, 97, 102]);
+
+// no padding
+assert.compareArray(Uint8Array.fromBase64('ZXhhZg'), [101, 120, 97, 102]);
+assert.compareArray(Uint8Array.fromBase64('ZXhhZg', { lastChunkHandling: 'loose' }), [101, 120, 97, 102]);
+assert.compareArray(Uint8Array.fromBase64('ZXhhZg', { lastChunkHandling: 'stop-before-partial' }), [101, 120, 97]);
+assert.throws(SyntaxError, function() {
+ Uint8Array.fromBase64('ZXhhZg', { lastChunkHandling: 'strict' });
+});
+
+// non-zero padding bits
+assert.compareArray(Uint8Array.fromBase64('ZXhhZh=='), [101, 120, 97, 102]);
+assert.compareArray(Uint8Array.fromBase64('ZXhhZh==', { lastChunkHandling: 'loose' }), [101, 120, 97, 102]);
+assert.compareArray(Uint8Array.fromBase64('ZXhhZh==', { lastChunkHandling: 'stop-before-partial' }), [101, 120, 97, 102]);
+assert.throws(SyntaxError, function() {
+ Uint8Array.fromBase64('ZXhhZh==', { lastChunkHandling: 'strict' });
+});
+
+// non-zero padding bits, no padding
+assert.compareArray(Uint8Array.fromBase64('ZXhhZh'), [101, 120, 97, 102]);
+assert.compareArray(Uint8Array.fromBase64('ZXhhZh', { lastChunkHandling: 'loose' }), [101, 120, 97, 102]);
+assert.compareArray(Uint8Array.fromBase64('ZXhhZh', { lastChunkHandling: 'stop-before-partial' }), [101, 120, 97]);
+assert.throws(SyntaxError, function() {
+ Uint8Array.fromBase64('ZXhhZh', { lastChunkHandling: 'strict' });
+});
+
+// partial padding
+assert.throws(SyntaxError, function() {
+ Uint8Array.fromBase64('ZXhhZg=');
+});
+assert.throws(SyntaxError, function() {
+ Uint8Array.fromBase64('ZXhhZg=', { lastChunkHandling: 'loose' });
+});
+assert.compareArray(Uint8Array.fromBase64('ZXhhZg=', { lastChunkHandling: 'stop-before-partial' }), [101, 120, 97]);
+assert.throws(SyntaxError, function() {
+ Uint8Array.fromBase64('ZXhhZg=', { lastChunkHandling: 'strict' });
+});
+
+// excess padding
+assert.throws(SyntaxError, function() {
+ Uint8Array.fromBase64('ZXhhZg===');
+});
+assert.throws(SyntaxError, function() {
+ Uint8Array.fromBase64('ZXhhZg===', { lastChunkHandling: 'loose' });
+});
+assert.throws(SyntaxError, function() {
+ Uint8Array.fromBase64('ZXhhZg===', { lastChunkHandling: 'stop-before-partial' });
+});
+assert.throws(SyntaxError, function() {
+ Uint8Array.fromBase64('ZXhhZg===', { lastChunkHandling: 'strict' });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/length.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/length.js
new file mode 100644
index 0000000000..dab9b49f61
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/length.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.frombase64
+description: >
+ Uint8Array.fromBase64.length is 1.
+includes: [propertyHelper.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+verifyProperty(Uint8Array.fromBase64, 'length', {
+ value: 1,
+ enumerable: false,
+ writable: false,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/name.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/name.js
new file mode 100644
index 0000000000..2bd6716863
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/name.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.frombase64
+description: >
+ Uint8Array.fromBase64.name is "fromBase64".
+includes: [propertyHelper.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+verifyProperty(Uint8Array.fromBase64, 'name', {
+ value: 'fromBase64',
+ enumerable: false,
+ writable: false,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/nonconstructor.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/nonconstructor.js
new file mode 100644
index 0000000000..7546b12b6b
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/nonconstructor.js
@@ -0,0 +1,18 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.frombase64
+description: >
+ Uint8Array.fromBase64 is not a constructor function.
+includes: [isConstructor.js]
+features: [uint8array-base64, TypedArray, Reflect.construct]
+---*/
+
+assert(!isConstructor(Uint8Array.fromBase64), "Uint8Array.fromBase64 is not a constructor");
+
+assert.throws(TypeError, function() {
+ new Uint8Array.fromBase64('');
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/option-coercion.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/option-coercion.js
new file mode 100644
index 0000000000..e314a8f16f
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/option-coercion.js
@@ -0,0 +1,62 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.frombase64
+description: Uint8Array.fromBase64 triggers effects of the "alphabet" and "lastChunkHandling" getters, but does not perform toString on the results
+includes: [compareArray.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+assert.throws(TypeError, function() {
+ Uint8Array.fromBase64("Zg==", { alphabet: Object("base64") });
+});
+
+assert.throws(TypeError, function() {
+ Uint8Array.fromBase64("Zg==", { lastChunkHandling: Object("loose") });
+});
+
+
+var toStringCalls = 0;
+var throwyToString = {
+ toString: function() {
+ toStringCalls += 1;
+ throw new Test262Error("toString called");
+ }
+};
+assert.throws(TypeError, function() {
+ Uint8Array.fromBase64("Zg==", { alphabet: throwyToString });
+});
+assert.sameValue(toStringCalls, 0);
+
+assert.throws(TypeError, function() {
+ Uint8Array.fromBase64("Zg==", { lastChunkHandling: throwyToString });
+});
+assert.sameValue(toStringCalls, 0);
+
+
+var alphabetAccesses = 0;
+var base64UrlOptions = {};
+Object.defineProperty(base64UrlOptions, "alphabet", {
+ get: function() {
+ alphabetAccesses += 1;
+ return "base64url";
+ }
+});
+var arr = Uint8Array.fromBase64("x-_y", base64UrlOptions);
+assert.compareArray(arr, [199, 239, 242]);
+assert.sameValue(alphabetAccesses, 1);
+
+var lastChunkHandlingAccesses = 0;
+var strictOptions = {};
+Object.defineProperty(strictOptions, "lastChunkHandling", {
+ get: function() {
+ lastChunkHandlingAccesses += 1;
+ return "strict";
+ }
+});
+var arr = Uint8Array.fromBase64("Zg==", strictOptions);
+assert.compareArray(arr, [102]);
+assert.sameValue(lastChunkHandlingAccesses, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/results.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/results.js
new file mode 100644
index 0000000000..9d19507f9a
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/results.js
@@ -0,0 +1,30 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.frombase64
+description: Conversion of base64 strings to Uint8Arrays
+includes: [compareArray.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+// standard test vectors from https://datatracker.ietf.org/doc/html/rfc4648#section-10
+var standardBase64Vectors = [
+ ["", []],
+ ["Zg==", [102]],
+ ["Zm8=", [102, 111]],
+ ["Zm9v", [102, 111, 111]],
+ ["Zm9vYg==", [102, 111, 111, 98]],
+ ["Zm9vYmE=", [102, 111, 111, 98, 97]],
+ ["Zm9vYmFy", [102, 111, 111, 98, 97, 114]],
+];
+
+standardBase64Vectors.forEach(function (pair) {
+ var arr = Uint8Array.fromBase64(pair[0]);
+ assert.sameValue(Object.getPrototypeOf(arr), Uint8Array.prototype, "decoding " + pair[0]);
+ assert.sameValue(arr.length, pair[1].length, "decoding " + pair[0]);
+ assert.sameValue(arr.buffer.byteLength, pair[1].length, "decoding " + pair[0]);
+ assert.compareArray(arr, pair[1], "decoding " + pair[0]);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/shell.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/shell.js
@@ -0,0 +1,24 @@
+// GENERATED, DO NOT EDIT
+// 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;
+}
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/string-coercion.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/string-coercion.js
new file mode 100644
index 0000000000..57292f8a98
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/string-coercion.js
@@ -0,0 +1,44 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.frombase64
+description: Uint8Array.fromBase64 throws if its argument is not a string
+features: [uint8array-base64, TypedArray]
+---*/
+
+var toStringCalls = 0;
+var throwyToString = {
+ toString: function() {
+ toStringCalls += 1;
+ throw new Test262Error("toString called");
+ }
+};
+
+assert.throws(TypeError, function() {
+ Uint8Array.fromBase64(throwyToString);
+});
+assert.sameValue(toStringCalls, 0);
+
+
+var optionAccesses = 0;
+var touchyOptions = {};
+Object.defineProperty(touchyOptions, "alphabet", {
+ get: function() {
+ optionAccesses += 1;
+ throw new Test262Error("alphabet accessed");
+ }
+});
+Object.defineProperty(touchyOptions, "lastChunkHandling", {
+ get: function() {
+ optionAccesses += 1;
+ throw new Test262Error("lastChunkHandling accessed");
+ }
+});
+assert.throws(TypeError, function() {
+ Uint8Array.fromBase64(throwyToString, touchyOptions);
+});
+assert.sameValue(toStringCalls, 0);
+assert.sameValue(optionAccesses, 0);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/whitespace.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/whitespace.js
new file mode 100644
index 0000000000..87c79a6563
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromBase64/whitespace.js
@@ -0,0 +1,25 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.frombase64
+description: Uint8Array.fromBase64 ignores ASCII whitespace in the input
+includes: [compareArray.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+var whitespaceKinds = [
+ ["Z g==", "space"],
+ ["Z\tg==", "tab"],
+ ["Z\x0Ag==", "LF"],
+ ["Z\x0Cg==", "FF"],
+ ["Z\x0Dg==", "CR"],
+];
+whitespaceKinds.forEach(function(pair) {
+ var arr = Uint8Array.fromBase64(pair[0]);
+ assert.sameValue(arr.length, 1);
+ assert.sameValue(arr.buffer.byteLength, 1);
+ assert.compareArray(arr, [102], "ascii whitespace: " + pair[1]);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/browser.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/browser.js
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/descriptor.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/descriptor.js
new file mode 100644
index 0000000000..3d53652054
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/descriptor.js
@@ -0,0 +1,18 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.fromhex
+description: >
+ Uint8Array.fromHex has default data property attributes.
+includes: [propertyHelper.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+verifyProperty(Uint8Array, 'fromHex', {
+ enumerable: false,
+ writable: true,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/ignores-receiver.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/ignores-receiver.js
new file mode 100644
index 0000000000..421a0278d7
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/ignores-receiver.js
@@ -0,0 +1,22 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.fromhex
+description: Uint8Array.fromHex ignores its receiver
+features: [uint8array-base64, TypedArray]
+---*/
+
+var fromHex = Uint8Array.fromHex;
+var noReceiver = fromHex("aa");
+assert.sameValue(Object.getPrototypeOf(noReceiver), Uint8Array.prototype);
+
+class Subclass extends Uint8Array {
+ constructor() {
+ throw new Test262Error("subclass constructor called");
+ }
+}
+var fromSubclass = Subclass.fromHex("aa");
+assert.sameValue(Object.getPrototypeOf(fromSubclass), Uint8Array.prototype);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/illegal-characters.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/illegal-characters.js
new file mode 100644
index 0000000000..718801e4c7
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/illegal-characters.js
@@ -0,0 +1,28 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.fromhex
+description: Uint8Array.fromHex throws a SyntaxError when input has non-hex characters
+features: [uint8array-base64, TypedArray]
+---*/
+
+var illegal = [
+ 'a.a',
+ 'aa^',
+ 'a a',
+ 'a\ta',
+ 'a\x0Aa',
+ 'a\x0Ca',
+ 'a\x0Da',
+ 'a\u00A0a', // nbsp
+ 'a\u2009a', // thin space
+ 'a\u2028a', // line separator
+];
+illegal.forEach(function(value) {
+ assert.throws(SyntaxError, function() {
+ Uint8Array.fromHex(value)
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/length.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/length.js
new file mode 100644
index 0000000000..9108a1c2c1
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/length.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.fromhex
+description: >
+ Uint8Array.fromHex.length is 1.
+includes: [propertyHelper.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+verifyProperty(Uint8Array.fromHex, 'length', {
+ value: 1,
+ enumerable: false,
+ writable: false,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/name.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/name.js
new file mode 100644
index 0000000000..7d4e145349
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/name.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.fromhex
+description: >
+ Uint8Array.fromHex.name is "fromHex".
+includes: [propertyHelper.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+verifyProperty(Uint8Array.fromHex, 'name', {
+ value: 'fromHex',
+ enumerable: false,
+ writable: false,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/nonconstructor.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/nonconstructor.js
new file mode 100644
index 0000000000..6e34171e77
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/nonconstructor.js
@@ -0,0 +1,18 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.fromhex
+description: >
+ Uint8Array.fromHex is not a constructor function.
+includes: [isConstructor.js]
+features: [uint8array-base64, TypedArray, Reflect.construct]
+---*/
+
+assert(!isConstructor(Uint8Array.fromHex), "Uint8Array.fromHex is not a constructor");
+
+assert.throws(TypeError, function() {
+ new Uint8Array.fromHex('');
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/odd-length-input.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/odd-length-input.js
new file mode 100644
index 0000000000..fe7860a083
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/odd-length-input.js
@@ -0,0 +1,14 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.fromhex
+description: Uint8Array.fromHex throws if given an odd number of input hex characters
+features: [uint8array-base64, TypedArray]
+---*/
+
+assert.throws(SyntaxError, function() {
+ Uint8Array.fromHex('a');
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/results.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/results.js
new file mode 100644
index 0000000000..d40beab7cd
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/results.js
@@ -0,0 +1,31 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.fromhex
+description: Conversion of hex strings to Uint8Arrays
+includes: [compareArray.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+var cases = [
+ ["", []],
+ ["66", [102]],
+ ["666f", [102, 111]],
+ ["666F", [102, 111]],
+ ["666f6f", [102, 111, 111]],
+ ["666F6f", [102, 111, 111]],
+ ["666f6f62", [102, 111, 111, 98]],
+ ["666f6f6261", [102, 111, 111, 98, 97]],
+ ["666f6f626172", [102, 111, 111, 98, 97, 114]],
+];
+
+cases.forEach(function (pair) {
+ var arr = Uint8Array.fromHex(pair[0]);
+ assert.sameValue(Object.getPrototypeOf(arr), Uint8Array.prototype, "decoding " + pair[0]);
+ assert.sameValue(arr.length, pair[1].length, "decoding " + pair[0]);
+ assert.sameValue(arr.buffer.byteLength, pair[1].length, "decoding " + pair[0]);
+ assert.compareArray(arr, pair[1], "decoding " + pair[0]);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/shell.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/shell.js
@@ -0,0 +1,24 @@
+// GENERATED, DO NOT EDIT
+// 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;
+}
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/string-coercion.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/string-coercion.js
new file mode 100644
index 0000000000..fea57227fc
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/fromHex/string-coercion.js
@@ -0,0 +1,23 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.fromhex
+description: Uint8Array.fromHex throws if its argument is not a string
+features: [uint8array-base64, TypedArray]
+---*/
+
+var toStringCalls = 0;
+var throwyToString = {
+ toString: function() {
+ toStringCalls += 1;
+ throw new Test262Error("toString called");
+ }
+};
+
+assert.throws(TypeError, function() {
+ Uint8Array.fromHex(throwyToString);
+});
+assert.sameValue(toStringCalls, 0);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/browser.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/browser.js
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/alphabet.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/alphabet.js
new file mode 100644
index 0000000000..bb4acdb8f2
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/alphabet.js
@@ -0,0 +1,44 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfrombase64
+description: Conversion of base64 strings to Uint8Arrays exercising the alphabet option
+includes: [compareArray.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+var target = new Uint8Array([255, 255, 255, 255]);
+var result = target.setFromBase64('x+/y');
+assert.sameValue(result.read, 4);
+assert.sameValue(result.written, 3);
+assert.compareArray(target, [199, 239, 242, 255]);
+
+var target = new Uint8Array([255, 255, 255, 255]);
+var result = target.setFromBase64('x+/y', { alphabet: 'base64' });
+assert.sameValue(result.read, 4);
+assert.sameValue(result.written, 3);
+assert.compareArray(target, [199, 239, 242, 255]);
+
+assert.throws(SyntaxError, function() {
+ var target = new Uint8Array([255, 255, 255, 255]);
+ target.setFromBase64('x+/y', { alphabet: 'base64url' });
+});
+
+
+var target = new Uint8Array([255, 255, 255, 255]);
+var result = target.setFromBase64('x-_y', { alphabet: 'base64url' });
+assert.sameValue(result.read, 4);
+assert.sameValue(result.written, 3);
+assert.compareArray(target, [199, 239, 242, 255]);
+
+assert.throws(SyntaxError, function() {
+ var target = new Uint8Array([255, 255, 255, 255]);
+ target.setFromBase64('x-_y');
+});
+assert.throws(SyntaxError, function() {
+ var target = new Uint8Array([255, 255, 255, 255]);
+ target.setFromBase64('x-_y', { alphabet: 'base64' });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/browser.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/browser.js
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/descriptor.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/descriptor.js
new file mode 100644
index 0000000000..bd319f7d43
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/descriptor.js
@@ -0,0 +1,18 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfrombase64
+description: >
+ Uint8Array.prototype.setFromBase64 has default data property attributes.
+includes: [propertyHelper.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+verifyProperty(Uint8Array.prototype, 'setFromBase64', {
+ enumerable: false,
+ writable: true,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/detached-buffer.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/detached-buffer.js
new file mode 100644
index 0000000000..3dd042bb02
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/detached-buffer.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfrombase64
+description: Uint8Array.prototype.setFromBase64 throws on detatched buffers
+includes: [detachArrayBuffer.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+var target = new Uint8Array([255, 255, 255]);
+$DETACHBUFFER(target.buffer);
+assert.throws(TypeError, function() {
+ target.setFromBase64('Zg==');
+});
+
+var getterCalls = 0;
+var targetDetachingOptions = {};
+Object.defineProperty(targetDetachingOptions, 'alphabet', {
+ get: function() {
+ getterCalls += 1;
+ $DETACHBUFFER(target.buffer);
+ return "base64";
+ }
+});
+var target = new Uint8Array([255, 255, 255]);
+assert.throws(TypeError, function() {
+ target.setFromBase64('Zg==', targetDetachingOptions);
+});
+assert.sameValue(getterCalls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/illegal-characters.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/illegal-characters.js
new file mode 100644
index 0000000000..9c6b827df8
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/illegal-characters.js
@@ -0,0 +1,27 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfrombase64
+description: Uint8Array.prototype.setFromBase64 throws a SyntaxError when input has non-base64, non-ascii-whitespace characters
+features: [uint8array-base64, TypedArray]
+---*/
+
+var illegal = [
+ 'Zm.9v',
+ 'Zm9v^',
+ 'Zg==&',
+ 'Z−==', // U+2212 'Minus Sign'
+ 'Z+==', // U+FF0B 'Fullwidth Plus Sign'
+ 'Zg\u00A0==', // nbsp
+ 'Zg\u2009==', // thin space
+ 'Zg\u2028==', // line separator
+];
+illegal.forEach(function(value) {
+ assert.throws(SyntaxError, function() {
+ var target = new Uint8Array([255, 255, 255, 255, 255]);
+ target.setFromBase64(value);
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/last-chunk-handling.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/last-chunk-handling.js
new file mode 100644
index 0000000000..958a89b10e
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/last-chunk-handling.js
@@ -0,0 +1,156 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfrombase64
+description: Handling of final chunks in target.setFromBase64
+includes: [compareArray.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+// padding
+var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+var result = target.setFromBase64('ZXhhZg==');
+assert.sameValue(result.read, 8);
+assert.sameValue(result.written, 4);
+assert.compareArray(target, [101, 120, 97, 102, 255, 255]);
+
+var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+var result = target.setFromBase64('ZXhhZg==', { lastChunkHandling: 'loose' });
+assert.sameValue(result.read, 8);
+assert.sameValue(result.written, 4);
+assert.compareArray(target, [101, 120, 97, 102, 255, 255]);
+
+var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+var result = target.setFromBase64('ZXhhZg==', { lastChunkHandling: 'stop-before-partial' });
+assert.sameValue(result.read, 8);
+assert.sameValue(result.written, 4);
+assert.compareArray(target, [101, 120, 97, 102, 255, 255]);
+
+var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+var result = target.setFromBase64('ZXhhZg==', { lastChunkHandling: 'strict' });
+assert.sameValue(result.read, 8);
+assert.sameValue(result.written, 4);
+assert.compareArray(target, [101, 120, 97, 102, 255, 255]);
+
+
+// no padding
+var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+var result = target.setFromBase64('ZXhhZg');
+assert.sameValue(result.read, 6);
+assert.sameValue(result.written, 4);
+assert.compareArray(target, [101, 120, 97, 102, 255, 255]);
+
+var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+var result = target.setFromBase64('ZXhhZg', { lastChunkHandling: 'loose' });
+assert.sameValue(result.read, 6);
+assert.sameValue(result.written, 4);
+assert.compareArray(target, [101, 120, 97, 102, 255, 255]);
+
+var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+var result = target.setFromBase64('ZXhhZg', { lastChunkHandling: 'stop-before-partial' });
+assert.sameValue(result.read, 4);
+assert.sameValue(result.written, 3);
+assert.compareArray(target, [101, 120, 97, 255, 255, 255]);
+
+assert.throws(SyntaxError, function() {
+ var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+ target.setFromBase64('ZXhhZg', { lastChunkHandling: 'strict' });
+});
+
+
+// non-zero padding bits
+var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+var result = target.setFromBase64('ZXhhZh==');
+assert.sameValue(result.read, 8);
+assert.sameValue(result.written, 4);
+assert.compareArray(target, [101, 120, 97, 102, 255, 255]);
+
+var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+var result = target.setFromBase64('ZXhhZh==', { lastChunkHandling: 'loose' });
+assert.sameValue(result.read, 8);
+assert.sameValue(result.written, 4);
+assert.compareArray(target, [101, 120, 97, 102, 255, 255]);
+
+var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+var result = target.setFromBase64('ZXhhZh==', { lastChunkHandling: 'stop-before-partial' });
+assert.sameValue(result.read, 8);
+assert.sameValue(result.written, 4);
+assert.compareArray(target, [101, 120, 97, 102, 255, 255]);
+
+assert.throws(SyntaxError, function() {
+ var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+ target.setFromBase64('ZXhhZh==', { lastChunkHandling: 'strict' });
+});
+
+
+// non-zero padding bits, no padding
+var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+var result = target.setFromBase64('ZXhhZh');
+assert.sameValue(result.read, 6);
+assert.sameValue(result.written, 4);
+assert.compareArray(target, [101, 120, 97, 102, 255, 255]);
+
+var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+var result = target.setFromBase64('ZXhhZh', { lastChunkHandling: 'loose' });
+assert.sameValue(result.read, 6);
+assert.sameValue(result.written, 4);
+assert.compareArray(target, [101, 120, 97, 102, 255, 255]);
+
+var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+var result = target.setFromBase64('ZXhhZh', { lastChunkHandling: 'stop-before-partial' });
+assert.sameValue(result.read, 4);
+assert.sameValue(result.written, 3);
+assert.compareArray(target, [101, 120, 97, 255, 255, 255]);
+
+assert.throws(SyntaxError, function() {
+ var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+ target.setFromBase64('ZXhhZh', { lastChunkHandling: 'strict' });
+});
+
+
+// partial padding
+assert.throws(SyntaxError, function() {
+ var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+ target.setFromBase64('ZXhhZg=');
+});
+
+assert.throws(SyntaxError, function() {
+ var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+ target.setFromBase64('ZXhhZg=', { lastChunkHandling: 'loose' });
+});
+
+var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+var result = target.setFromBase64('ZXhhZg=', { lastChunkHandling: 'stop-before-partial' });
+assert.sameValue(result.read, 4);
+assert.sameValue(result.written, 3);
+assert.compareArray(target, [101, 120, 97, 255, 255, 255]);
+
+assert.throws(SyntaxError, function() {
+ var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+ target.setFromBase64('ZXhhZg=', { lastChunkHandling: 'strict' });
+});
+
+
+// excess padding
+assert.throws(SyntaxError, function() {
+ var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+ target.setFromBase64('ZXhhZg===');
+});
+
+assert.throws(SyntaxError, function() {
+ var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+ target.setFromBase64('ZXhhZg===', { lastChunkHandling: 'loose' });
+});
+
+assert.throws(SyntaxError, function() {
+ var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+ target.setFromBase64('ZXhhZg===', { lastChunkHandling: 'stop-before-partial' });
+});
+
+assert.throws(SyntaxError, function() {
+ var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+ target.setFromBase64('ZXhhZg===', { lastChunkHandling: 'strict' });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/length.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/length.js
new file mode 100644
index 0000000000..df97101a14
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/length.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfrombase64
+description: >
+ Uint8Array.prototype.setFromBase64.length is 1.
+includes: [propertyHelper.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+verifyProperty(Uint8Array.prototype.setFromBase64, 'length', {
+ value: 1,
+ enumerable: false,
+ writable: false,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/name.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/name.js
new file mode 100644
index 0000000000..c38be74532
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/name.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfrombase64
+description: >
+ Uint8Array.prototype.setFromBase64.name is "setFromBase64".
+includes: [propertyHelper.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+verifyProperty(Uint8Array.prototype.setFromBase64, 'name', {
+ value: 'setFromBase64',
+ enumerable: false,
+ writable: false,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/nonconstructor.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/nonconstructor.js
new file mode 100644
index 0000000000..46f5078ff5
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/nonconstructor.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfrombase64
+description: >
+ Uint8Array.prototype.setFromBase64 is not a constructor function.
+includes: [isConstructor.js]
+features: [uint8array-base64, TypedArray, Reflect.construct]
+---*/
+
+assert(!isConstructor(Uint8Array.prototype.setFromBase64), "Uint8Array.prototype.setFromBase64 is not a constructor");
+
+assert.throws(TypeError, function() {
+ var target = new Uint8Array(10);
+ new target.setFromBase64('');
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/option-coercion.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/option-coercion.js
new file mode 100644
index 0000000000..90bd1e330d
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/option-coercion.js
@@ -0,0 +1,72 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfrombase64
+description: Uint8Array.prototype.setFromBase64 triggers effects of the "alphabet" and "lastChunkHandling" getters, but does not perform toString on the results
+includes: [compareArray.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+assert.throws(TypeError, function() {
+ var target = new Uint8Array([255, 255, 255]);
+ target.setFromBase64("Zg==", { alphabet: Object("base64") });
+});
+
+assert.throws(TypeError, function() {
+ var target = new Uint8Array([255, 255, 255]);
+ target.setFromBase64("Zg==", { lastChunkHandling: Object("strict") });
+});
+
+
+var toStringCalls = 0;
+var throwyToString = {
+ toString: function() {
+ toStringCalls += 1;
+ throw new Test262Error("toString called");
+ }
+};
+assert.throws(TypeError, function() {
+ var target = new Uint8Array([255, 255, 255]);
+ target.setFromBase64("Zg==", { alphabet: throwyToString });
+});
+assert.sameValue(toStringCalls, 0);
+
+assert.throws(TypeError, function() {
+ var target = new Uint8Array([255, 255, 255]);
+ target.setFromBase64("Zg==", { lastChunkHandling: throwyToString });
+});
+assert.sameValue(toStringCalls, 0);
+
+
+var alphabetAccesses = 0;
+var base64UrlOptions = {};
+Object.defineProperty(base64UrlOptions, "alphabet", {
+ get: function() {
+ alphabetAccesses += 1;
+ return "base64url";
+ }
+});
+var target = new Uint8Array([255, 255, 255, 255]);
+var result = target.setFromBase64("x-_y", base64UrlOptions);
+assert.sameValue(result.read, 4);
+assert.sameValue(result.written, 3);
+assert.compareArray(target, [199, 239, 242, 255]);
+assert.sameValue(alphabetAccesses, 1);
+
+var lastChunkHandlingAccesses = 0;
+var strictOptions = {};
+Object.defineProperty(strictOptions, "lastChunkHandling", {
+ get: function() {
+ lastChunkHandlingAccesses += 1;
+ return "strict";
+ }
+});
+var target = new Uint8Array([255, 255, 255, 255]);
+var result = target.setFromBase64("Zg==", strictOptions);
+assert.sameValue(result.read, 4);
+assert.sameValue(result.written, 1);
+assert.compareArray(target, [102, 255, 255, 255]);
+assert.sameValue(lastChunkHandlingAccesses, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/results.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/results.js
new file mode 100644
index 0000000000..2c39bab318
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/results.js
@@ -0,0 +1,33 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfrombase64
+description: Conversion of base64 strings to Uint8Arrays
+includes: [compareArray.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+// standard test vectors from https://datatracker.ietf.org/doc/html/rfc4648#section-10
+var standardBase64Vectors = [
+ ["", []],
+ ["Zg==", [102]],
+ ["Zm8=", [102, 111]],
+ ["Zm9v", [102, 111, 111]],
+ ["Zm9vYg==", [102, 111, 111, 98]],
+ ["Zm9vYmE=", [102, 111, 111, 98, 97]],
+ ["Zm9vYmFy", [102, 111, 111, 98, 97, 114]],
+];
+
+standardBase64Vectors.forEach(function (pair) {
+ var allFF = [255, 255, 255, 255, 255, 255, 255, 255];
+ var target = new Uint8Array(allFF);
+ var result = target.setFromBase64(pair[0]);
+ assert.sameValue(result.read, pair[0].length);
+ assert.sameValue(result.written, pair[1].length);
+
+ var expected = pair[1].concat(allFF.slice(pair[1].length))
+ assert.compareArray(target, expected, "decoding " + pair[0]);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/shell.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/shell.js
new file mode 100644
index 0000000000..a7590326c3
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/shell.js
@@ -0,0 +1,42 @@
+// GENERATED, DO NOT EDIT
+// 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: 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;
+}
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/string-coercion.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/string-coercion.js
new file mode 100644
index 0000000000..7c479a78cd
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/string-coercion.js
@@ -0,0 +1,46 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfrombase64
+description: Uint8Array.prototype.setFromBase64 throws if its first argument is not a string
+features: [uint8array-base64, TypedArray]
+---*/
+
+var toStringCalls = 0;
+var throwyToString = {
+ toString: function() {
+ toStringCalls += 1;
+ throw new Test262Error("toString called");
+ }
+};
+
+assert.throws(TypeError, function() {
+ var target = new Uint8Array(10);
+ target.setFromBase64(throwyToString);
+});
+assert.sameValue(toStringCalls, 0);
+
+
+var optionAccesses = 0;
+var touchyOptions = {};
+Object.defineProperty(touchyOptions, "alphabet", {
+ get: function() {
+ optionAccesses += 1;
+ throw new Test262Error("alphabet accessed");
+ }
+});
+Object.defineProperty(touchyOptions, "lastChunkHandling", {
+ get: function() {
+ optionAccesses += 1;
+ throw new Test262Error("lastChunkHandling accessed");
+ }
+});
+assert.throws(TypeError, function() {
+ var target = new Uint8Array(10);
+ target.setFromBase64(throwyToString, touchyOptions);
+});
+assert.sameValue(toStringCalls, 0);
+assert.sameValue(optionAccesses, 0);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/subarray.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/subarray.js
new file mode 100644
index 0000000000..ffffd227b9
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/subarray.js
@@ -0,0 +1,20 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfrombase64
+description: Uint8Array.prototype.setFromBase64 takes into account the offset of the target Uint8Array
+includes: [compareArray.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+var base = new Uint8Array([255, 255, 255, 255, 255, 255, 255]);
+var subarray = base.subarray(2, 5);
+
+var result = subarray.setFromBase64('Zm9vYmFy');
+assert.sameValue(result.read, 4);
+assert.sameValue(result.written, 3);
+assert.compareArray(subarray, [102, 111, 111]);
+assert.compareArray(base, [255, 255, 102, 111, 111, 255, 255]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/target-size.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/target-size.js
new file mode 100644
index 0000000000..4e38423621
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/target-size.js
@@ -0,0 +1,67 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfrombase64
+description: Uint8Array.prototype.setFromBase64 behavior when target buffer is small
+includes: [compareArray.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+// buffer too small
+var target = new Uint8Array([255, 255, 255, 255, 255]);
+var result = target.setFromBase64('Zm9vYmFy');
+assert.sameValue(result.read, 4);
+assert.sameValue(result.written, 3);
+assert.compareArray(target, [102, 111, 111, 255, 255]);
+
+// buffer too small, padded
+var target = new Uint8Array([255, 255, 255, 255]);
+var result = target.setFromBase64('Zm9vYmE=');
+assert.sameValue(result.read, 4);
+assert.sameValue(result.written, 3);
+assert.compareArray(target, [102, 111, 111, 255]);
+
+// buffer exact
+var target = new Uint8Array([255, 255, 255, 255, 255, 255]);
+var result = target.setFromBase64('Zm9vYmFy');
+assert.sameValue(result.read, 8);
+assert.sameValue(result.written, 6);
+assert.compareArray(target, [102, 111, 111, 98, 97, 114]);
+
+// buffer exact, padded
+var target = new Uint8Array([255, 255, 255, 255, 255]);
+var result = target.setFromBase64('Zm9vYmE=');
+assert.sameValue(result.read, 8);
+assert.sameValue(result.written, 5);
+assert.compareArray(target, [102, 111, 111, 98, 97]);
+
+// buffer exact, not padded
+var target = new Uint8Array([255, 255, 255, 255, 255]);
+var result = target.setFromBase64('Zm9vYmE');
+assert.sameValue(result.read, 7);
+assert.sameValue(result.written, 5);
+assert.compareArray(target, [102, 111, 111, 98, 97]);
+
+// buffer exact, padded, stop-before-partial
+var target = new Uint8Array([255, 255, 255, 255, 255]);
+var result = target.setFromBase64('Zm9vYmE=', { lastChunkHandling: 'stop-before-partial' });
+assert.sameValue(result.read, 8);
+assert.sameValue(result.written, 5);
+assert.compareArray(target, [102, 111, 111, 98, 97]);
+
+// buffer exact, not padded, stop-before-partial
+var target = new Uint8Array([255, 255, 255, 255, 255]);
+var result = target.setFromBase64('Zm9vYmE', { lastChunkHandling: 'stop-before-partial' });
+assert.sameValue(result.read, 4);
+assert.sameValue(result.written, 3);
+assert.compareArray(target, [102, 111, 111, 255, 255]);
+
+// buffer too large
+var target = new Uint8Array([255, 255, 255, 255, 255, 255, 255]);
+var result = target.setFromBase64('Zm9vYmFy');
+assert.sameValue(result.read, 8);
+assert.sameValue(result.written, 6);
+assert.compareArray(target, [102, 111, 111, 98, 97, 114, 255]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/whitespace.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/whitespace.js
new file mode 100644
index 0000000000..a09673d2bd
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromBase64/whitespace.js
@@ -0,0 +1,26 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfrombase64
+description: Uint8Array.prototype.setFromBase64 ignores ASCII whitespace in the input
+includes: [compareArray.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+var whitespaceKinds = [
+ ["Z g==", "space"],
+ ["Z\tg==", "tab"],
+ ["Z\x0Ag==", "LF"],
+ ["Z\x0Cg==", "FF"],
+ ["Z\x0Dg==", "CR"],
+];
+whitespaceKinds.forEach(function(pair) {
+ var target = new Uint8Array([255, 255, 255]);
+ var result = target.setFromBase64(pair[0]);
+ assert.sameValue(result.read, 5);
+ assert.sameValue(result.written, 1);
+ assert.compareArray(target, [102, 255, 255], "ascii whitespace: " + pair[1]);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/browser.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/browser.js
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/descriptor.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/descriptor.js
new file mode 100644
index 0000000000..3d1a4c996a
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/descriptor.js
@@ -0,0 +1,18 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfromhex
+description: >
+ Uint8Array.prototype.setFromHex has default data property attributes.
+includes: [propertyHelper.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+verifyProperty(Uint8Array.prototype, 'setFromHex', {
+ enumerable: false,
+ writable: true,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/detached-buffer.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/detached-buffer.js
new file mode 100644
index 0000000000..5ba8e15727
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/detached-buffer.js
@@ -0,0 +1,17 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfromhex
+description: Uint8Array.prototype.setFromHex throws on detatched buffers
+includes: [detachArrayBuffer.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+var target = new Uint8Array([255, 255, 255]);
+$DETACHBUFFER(target.buffer);
+assert.throws(TypeError, function() {
+ target.setFromHex('aa');
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/illegal-characters.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/illegal-characters.js
new file mode 100644
index 0000000000..1c30b4cffd
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/illegal-characters.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfromhex
+description: Uint8Array.prototype.setFromHex throws a SyntaxError when input has non-hex characters
+features: [uint8array-base64, TypedArray]
+---*/
+
+var illegal = [
+ 'a.a',
+ 'aa^',
+ 'a a',
+ 'a\ta',
+ 'a\x0Aa',
+ 'a\x0Ca',
+ 'a\x0Da',
+ 'a\u00A0a', // nbsp
+ 'a\u2009a', // thin space
+ 'a\u2028a', // line separator
+];
+illegal.forEach(function(value) {
+ assert.throws(SyntaxError, function() {
+ var target = new Uint8Array([255, 255, 255, 255, 255]);
+ target.setFromHex(value);
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/length.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/length.js
new file mode 100644
index 0000000000..b0b56ef761
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/length.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfromhex
+description: >
+ Uint8Array.prototype.setFromHex.length is 1.
+includes: [propertyHelper.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+verifyProperty(Uint8Array.prototype.setFromHex, 'length', {
+ value: 1,
+ enumerable: false,
+ writable: false,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/name.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/name.js
new file mode 100644
index 0000000000..cbc06e6f3d
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/name.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfromhex
+description: >
+ Uint8Array.prototype.setFromHex.name is "setFromHex".
+includes: [propertyHelper.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+verifyProperty(Uint8Array.prototype.setFromHex, 'name', {
+ value: 'setFromHex',
+ enumerable: false,
+ writable: false,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/nonconstructor.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/nonconstructor.js
new file mode 100644
index 0000000000..196b962bdf
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/nonconstructor.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfromhex
+description: >
+ Uint8Array.prototype.setFromHex is not a constructor function.
+includes: [isConstructor.js]
+features: [uint8array-base64, TypedArray, Reflect.construct]
+---*/
+
+assert(!isConstructor(Uint8Array.prototype.setFromHex), "target.setFromHex is not a constructor");
+
+assert.throws(TypeError, function() {
+ var target = new Uint8Array(10);
+ new target.setFromHex('');
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/results.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/results.js
new file mode 100644
index 0000000000..c7749c6257
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/results.js
@@ -0,0 +1,34 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfromhex
+description: Conversion of hex strings to Uint8Arrays
+includes: [compareArray.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+var cases = [
+ ["", []],
+ ["66", [102]],
+ ["666f", [102, 111]],
+ ["666F", [102, 111]],
+ ["666f6f", [102, 111, 111]],
+ ["666F6f", [102, 111, 111]],
+ ["666f6f62", [102, 111, 111, 98]],
+ ["666f6f6261", [102, 111, 111, 98, 97]],
+ ["666f6f626172", [102, 111, 111, 98, 97, 114]],
+];
+
+cases.forEach(function (pair) {
+ var allFF = [255, 255, 255, 255, 255, 255, 255, 255];
+ var target = new Uint8Array(allFF);
+ var result = target.setFromHex(pair[0]);
+ assert.sameValue(result.read, pair[0].length);
+ assert.sameValue(result.written, pair[1].length);
+
+ var expected = pair[1].concat(allFF.slice(pair[1].length))
+ assert.compareArray(target, expected, "decoding " + pair[0]);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/shell.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/shell.js
new file mode 100644
index 0000000000..a7590326c3
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/shell.js
@@ -0,0 +1,42 @@
+// GENERATED, DO NOT EDIT
+// 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: 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;
+}
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/string-coercion.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/string-coercion.js
new file mode 100644
index 0000000000..9a6f5f84c0
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/string-coercion.js
@@ -0,0 +1,24 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfromhex
+description: Uint8Array.prototype.setFromHex throws if its first argument is not a string
+features: [uint8array-base64, TypedArray]
+---*/
+
+var toStringCalls = 0;
+var throwyToString = {
+ toString: function() {
+ toStringCalls += 1;
+ throw new Test262Error("toString called");
+ }
+};
+
+assert.throws(TypeError, function() {
+ var target = new Uint8Array(10);
+ target.setFromHex(throwyToString);
+});
+assert.sameValue(toStringCalls, 0);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/subarray.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/subarray.js
new file mode 100644
index 0000000000..45879d8cb3
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/subarray.js
@@ -0,0 +1,20 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfromhex
+description: Uint8Array.prototype.setFromHex takes into account the offset of the target Uint8Array
+includes: [compareArray.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+var base = new Uint8Array([255, 255, 255, 255, 255, 255, 255]);
+var subarray = base.subarray(2, 5);
+
+var result = subarray.setFromHex('aabbcc');
+assert.sameValue(result.read, 6);
+assert.sameValue(result.written, 3);
+assert.compareArray(subarray, [170, 187, 204]);
+assert.compareArray(base, [255, 255, 170, 187, 204, 255, 255]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/target-size.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/target-size.js
new file mode 100644
index 0000000000..d73fa1749d
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/setFromHex/target-size.js
@@ -0,0 +1,32 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.setfromhex
+description: Uint8Array.prototype.setFromHex behavior when target buffer is small
+includes: [compareArray.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+// buffer too small
+var target = new Uint8Array([255, 255]);
+var result = target.setFromHex('aabbcc');
+assert.sameValue(result.read, 4);
+assert.sameValue(result.written, 2);
+assert.compareArray(target, [170, 187]);
+
+// buffer exact
+var target = new Uint8Array([255, 255, 255]);
+var result = target.setFromHex('aabbcc');
+assert.sameValue(result.read, 6);
+assert.sameValue(result.written, 3);
+assert.compareArray(target, [170, 187, 204]);
+
+// buffer too large
+var target = new Uint8Array([255, 255, 255, 255]);
+var result = target.setFromHex('aabbcc');
+assert.sameValue(result.read, 6);
+assert.sameValue(result.written, 3);
+assert.compareArray(target, [170, 187, 204, 255]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/shell.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/shell.js
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/alphabet.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/alphabet.js
new file mode 100644
index 0000000000..7edf0a379e
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/alphabet.js
@@ -0,0 +1,20 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.tobase64
+description: Conversion of Uint8Arrays to base64 strings exercising the alphabet option
+features: [uint8array-base64, TypedArray]
+---*/
+
+assert.sameValue((new Uint8Array([199, 239, 242])).toBase64(), "x+/y");
+
+assert.sameValue((new Uint8Array([199, 239, 242])).toBase64({ alphabet: 'base64' }), "x+/y");
+
+assert.sameValue((new Uint8Array([199, 239, 242])).toBase64({ alphabet: 'base64url' }), "x-_y");
+
+assert.throws(TypeError, function() {
+ (new Uint8Array([199, 239, 242])).toBase64({ alphabet: 'other' });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/browser.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/browser.js
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/descriptor.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/descriptor.js
new file mode 100644
index 0000000000..9c34719bf1
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/descriptor.js
@@ -0,0 +1,18 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.tobase64
+description: >
+ Uint8Array.prototype.toBase64 has default data property attributes.
+includes: [propertyHelper.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+verifyProperty(Uint8Array.prototype, 'toBase64', {
+ enumerable: false,
+ writable: true,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/detached-buffer.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/detached-buffer.js
new file mode 100644
index 0000000000..0904454743
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/detached-buffer.js
@@ -0,0 +1,42 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.tobase64
+description: Uint8Array.prototype.toBase64 checks for detachedness after side-effects are finished
+includes: [detachArrayBuffer.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+var array = new Uint8Array(2);
+var getterCalls = 0;
+var receiverDetachingOptions = {};
+Object.defineProperty(receiverDetachingOptions, "alphabet", {
+ get: function() {
+ getterCalls += 1;
+ $DETACHBUFFER(array.buffer);
+ return "base64";
+ }
+});
+assert.throws(TypeError, function() {
+ array.toBase64(receiverDetachingOptions);
+});
+assert.sameValue(getterCalls, 1);
+
+
+var detached = new Uint8Array(2);
+$DETACHBUFFER(detached.buffer);
+var getterCalls = 0;
+var sideEffectingOptions = {};
+Object.defineProperty(sideEffectingOptions, "alphabet", {
+ get: function() {
+ getterCalls += 1;
+ return "base64";
+ }
+});
+assert.throws(TypeError, function() {
+ detached.toBase64(sideEffectingOptions);
+});
+assert.sameValue(getterCalls, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/length.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/length.js
new file mode 100644
index 0000000000..9e4aabb9ed
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/length.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.tobase64
+description: >
+ Uint8Array.prototype.toBase64.length is 0.
+includes: [propertyHelper.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+verifyProperty(Uint8Array.prototype.toBase64, 'length', {
+ value: 0,
+ enumerable: false,
+ writable: false,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/name.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/name.js
new file mode 100644
index 0000000000..2510648b76
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/name.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.tobase64
+description: >
+ Uint8Array.prototype.toBase64.name is "toBase64".
+includes: [propertyHelper.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+verifyProperty(Uint8Array.prototype.toBase64, 'name', {
+ value: 'toBase64',
+ enumerable: false,
+ writable: false,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/nonconstructor.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/nonconstructor.js
new file mode 100644
index 0000000000..79280e2d5d
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/nonconstructor.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.tobase64
+description: >
+ Uint8Array.prototype.toBase64 is not a constructor function.
+includes: [isConstructor.js]
+features: [uint8array-base64, TypedArray, Reflect.construct]
+---*/
+
+assert(!isConstructor(Uint8Array.prototype.toBase64), "Uint8Array.prototype.toBase64 is not a constructor");
+
+var uint8Array = new Uint8Array(8);
+assert.throws(TypeError, function() {
+ new uint8Array.toBase64();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/option-coercion.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/option-coercion.js
new file mode 100644
index 0000000000..054a3a5e0d
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/option-coercion.js
@@ -0,0 +1,51 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.tobase64
+description: Uint8Array.prototype.toBase64 triggers effects of the "alphabet" getter, but does not perform toString on the result
+features: [uint8array-base64, TypedArray]
+---*/
+
+assert.throws(TypeError, function() {
+ (new Uint8Array(2)).toBase64({ alphabet: Object("base64") });
+});
+
+
+var toStringCalls = 0;
+var throwyToString = {
+ toString: function() {
+ toStringCalls += 1;
+ throw new Test262Error("toString called on alphabet value");
+ }
+};
+assert.throws(TypeError, function() {
+ (new Uint8Array(2)).toBase64({ alphabet: throwyToString });
+});
+assert.sameValue(toStringCalls, 0);
+
+var alphabetAccesses = 0;
+var base64UrlOptions = {};
+Object.defineProperty(base64UrlOptions, "alphabet", {
+ get: function() {
+ alphabetAccesses += 1;
+ return "base64url";
+ }
+});
+assert.sameValue((new Uint8Array([199, 239, 242])).toBase64(base64UrlOptions), "x-_y");
+assert.sameValue(alphabetAccesses, 1);
+
+// side-effects from the getter on the receiver are reflected in the result
+var array = new Uint8Array([0]);
+var receiverMutatingOptions = {};
+Object.defineProperty(receiverMutatingOptions, "alphabet", {
+ get: function() {
+ array[0] = 255;
+ return "base64";
+ }
+});
+var result = array.toBase64(receiverMutatingOptions);
+assert.sameValue(result, "/w==");
+assert.sameValue(array[0], 255);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/receiver-not-uint8array.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/receiver-not-uint8array.js
new file mode 100644
index 0000000000..53352ce4a5
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/receiver-not-uint8array.js
@@ -0,0 +1,36 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.tobase64
+description: Uint8Array.prototype.toBase64 throws if the receiver is not a Uint8Array
+includes: [testTypedArray.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+var toBase64 = Uint8Array.prototype.toBase64;
+
+var options = {};
+Object.defineProperty(options, "alphabet", {
+ get: function() {
+ throw new Test262Error("options.alphabet accessed despite incompatible receiver");
+ }
+});
+
+testWithTypedArrayConstructors(function(TA) {
+ if (TA === Uint8Array) return;
+ var sample = new TA(2);
+ assert.throws(TypeError, function() {
+ Uint8Array.prototype.toBase64.call(sample, options);
+ });
+});
+
+assert.throws(TypeError, function() {
+ Uint8Array.prototype.toBase64.call([], options);
+});
+
+assert.throws(TypeError, function() {
+ toBase64(options);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/results.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/results.js
new file mode 100644
index 0000000000..5ce75170b7
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/results.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.tobase64
+description: Conversion of Uint8Arrays to base64 strings
+features: [uint8array-base64, TypedArray]
+---*/
+
+// standard test vectors from https://datatracker.ietf.org/doc/html/rfc4648#section-10
+assert.sameValue((new Uint8Array([])).toBase64(), "");
+assert.sameValue((new Uint8Array([102])).toBase64(), "Zg==");
+assert.sameValue((new Uint8Array([102, 111])).toBase64(), "Zm8=");
+assert.sameValue((new Uint8Array([102, 111, 111])).toBase64(), "Zm9v");
+assert.sameValue((new Uint8Array([102, 111, 111, 98])).toBase64(), "Zm9vYg==");
+assert.sameValue((new Uint8Array([102, 111, 111, 98, 97])).toBase64(), "Zm9vYmE=");
+assert.sameValue((new Uint8Array([102, 111, 111, 98, 97, 114])).toBase64(), "Zm9vYmFy");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/shell.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/shell.js
new file mode 100644
index 0000000000..2af708ed59
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toBase64/shell.js
@@ -0,0 +1,203 @@
+// GENERATED, DO NOT EDIT
+// 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: 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: 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:
+ - floatArrayConstructors
+ - nonClampedIntArrayConstructors
+ - intArrayConstructors
+ - typedArrayConstructors
+ - TypedArray
+ - testWithTypedArrayConstructors
+ - nonAtomicsFriendlyTypedArrayConstructors
+ - testWithAtomicsFriendlyTypedArrayConstructors
+ - testWithNonAtomicsFriendlyTypedArrayConstructors
+ - testTypedArrayConversions
+---*/
+
+var floatArrayConstructors = [
+ Float64Array,
+ Float32Array
+];
+
+var nonClampedIntArrayConstructors = [
+ Int32Array,
+ Int16Array,
+ Int8Array,
+ Uint32Array,
+ Uint16Array,
+ Uint8Array
+];
+
+var intArrayConstructors = nonClampedIntArrayConstructors.concat([Uint8ClampedArray]);
+
+// Float16Array is a newer feature
+// adding it to this list unconditionally would cause implementations lacking it to fail every test which uses it
+if (typeof Float16Array !== 'undefined') {
+ floatArrayConstructors.push(Float16Array);
+}
+
+/**
+ * Array containing every non-bigint typed array constructor.
+ */
+
+var typedArrayConstructors = floatArrayConstructors.concat(intArrayConstructors);
+
+/**
+ * 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;
+ }
+ }
+}
+
+var nonAtomicsFriendlyTypedArrayConstructors = floatArrayConstructors.concat([Uint8ClampedArray]);
+/**
+ * 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, nonAtomicsFriendlyTypedArrayConstructors);
+}
+
+/**
+ * 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);
+ });
+ });
+}
+
+/**
+ * Checks if the given argument is one of the float-based TypedArray constructors.
+ *
+ * @param {constructor} ctor - the value to check
+ * @returns {boolean}
+ */
+function isFloatTypedArrayConstructor(arg) {
+ return floatArrayConstructors.indexOf(arg) !== -1;
+}
+
+/**
+ * Determines the precision of the given float-based TypedArray constructor.
+ *
+ * @param {constructor} ctor - the value to check
+ * @returns {string} "half", "single", or "double" for Float16Array, Float32Array, and Float64Array respectively.
+ */
+function floatTypedArrayConstructorPrecision(FA) {
+ if (typeof Float16Array !== "undefined" && FA === Float16Array) {
+ return "half";
+ } else if (FA === Float32Array) {
+ return "single";
+ } else if (FA === Float64Array) {
+ return "double";
+ } else {
+ throw new Error("Malformed test - floatTypedArrayConstructorPrecision called with non-float TypedArray");
+ }
+}
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/browser.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/browser.js
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/descriptor.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/descriptor.js
new file mode 100644
index 0000000000..fa1eba15de
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/descriptor.js
@@ -0,0 +1,18 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.tohex
+description: >
+ Uint8Array.prototype.toHex has default data property attributes.
+includes: [propertyHelper.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+verifyProperty(Uint8Array.prototype, 'toHex', {
+ enumerable: false,
+ writable: true,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/detached-buffer.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/detached-buffer.js
new file mode 100644
index 0000000000..e0126f6725
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/detached-buffer.js
@@ -0,0 +1,18 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.tohex
+description: Uint8Array.prototype.toHex throws if called on a detached buffer
+includes: [detachArrayBuffer.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+var array = new Uint8Array(2);
+$DETACHBUFFER(array.buffer);
+assert.throws(TypeError, function() {
+ array.toHex();
+});
+
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/length.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/length.js
new file mode 100644
index 0000000000..9c7d00d693
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/length.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.tohex
+description: >
+ Uint8Array.prototype.toHex.length is 0.
+includes: [propertyHelper.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+verifyProperty(Uint8Array.prototype.toHex, 'length', {
+ value: 0,
+ enumerable: false,
+ writable: false,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/name.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/name.js
new file mode 100644
index 0000000000..af2e1ef1d4
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/name.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.tohex
+description: >
+ Uint8Array.prototype.toHex.name is "toHex".
+includes: [propertyHelper.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+verifyProperty(Uint8Array.prototype.toHex, 'name', {
+ value: 'toHex',
+ enumerable: false,
+ writable: false,
+ configurable: true
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/nonconstructor.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/nonconstructor.js
new file mode 100644
index 0000000000..2d0f9fc00f
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/nonconstructor.js
@@ -0,0 +1,19 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.tohex
+description: >
+ Uint8Array.prototype.toHex is not a constructor function.
+includes: [isConstructor.js]
+features: [uint8array-base64, TypedArray, Reflect.construct]
+---*/
+
+assert(!isConstructor(Uint8Array.prototype.toHex), "Uint8Array.prototype.toHex is not a constructor");
+
+var uint8Array = new Uint8Array(8);
+assert.throws(TypeError, function() {
+ new uint8Array.toHex();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/receiver-not-uint8array.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/receiver-not-uint8array.js
new file mode 100644
index 0000000000..1409cca969
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/receiver-not-uint8array.js
@@ -0,0 +1,29 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.tohex
+description: Uint8Array.prototype.toHex throws if the receiver is not a Uint8Array
+includes: [testTypedArray.js]
+features: [uint8array-base64, TypedArray]
+---*/
+
+var toHex = Uint8Array.prototype.toHex;
+
+testWithTypedArrayConstructors(function(TA) {
+ if (TA === Uint8Array) return;
+ var sample = new TA(2);
+ assert.throws(TypeError, function() {
+ Uint8Array.prototype.toHex.call(sample);
+ });
+});
+
+assert.throws(TypeError, function() {
+ Uint8Array.prototype.toHex.call([]);
+});
+
+assert.throws(TypeError, function() {
+ toHex();
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/results.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/results.js
new file mode 100644
index 0000000000..fb8c31096f
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/results.js
@@ -0,0 +1,18 @@
+// |reftest| shell-option(--enable-uint8array-base64) skip-if(!Uint8Array.fromBase64||!xulRuntime.shell) -- uint8array-base64 is not enabled unconditionally, requires shell-options
+// Copyright (C) 2024 Kevin Gibbons. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-uint8array.prototype.tohex
+description: Conversion of Uint8Arrays to hex strings
+features: [uint8array-base64, TypedArray]
+---*/
+
+assert.sameValue((new Uint8Array([])).toHex(), "");
+assert.sameValue((new Uint8Array([102])).toHex(), "66");
+assert.sameValue((new Uint8Array([102, 111])).toHex(), "666f");
+assert.sameValue((new Uint8Array([102, 111, 111])).toHex(), "666f6f");
+assert.sameValue((new Uint8Array([102, 111, 111, 98])).toHex(), "666f6f62");
+assert.sameValue((new Uint8Array([102, 111, 111, 98, 97])).toHex(), "666f6f6261");
+assert.sameValue((new Uint8Array([102, 111, 111, 98, 97, 114])).toHex(), "666f6f626172");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/shell.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/shell.js
new file mode 100644
index 0000000000..2af708ed59
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/prototype/toHex/shell.js
@@ -0,0 +1,203 @@
+// GENERATED, DO NOT EDIT
+// 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: 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: 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:
+ - floatArrayConstructors
+ - nonClampedIntArrayConstructors
+ - intArrayConstructors
+ - typedArrayConstructors
+ - TypedArray
+ - testWithTypedArrayConstructors
+ - nonAtomicsFriendlyTypedArrayConstructors
+ - testWithAtomicsFriendlyTypedArrayConstructors
+ - testWithNonAtomicsFriendlyTypedArrayConstructors
+ - testTypedArrayConversions
+---*/
+
+var floatArrayConstructors = [
+ Float64Array,
+ Float32Array
+];
+
+var nonClampedIntArrayConstructors = [
+ Int32Array,
+ Int16Array,
+ Int8Array,
+ Uint32Array,
+ Uint16Array,
+ Uint8Array
+];
+
+var intArrayConstructors = nonClampedIntArrayConstructors.concat([Uint8ClampedArray]);
+
+// Float16Array is a newer feature
+// adding it to this list unconditionally would cause implementations lacking it to fail every test which uses it
+if (typeof Float16Array !== 'undefined') {
+ floatArrayConstructors.push(Float16Array);
+}
+
+/**
+ * Array containing every non-bigint typed array constructor.
+ */
+
+var typedArrayConstructors = floatArrayConstructors.concat(intArrayConstructors);
+
+/**
+ * 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;
+ }
+ }
+}
+
+var nonAtomicsFriendlyTypedArrayConstructors = floatArrayConstructors.concat([Uint8ClampedArray]);
+/**
+ * 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, nonAtomicsFriendlyTypedArrayConstructors);
+}
+
+/**
+ * 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);
+ });
+ });
+}
+
+/**
+ * Checks if the given argument is one of the float-based TypedArray constructors.
+ *
+ * @param {constructor} ctor - the value to check
+ * @returns {boolean}
+ */
+function isFloatTypedArrayConstructor(arg) {
+ return floatArrayConstructors.indexOf(arg) !== -1;
+}
+
+/**
+ * Determines the precision of the given float-based TypedArray constructor.
+ *
+ * @param {constructor} ctor - the value to check
+ * @returns {string} "half", "single", or "double" for Float16Array, Float32Array, and Float64Array respectively.
+ */
+function floatTypedArrayConstructorPrecision(FA) {
+ if (typeof Float16Array !== "undefined" && FA === Float16Array) {
+ return "half";
+ } else if (FA === Float32Array) {
+ return "single";
+ } else if (FA === Float64Array) {
+ return "double";
+ } else {
+ throw new Error("Malformed test - floatTypedArrayConstructorPrecision called with non-float TypedArray");
+ }
+}
diff --git a/js/src/tests/test262/prs/3994/built-ins/Uint8Array/shell.js b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/Uint8Array/shell.js
diff --git a/js/src/tests/test262/prs/3994/built-ins/browser.js b/js/src/tests/test262/prs/3994/built-ins/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/browser.js
diff --git a/js/src/tests/test262/prs/3994/built-ins/shell.js b/js/src/tests/test262/prs/3994/built-ins/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/built-ins/shell.js
diff --git a/js/src/tests/test262/prs/3994/shell.js b/js/src/tests/test262/prs/3994/shell.js
new file mode 100644
index 0000000000..9adb7aa914
--- /dev/null
+++ b/js/src/tests/test262/prs/3994/shell.js
@@ -0,0 +1,723 @@
+// GENERATED, DO NOT EDIT
+// file: assert.js
+// Copyright (C) 2017 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Collection of assertion functions used throughout test262
+defines: [assert]
+---*/
+
+
+function assert(mustBeTrue, message) {
+ if (mustBeTrue === true) {
+ return;
+ }
+
+ if (message === undefined) {
+ message = 'Expected true but got ' + assert._toString(mustBeTrue);
+ }
+ throw new Test262Error(message);
+}
+
+assert._isSameValue = function (a, b) {
+ if (a === b) {
+ // Handle +/-0 vs. -/+0
+ return a !== 0 || 1 / a === 1 / b;
+ }
+
+ // Handle NaN vs. NaN
+ return a !== a && b !== b;
+};
+
+assert.sameValue = function (actual, expected, message) {
+ try {
+ if (assert._isSameValue(actual, expected)) {
+ return;
+ }
+ } catch (error) {
+ throw new Test262Error(message + ' (_isSameValue operation threw) ' + error);
+ return;
+ }
+
+ if (message === undefined) {
+ message = '';
+ } else {
+ message += ' ';
+ }
+
+ message += 'Expected SameValue(«' + assert._toString(actual) + '», «' + assert._toString(expected) + '») to be true';
+
+ throw new Test262Error(message);
+};
+
+assert.notSameValue = function (actual, unexpected, message) {
+ if (!assert._isSameValue(actual, unexpected)) {
+ return;
+ }
+
+ if (message === undefined) {
+ message = '';
+ } else {
+ message += ' ';
+ }
+
+ message += 'Expected SameValue(«' + assert._toString(actual) + '», «' + assert._toString(unexpected) + '») to be false';
+
+ throw new Test262Error(message);
+};
+
+assert.throws = function (expectedErrorConstructor, func, message) {
+ var expectedName, actualName;
+ if (typeof func !== "function") {
+ throw new Test262Error('assert.throws requires two arguments: the error constructor ' +
+ 'and a function to run');
+ return;
+ }
+ if (message === undefined) {
+ message = '';
+ } else {
+ message += ' ';
+ }
+
+ try {
+ func();
+ } catch (thrown) {
+ 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);
+ }
+ return;
+ }
+
+ message += 'Expected a ' + expectedErrorConstructor.name + ' to be thrown but no exception was thrown at all';
+ throw new Test262Error(message);
+};
+
+assert._toString = function (value) {
+ try {
+ if (value === 0 && 1 / value === -Infinity) {
+ return '-0';
+ }
+
+ return String(value);
+ } catch (err) {
+ if (err.name === 'TypeError') {
+ return Object.prototype.toString.call(value);
+ }
+
+ throw err;
+ }
+};
+
+// file: compareArray.js
+// Copyright (C) 2017 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Compare the contents of two arrays
+defines: [compareArray]
+---*/
+
+function compareArray(a, b) {
+ if (b.length !== a.length) {
+ return false;
+ }
+
+ for (var i = 0; i < a.length; i++) {
+ if (!compareArray.isSameValue(b[i], a[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
+compareArray.isSameValue = function(a, b) {
+ if (a === 0 && b === 0) return 1 / a === 1 / b;
+ if (a !== a && b !== b) return true;
+
+ return a === b;
+};
+
+compareArray.format = function(arrayLike) {
+ return `[${[].map.call(arrayLike, String).join(', ')}]`;
+};
+
+assert.compareArray = function(actual, expected, message) {
+ message = message === undefined ? '' : message;
+
+ if (typeof message === 'symbol') {
+ message = message.toString();
+ }
+
+ assert(actual != null, `First argument shouldn't be nullish. ${message}`);
+ assert(expected != null, `Second argument shouldn't be nullish. ${message}`);
+ var format = compareArray.format;
+ var result = compareArray(actual, expected);
+
+ // The following prevents actual and expected from being iterated and evaluated
+ // more than once unless absolutely necessary.
+ if (!result) {
+ assert(false, `Expected ${format(actual)} and ${format(expected)} to have the same contents. ${message}`);
+ }
+};
+
+// file: propertyHelper.js
+// Copyright (C) 2017 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Collection of functions used to safely verify the correctness of
+ property descriptors.
+defines:
+ - verifyProperty
+ - verifyEqualTo # deprecated
+ - verifyWritable # deprecated
+ - verifyNotWritable # deprecated
+ - verifyEnumerable # deprecated
+ - verifyNotEnumerable # deprecated
+ - verifyConfigurable # deprecated
+ - verifyNotConfigurable # deprecated
+---*/
+
+// @ts-check
+
+/**
+ * @param {object} obj
+ * @param {string|symbol} name
+ * @param {PropertyDescriptor|undefined} desc
+ * @param {object} [options]
+ * @param {boolean} [options.restore]
+ */
+function verifyProperty(obj, name, desc, options) {
+ assert(
+ arguments.length > 2,
+ 'verifyProperty should receive at least 3 arguments: obj, name, and descriptor'
+ );
+
+ var originalDesc = Object.getOwnPropertyDescriptor(obj, name);
+ var nameStr = String(name);
+
+ // Allows checking for undefined descriptor if it's explicitly given.
+ if (desc === undefined) {
+ assert.sameValue(
+ originalDesc,
+ undefined,
+ "obj['" + nameStr + "'] descriptor should be undefined"
+ );
+
+ // desc and originalDesc are both undefined, problem solved;
+ return true;
+ }
+
+ assert(
+ Object.prototype.hasOwnProperty.call(obj, name),
+ "obj should have an own property " + nameStr
+ );
+
+ assert.notSameValue(
+ desc,
+ null,
+ "The desc argument should be an object or undefined, null"
+ );
+
+ assert.sameValue(
+ typeof desc,
+ "object",
+ "The desc argument should be an object or undefined, " + String(desc)
+ );
+
+ var names = Object.getOwnPropertyNames(desc);
+ for (var i = 0; i < names.length; i++) {
+ assert(
+ names[i] === "value" ||
+ names[i] === "writable" ||
+ names[i] === "enumerable" ||
+ names[i] === "configurable" ||
+ names[i] === "get" ||
+ names[i] === "set",
+ "Invalid descriptor field: " + names[i],
+ );
+ }
+
+ var failures = [];
+
+ if (Object.prototype.hasOwnProperty.call(desc, 'value')) {
+ if (!isSameValue(desc.value, originalDesc.value)) {
+ failures.push("descriptor value should be " + desc.value);
+ }
+ if (!isSameValue(desc.value, obj[name])) {
+ failures.push("object value should be " + desc.value);
+ }
+ }
+
+ if (Object.prototype.hasOwnProperty.call(desc, 'enumerable')) {
+ if (desc.enumerable !== originalDesc.enumerable ||
+ desc.enumerable !== isEnumerable(obj, name)) {
+ failures.push('descriptor should ' + (desc.enumerable ? '' : 'not ') + 'be enumerable');
+ }
+ }
+
+ if (Object.prototype.hasOwnProperty.call(desc, 'writable')) {
+ if (desc.writable !== originalDesc.writable ||
+ desc.writable !== isWritable(obj, name)) {
+ failures.push('descriptor should ' + (desc.writable ? '' : 'not ') + 'be writable');
+ }
+ }
+
+ if (Object.prototype.hasOwnProperty.call(desc, 'configurable')) {
+ if (desc.configurable !== originalDesc.configurable ||
+ desc.configurable !== isConfigurable(obj, name)) {
+ failures.push('descriptor should ' + (desc.configurable ? '' : 'not ') + 'be configurable');
+ }
+ }
+
+ assert(!failures.length, failures.join('; '));
+
+ if (options && options.restore) {
+ Object.defineProperty(obj, name, originalDesc);
+ }
+
+ return true;
+}
+
+function isConfigurable(obj, name) {
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
+ try {
+ delete obj[name];
+ } catch (e) {
+ if (!(e instanceof TypeError)) {
+ throw new Test262Error("Expected TypeError, got " + e);
+ }
+ }
+ return !hasOwnProperty.call(obj, name);
+}
+
+function isEnumerable(obj, name) {
+ var stringCheck = false;
+
+ if (typeof name === "string") {
+ for (var x in obj) {
+ if (x === name) {
+ stringCheck = true;
+ break;
+ }
+ }
+ } else {
+ // skip it if name is not string, works for Symbol names.
+ stringCheck = true;
+ }
+
+ return stringCheck &&
+ Object.prototype.hasOwnProperty.call(obj, name) &&
+ Object.prototype.propertyIsEnumerable.call(obj, name);
+}
+
+function isSameValue(a, b) {
+ if (a === 0 && b === 0) return 1 / a === 1 / b;
+ if (a !== a && b !== b) return true;
+
+ return a === b;
+}
+
+var __isArray = Array.isArray;
+function isWritable(obj, name, verifyProp, value) {
+ var unlikelyValue = __isArray(obj) && name === "length" ?
+ Math.pow(2, 32) - 1 :
+ "unlikelyValue";
+ var newValue = value || unlikelyValue;
+ var hadValue = Object.prototype.hasOwnProperty.call(obj, name);
+ var oldValue = obj[name];
+ var writeSucceeded;
+
+ try {
+ obj[name] = newValue;
+ } catch (e) {
+ if (!(e instanceof TypeError)) {
+ throw new Test262Error("Expected TypeError, got " + e);
+ }
+ }
+
+ writeSucceeded = isSameValue(obj[verifyProp || name], newValue);
+
+ // Revert the change only if it was successful (in other cases, reverting
+ // is unnecessary and may trigger exceptions for certain property
+ // configurations)
+ if (writeSucceeded) {
+ if (hadValue) {
+ obj[name] = oldValue;
+ } else {
+ delete obj[name];
+ }
+ }
+
+ return writeSucceeded;
+}
+
+/**
+ * Deprecated; please use `verifyProperty` in new tests.
+ */
+function verifyEqualTo(obj, name, value) {
+ if (!isSameValue(obj[name], value)) {
+ throw new Test262Error("Expected obj[" + String(name) + "] to equal " + value +
+ ", actually " + obj[name]);
+ }
+}
+
+/**
+ * Deprecated; please use `verifyProperty` in new tests.
+ */
+function verifyWritable(obj, name, verifyProp, value) {
+ if (!verifyProp) {
+ assert(Object.getOwnPropertyDescriptor(obj, name).writable,
+ "Expected obj[" + String(name) + "] to have writable:true.");
+ }
+ if (!isWritable(obj, name, verifyProp, value)) {
+ throw new Test262Error("Expected obj[" + String(name) + "] to be writable, but was not.");
+ }
+}
+
+/**
+ * Deprecated; please use `verifyProperty` in new tests.
+ */
+function verifyNotWritable(obj, name, verifyProp, value) {
+ if (!verifyProp) {
+ assert(!Object.getOwnPropertyDescriptor(obj, name).writable,
+ "Expected obj[" + String(name) + "] to have writable:false.");
+ }
+ if (isWritable(obj, name, verifyProp)) {
+ throw new Test262Error("Expected obj[" + String(name) + "] NOT to be writable, but was.");
+ }
+}
+
+/**
+ * Deprecated; please use `verifyProperty` in new tests.
+ */
+function verifyEnumerable(obj, name) {
+ assert(Object.getOwnPropertyDescriptor(obj, name).enumerable,
+ "Expected obj[" + String(name) + "] to have enumerable:true.");
+ if (!isEnumerable(obj, name)) {
+ throw new Test262Error("Expected obj[" + String(name) + "] to be enumerable, but was not.");
+ }
+}
+
+/**
+ * Deprecated; please use `verifyProperty` in new tests.
+ */
+function verifyNotEnumerable(obj, name) {
+ assert(!Object.getOwnPropertyDescriptor(obj, name).enumerable,
+ "Expected obj[" + String(name) + "] to have enumerable:false.");
+ if (isEnumerable(obj, name)) {
+ throw new Test262Error("Expected obj[" + String(name) + "] NOT to be enumerable, but was.");
+ }
+}
+
+/**
+ * Deprecated; please use `verifyProperty` in new tests.
+ */
+function verifyConfigurable(obj, name) {
+ assert(Object.getOwnPropertyDescriptor(obj, name).configurable,
+ "Expected obj[" + String(name) + "] to have configurable:true.");
+ if (!isConfigurable(obj, name)) {
+ throw new Test262Error("Expected obj[" + String(name) + "] to be configurable, but was not.");
+ }
+}
+
+/**
+ * Deprecated; please use `verifyProperty` in new tests.
+ */
+function verifyNotConfigurable(obj, name) {
+ assert(!Object.getOwnPropertyDescriptor(obj, name).configurable,
+ "Expected obj[" + String(name) + "] to have configurable:false.");
+ if (isConfigurable(obj, name)) {
+ throw new Test262Error("Expected obj[" + String(name) + "] NOT to be configurable, but was.");
+ }
+}
+
+// file: sta.js
+// Copyright (c) 2012 Ecma International. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: |
+ Provides both:
+
+ - An error class to avoid false positives when testing for thrown exceptions
+ - A function to explicitly throw an exception using the Test262Error class
+defines: [Test262Error, $DONOTEVALUATE]
+---*/
+
+
+function Test262Error(message) {
+ this.message = message || "";
+}
+
+Test262Error.prototype.toString = function () {
+ return "Test262Error: " + this.message;
+};
+
+Test262Error.thrower = function (message) {
+ throw new Test262Error(message);
+};
+
+function $DONOTEVALUATE() {
+ throw "Test262: This statement should not be evaluated.";
+}
+
+// file: test262-host.js
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+// https://github.com/tc39/test262/blob/main/INTERPRETING.md#host-defined-functions
+;(function createHostObject(global) {
+ "use strict";
+
+ // Save built-in functions and constructors.
+ var FunctionToString = global.Function.prototype.toString;
+ var ReflectApply = global.Reflect.apply;
+ var Atomics = global.Atomics;
+ var Error = global.Error;
+ var SharedArrayBuffer = global.SharedArrayBuffer;
+ var Int32Array = global.Int32Array;
+
+ // Save built-in shell functions.
+ var NewGlobal = global.newGlobal;
+ var setSharedArrayBuffer = global.setSharedArrayBuffer;
+ var getSharedArrayBuffer = global.getSharedArrayBuffer;
+ var evalInWorker = global.evalInWorker;
+ var monotonicNow = global.monotonicNow;
+ var gc = global.gc;
+ var clearKeptObjects = global.clearKeptObjects;
+
+ var hasCreateIsHTMLDDA = "createIsHTMLDDA" in global;
+ var hasThreads = ("helperThreadCount" in global ? global.helperThreadCount() > 0 : true);
+ var hasMailbox = typeof setSharedArrayBuffer === "function" && typeof getSharedArrayBuffer === "function";
+ var hasEvalInWorker = typeof evalInWorker === "function";
+
+ if (!hasCreateIsHTMLDDA && !("document" in global && "all" in global.document))
+ throw new Error("no [[IsHTMLDDA]] object available for testing");
+
+ var IsHTMLDDA = hasCreateIsHTMLDDA
+ ? global.createIsHTMLDDA()
+ : global.document.all;
+
+ // The $262.agent framework is not appropriate for browsers yet, and some
+ // test cases can't work in browsers (they block the main thread).
+
+ var shellCode = hasMailbox && hasEvalInWorker;
+ var sabTestable = Atomics && SharedArrayBuffer && hasThreads && shellCode;
+
+ global.$262 = {
+ __proto__: null,
+ createRealm() {
+ var newGlobalObject = NewGlobal();
+ var createHostObjectFn = ReflectApply(FunctionToString, createHostObject, []);
+ newGlobalObject.Function(`${createHostObjectFn} createHostObject(this);`)();
+ return newGlobalObject.$262;
+ },
+ detachArrayBuffer: global.detachArrayBuffer,
+ evalScript: global.evaluateScript || global.evaluate,
+ global,
+ IsHTMLDDA,
+ gc() {
+ gc();
+ },
+ clearKeptObjects() {
+ clearKeptObjects();
+ },
+ agent: (function () {
+
+ // SpiderMonkey complication: With run-time argument --no-threads
+ // our test runner will not properly filter test cases that can't be
+ // run because agents can't be started, and so we do a little
+ // filtering here: We will quietly succeed and exit if an agent test
+ // should not have been run because threads cannot be started.
+ //
+ // Firefox complication: The test cases that use $262.agent can't
+ // currently work in the browser, so for now we rely on them not
+ // being run at all.
+
+ if (!sabTestable) {
+ let {reportCompare, quit} = global;
+
+ function notAvailable() {
+ // See comment above.
+ if (!hasThreads && shellCode) {
+ reportCompare(0, 0);
+ quit(0);
+ }
+ throw new Error("Agents not available");
+ }
+
+ return {
+ start(script) { notAvailable() },
+ broadcast(sab, id) { notAvailable() },
+ getReport() { notAvailable() },
+ sleep(s) { notAvailable() },
+ monotonicNow,
+ }
+ }
+
+ // The SpiderMonkey implementation uses a designated shared buffer _ia
+ // for coordination, and spinlocks for everything except sleeping.
+
+ var _MSG_LOC = 0; // Low bit set: broadcast available; High bits: seq #
+ var _ID_LOC = 1; // ID sent with broadcast
+ var _ACK_LOC = 2; // Worker increments this to ack that broadcast was received
+ var _RDY_LOC = 3; // Worker increments this to ack that worker is up and running
+ var _LOCKTXT_LOC = 4; // Writer lock for the text buffer: 0=open, 1=closed
+ var _NUMTXT_LOC = 5; // Count of messages in text buffer
+ var _NEXT_LOC = 6; // First free location in the buffer
+ var _SLEEP_LOC = 7; // Used for sleeping
+
+ var _FIRST = 10; // First location of first message
+
+ var _ia = new Int32Array(new SharedArrayBuffer(65536));
+ _ia[_NEXT_LOC] = _FIRST;
+
+ var _worker_prefix =
+// BEGIN WORKER PREFIX
+`if (typeof $262 === 'undefined')
+ $262 = {};
+$262.agent = (function (global) {
+ var ReflectApply = global.Reflect.apply;
+ var StringCharCodeAt = global.String.prototype.charCodeAt;
+ var {
+ add: Atomics_add,
+ compareExchange: Atomics_compareExchange,
+ load: Atomics_load,
+ store: Atomics_store,
+ wait: Atomics_wait,
+ } = global.Atomics;
+
+ var {getSharedArrayBuffer} = global;
+
+ var _ia = new Int32Array(getSharedArrayBuffer());
+ var agent = {
+ receiveBroadcast(receiver) {
+ var k;
+ while (((k = Atomics_load(_ia, ${_MSG_LOC})) & 1) === 0)
+ ;
+ var received_sab = getSharedArrayBuffer();
+ var received_id = Atomics_load(_ia, ${_ID_LOC});
+ Atomics_add(_ia, ${_ACK_LOC}, 1);
+ while (Atomics_load(_ia, ${_MSG_LOC}) === k)
+ ;
+ receiver(received_sab, received_id);
+ },
+
+ report(msg) {
+ while (Atomics_compareExchange(_ia, ${_LOCKTXT_LOC}, 0, 1) === 1)
+ ;
+ msg = "" + msg;
+ var i = _ia[${_NEXT_LOC}];
+ _ia[i++] = msg.length;
+ for ( let j=0 ; j < msg.length ; j++ )
+ _ia[i++] = ReflectApply(StringCharCodeAt, msg, [j]);
+ _ia[${_NEXT_LOC}] = i;
+ Atomics_add(_ia, ${_NUMTXT_LOC}, 1);
+ Atomics_store(_ia, ${_LOCKTXT_LOC}, 0);
+ },
+
+ sleep(s) {
+ Atomics_wait(_ia, ${_SLEEP_LOC}, 0, s);
+ },
+
+ leaving() {},
+
+ monotonicNow: global.monotonicNow,
+ };
+ Atomics_add(_ia, ${_RDY_LOC}, 1);
+ return agent;
+})(this);`;
+// END WORKER PREFIX
+
+ var _numWorkers = 0;
+ var _numReports = 0;
+ var _reportPtr = _FIRST;
+ var {
+ add: Atomics_add,
+ load: Atomics_load,
+ store: Atomics_store,
+ wait: Atomics_wait,
+ } = Atomics;
+ var StringFromCharCode = global.String.fromCharCode;
+
+ return {
+ start(script) {
+ setSharedArrayBuffer(_ia.buffer);
+ var oldrdy = Atomics_load(_ia, _RDY_LOC);
+ evalInWorker(_worker_prefix + script);
+ while (Atomics_load(_ia, _RDY_LOC) === oldrdy)
+ ;
+ _numWorkers++;
+ },
+
+ broadcast(sab, id) {
+ setSharedArrayBuffer(sab);
+ Atomics_store(_ia, _ID_LOC, id);
+ Atomics_store(_ia, _ACK_LOC, 0);
+ Atomics_add(_ia, _MSG_LOC, 1);
+ while (Atomics_load(_ia, _ACK_LOC) < _numWorkers)
+ ;
+ Atomics_add(_ia, _MSG_LOC, 1);
+ },
+
+ getReport() {
+ if (_numReports === Atomics_load(_ia, _NUMTXT_LOC))
+ return null;
+ var s = "";
+ var i = _reportPtr;
+ var len = _ia[i++];
+ for ( let j=0 ; j < len ; j++ )
+ s += StringFromCharCode(_ia[i++]);
+ _reportPtr = i;
+ _numReports++;
+ return s;
+ },
+
+ sleep(s) {
+ Atomics_wait(_ia, _SLEEP_LOC, 0, s);
+ },
+
+ monotonicNow,
+ };
+ })()
+ };
+})(this);
+
+var $mozAsyncTestDone = false;
+function $DONE(failure) {
+ // This function is generally called from within a Promise handler, so any
+ // exception thrown by this method will be swallowed and most likely
+ // ignored by the Promise machinery.
+ if ($mozAsyncTestDone) {
+ reportFailure("$DONE() already called");
+ return;
+ }
+ $mozAsyncTestDone = true;
+
+ if (failure)
+ reportFailure(failure);
+ else
+ reportCompare(0, 0);
+
+ if (typeof jsTestDriverEnd === "function") {
+ gDelayTestDriverEnd = false;
+ jsTestDriverEnd();
+ }
+}
+
+// Some tests in test262 leave promise rejections unhandled.
+if ("ignoreUnhandledRejections" in this) {
+ ignoreUnhandledRejections();
+}
diff --git a/js/src/tests/test262/staging/JSON/json-parse-with-source-snapshot.js b/js/src/tests/test262/staging/JSON/json-parse-with-source-snapshot.js
index 45465333d4..7ef4f88dd8 100644
--- a/js/src/tests/test262/staging/JSON/json-parse-with-source-snapshot.js
+++ b/js/src/tests/test262/staging/JSON/json-parse-with-source-snapshot.js
@@ -1,4 +1,4 @@
-// |reftest| skip -- json-parse-with-source is not supported
+// |reftest| shell-option(--enable-json-parse-with-source) skip-if(!JSON.hasOwnProperty('isRawJSON')||!xulRuntime.shell) -- json-parse-with-source is not enabled unconditionally, requires shell-options
// Copyright (C) 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
diff --git a/js/src/tests/test262/staging/JSON/json-parse-with-source.js b/js/src/tests/test262/staging/JSON/json-parse-with-source.js
index f8674511ef..c6b6326423 100644
--- a/js/src/tests/test262/staging/JSON/json-parse-with-source.js
+++ b/js/src/tests/test262/staging/JSON/json-parse-with-source.js
@@ -1,4 +1,4 @@
-// |reftest| skip -- json-parse-with-source is not supported
+// |reftest| shell-option(--enable-json-parse-with-source) skip-if(!JSON.hasOwnProperty('isRawJSON')||!xulRuntime.shell) -- json-parse-with-source is not enabled unconditionally, requires shell-options
// Copyright (C) 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---