diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /js/src/jit-test/tests/structured-clone | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/jit-test/tests/structured-clone')
10 files changed, 436 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/structured-clone/Map-Set-cross-compartment.js b/js/src/jit-test/tests/structured-clone/Map-Set-cross-compartment.js new file mode 100644 index 0000000000..8ce792562e --- /dev/null +++ b/js/src/jit-test/tests/structured-clone/Map-Set-cross-compartment.js @@ -0,0 +1,11 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +// Don't crash +serialize(evalcx("new Set(['x', 'y'])")); +serialize(evalcx("new Map([['x', 1]])")); + +assertEq(deserialize(serialize(evalcx("new Set([1, 2, 3])"))).has(1), true); +assertEq(deserialize(serialize(evalcx("new Map([['x', 1]])"))).get('x'), 1); diff --git a/js/src/jit-test/tests/structured-clone/Map.js b/js/src/jit-test/tests/structured-clone/Map.js new file mode 100644 index 0000000000..51ac240961 --- /dev/null +++ b/js/src/jit-test/tests/structured-clone/Map.js @@ -0,0 +1,112 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +load(libdir + "asserts.js"); + +var map = new Map(); +map.set("self", map); + +var magic = deserialize(serialize(map)); +assertEq(magic.get("self"), magic); +assertEq(magic.size, 1); + +map = new Map(); +map.set(map, "self"); + +magic = deserialize(serialize(map)); +assertEq(magic.get(magic), "self"); +assertEq(magic.size, 1); + +var values = [ + "a", "\uDEFF", undefined, null, -3.5, true, false, NaN, 155, -2 +] + +map = new Map(); +for (var value of values) { + map.set(value, value); +} + +magic = deserialize(serialize(map)); +var i = 0; +for (value of magic) { + assertEq(value[0], value[1]); + assertEq(value[0], values[i++]); +} + +assertDeepEq([...map.keys()], [...magic.keys()]); +assertDeepEq([...map.values()], [...magic.values()]); + +var obj = {a: 1}; +obj.map = new Map(); +obj.map.set("obj", obj); + +magic = deserialize(serialize(obj)); + +assertEq(magic.map.get("obj"), magic); +assertEq(magic.a, 1); + +map = new Map(); +map.set("a", new Number(1)); +map.set("b", new String("aaaa")); +map.set("c", new Date(NaN)); + +magic = deserialize(serialize(map)); + +assertEq(magic.get("a").valueOf(), 1); +assertEq(magic.get("b").valueOf(), "aaaa"); +assertEq(magic.get("c").valueOf(), NaN); + +assertDeepEq([...map.keys()], ["a", "b", "c"]); + +map = new Map(); +map.set("x", new Map()); +map.get("x").set("x", map); +map.get("x").set("b", null); + +magic = deserialize(serialize(map)); + +assertEq(magic.get("x").get("x"), magic); +assertEq(magic.get("x").get("b"), null); + +map = new Map() +map.set({a: 1}, "b"); + +magic = deserialize(serialize(map)); + +obj = [...magic.keys()][0]; +assertEq(obj.a, 1); +assertEq(magic.get(obj), "b"); + +// Make sure expandos aren't cloned (Bug 1041172) +map = new Map(); +map.a = "aaaaa"; +magic = deserialize(serialize(map)); +assertEq("a" in magic, false); +assertEq(Object.keys(magic).length, 0); + +// Busted [[Prototype]] shouldn't matter +map = new Map(); +Object.setPrototypeOf(map, null); +Map.prototype.set.call(map, "self", map); +magic = deserialize(serialize(map)); +assertEq(magic.get("self"), magic); +assertEq(magic.size, 1); + +// Can't fuzz around with Map after it is cloned +obj = { + a: new Map(), + get b() { + obj.a.delete("test"); + return "invoked"; + } +} +obj.a.set("test", "hello"); +assertEq(obj.a.has("test"), true); +magic = deserialize(serialize(obj)); +assertEq(obj.a.has("test"), false); +assertEq(magic.a.size, 1); +assertEq(magic.a.get("test"), "hello"); +assertEq([...magic.a.keys()].toString(), "test"); +assertEq(magic.b, "invoked");
\ No newline at end of file diff --git a/js/src/jit-test/tests/structured-clone/Set.js b/js/src/jit-test/tests/structured-clone/Set.js new file mode 100644 index 0000000000..76c1651715 --- /dev/null +++ b/js/src/jit-test/tests/structured-clone/Set.js @@ -0,0 +1,84 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +load(libdir + "asserts.js"); + +var set = new Set(); +set.add(set); + +var magic = deserialize(serialize(set)); +assertEq(magic.size, 1); +assertEq(magic.values().next().value, magic); + +var values = [ + "a", "\uDEFF", undefined, null, -3.5, true, false, NaN, 155, -2 +] + +set = new Set(); +for (var value of values) { + set.add(value) +} + +magic = deserialize(serialize(set)); +var i = 0; +for (value of magic) { + assertEq(value, values[i++]); +} + +assertDeepEq([...set.keys()], [...magic.keys()]); +assertDeepEq([...set.values()], [...magic.values()]); + +var obj = {a: 1}; +obj.set = new Set(); +obj.set.add(obj); + +magic = deserialize(serialize(obj)); + +assertEq(magic.set.values().next().value, magic); +assertEq(magic.a, 1); + +set = new Set(); +set.add(new Number(1)); +set.add(new String("aaaa")); +set.add(new Date(NaN)); + +magic = deserialize(serialize(set)); + +values = magic.values(); +assertEq(values.next().value.valueOf(), 1); +assertEq(values.next().value.valueOf(), "aaaa"); +assertEq(values.next().value.valueOf(), NaN); +assertEq(values.next().done, true); + +// Make sure expandos aren't cloned (Bug 1041172) +set = new Set(); +set.a = "aaaaa"; +magic = deserialize(serialize(set)); +assertEq("a" in magic, false); +assertEq(Object.keys(magic).length, 0); + +// Busted [[Prototype]] shouldn't matter +set = new Set(); +Object.setPrototypeOf(set, null); +Set.prototype.add.call(set, "aaa"); +magic = deserialize(serialize(set)); +assertEq(magic.has("aaa"), true); +assertEq(magic.size, 1); + +// Can't fuzz around with Set after it is cloned +obj = { + a: new Set(), + get b() { + obj.a.delete("test"); + return "invoked"; + } +} +obj.a.add("test"); +assertEq(obj.a.has("test"), true); +magic = deserialize(serialize(obj)); +assertEq(obj.a.has("test"), false); +assertEq(magic.a.size, 1); +assertEq([...magic.a.keys()].toString(), "test"); +assertEq(magic.b, "invoked");
\ No newline at end of file diff --git a/js/src/jit-test/tests/structured-clone/array-buffers.js b/js/src/jit-test/tests/structured-clone/array-buffers.js new file mode 100644 index 0000000000..fcb61f6eca --- /dev/null +++ b/js/src/jit-test/tests/structured-clone/array-buffers.js @@ -0,0 +1,80 @@ +// Tests for ArrayBuffer, TypedArray, and DataView encoding/decoding. + +var clonebuffer = serialize("dummy"); + +// ========= V2 ========= + +function testV2Int32Array() { + var buf = new Uint8Array([3,0,0,0,0,0,241,255,3,0,0,0,16,0,255,255,4,0,0,0,0,0,0,0,12,0,0,0,9,0,255,255,1,0,0,0,177,127,57,5,133,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0]); + clonebuffer.clonebuffer = buf.buffer; + var ta = deserialize(clonebuffer); + assertEq(ta instanceof Int32Array, true); + assertEq(ta.toString(), "1,87654321,-123"); +} +testV2Int32Array(); + +function testV2Float64Array() { + var buf = new Uint8Array([3,0,0,0,0,0,241,255,4,0,0,0,16,0,255,255,7,0,0,0,0,0,0,0,32,0,0,0,9,0,255,255,0,0,0,0,0,0,248,127,31,133,235,81,184,30,9,64,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]); + clonebuffer.clonebuffer = buf.buffer; + var ta = deserialize(clonebuffer); + assertEq(ta instanceof Float64Array, true); + assertEq(ta.toString(), "NaN,3.14,0,0"); +} +testV2Float64Array(); + +function testV2DataView() { + var buf = new Uint8Array([3,0,0,0,0,0,241,255,3,0,0,0,21,0,255,255,3,0,0,0,9,0,255,255,5,0,255,0,0,0,0,0,0,0,0,0,0,0,0,0]); + clonebuffer.clonebuffer = buf.buffer; + var dv = deserialize(clonebuffer); + assertEq(dv instanceof DataView, true); + assertEq(new Uint8Array(dv.buffer).toString(), "5,0,255"); +} +testV2DataView(); + +function testV2ArrayBuffer() { + var buf = new Uint8Array([3,0,0,0,0,0,241,255,4,0,0,0,9,0,255,255,33,44,55,66,0,0,0,0]); + clonebuffer.clonebuffer = buf.buffer; + var ab = deserialize(clonebuffer); + assertEq(ab instanceof ArrayBuffer, true); + assertEq(new Uint8Array(ab).toString(), "33,44,55,66"); +} +testV2ArrayBuffer(); + +// ========= Current ========= + +function testInt32Array() { + var ta1 = new Int32Array([1, 87654321, -123]); + var clonebuf = serialize(ta1, undefined, {scope: "DifferentProcessForIndexedDB"}); + var ta2 = deserialize(clonebuf); + assertEq(ta2 instanceof Int32Array, true); + assertEq(ta2.toString(), "1,87654321,-123"); +} +testInt32Array(); + +function testFloat64Array() { + var ta1 = new Float64Array([NaN, 3.14, 0, 0]); + var clonebuf = serialize(ta1, undefined, {scope: "DifferentProcessForIndexedDB"}); + var ta2 = deserialize(clonebuf); + assertEq(ta2 instanceof Float64Array, true); + assertEq(ta2.toString(), "NaN,3.14,0,0"); +} +testFloat64Array(); + +function testDataView() { + var ta = new Uint8Array([5, 0, 255]); + var dv1 = new DataView(ta.buffer); + var clonebuf = serialize(dv1, undefined, {scope: "DifferentProcessForIndexedDB"}); + var dv2 = deserialize(clonebuf); + assertEq(dv2 instanceof DataView, true); + assertEq(new Uint8Array(dv2.buffer).toString(), "5,0,255"); +} +testDataView(); + +function testArrayBuffer() { + var ta = new Uint8Array([33, 44, 55, 66]); + var clonebuf = serialize(ta.buffer, undefined, {scope: "DifferentProcessForIndexedDB"}); + var ab = deserialize(clonebuf); + assertEq(ab instanceof ArrayBuffer, true); + assertEq(new Uint8Array(ab).toString(), "33,44,55,66"); +} +testArrayBuffer(); diff --git a/js/src/jit-test/tests/structured-clone/bug1687243.js b/js/src/jit-test/tests/structured-clone/bug1687243.js new file mode 100644 index 0000000000..13b7b83a07 --- /dev/null +++ b/js/src/jit-test/tests/structured-clone/bug1687243.js @@ -0,0 +1,30 @@ +let invalidTypedArrays = [ + // Uint8Array with invalid length. + [3,0,0,0,0,0,241,255,0,0,0,0,32,0,255,255,3,0,0,0,0,0,0,255,0,0,0,0,31,0,255,255,3,0,0,0,0,0,0,0,1,2,3,0,0,0,0,0,0,0,0,0,0,0,0,0], + // Uint8Array with invalid byteOffset. + [3,0,0,0,0,0,241,255,0,0,0,0,32,0,255,255,3,0,0,0,0,0,0,0,0,0,0,0,31,0,255,255,3,0,0,0,0,0,0,0,1,2,3,0,0,0,0,0,0,0,0,0,0,0,0,1], +]; +let invalidDataViews = [ + // DataView with invalid length. + [3,0,0,0,0,0,241,255,0,0,0,0,33,0,255,255,3,0,0,0,0,0,0,255,0,0,0,0,31,0,255,255,3,0,0,0,0,0,0,0,1,2,3,0,0,0,0,0,0,0,0,0,0,0,0,0], + // DataView with invalid byteOffset. + [3,0,0,0,0,0,241,255,0,0,0,0,33,0,255,255,3,0,0,0,0,0,0,0,0,0,0,0,31,0,255,255,3,0,0,0,0,0,0,0,1,2,3,0,0,0,0,0,0,0,0,0,0,0,0,1], +]; +function checkError(data, message) { + let clonebuffer = serialize("dummy"); + let buf = new Uint8Array(data); + clonebuffer.clonebuffer = buf.buffer; + let ex = null; + try { + deserialize(clonebuffer); + } catch (e) { + ex = e; + } + assertEq(ex.toString().includes(message), true); +} +for (let data of invalidTypedArrays) { + checkError(data, "invalid typed array length or offset"); +} +for (let data of invalidDataViews) { + checkError(data, "invalid DataView length or offset"); +} diff --git a/js/src/jit-test/tests/structured-clone/roundtrip.js b/js/src/jit-test/tests/structured-clone/roundtrip.js new file mode 100644 index 0000000000..ef7732ea07 --- /dev/null +++ b/js/src/jit-test/tests/structured-clone/roundtrip.js @@ -0,0 +1,30 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +load(libdir + "asserts.js"); + +const objects = [ + {}, + {a: 1, b: 2}, + {0: 1, 1: 2}, + {0: 1, 1: 2, a: 1}, + {0: 1, 1: 2, a: 1, b: 2}, + {1000000: 0, 1000001: 1}, + {0: 0, 1: 0, 1000000: 0, 1000001: 1}, + + [], + [0, 1, 2], + [0, 15, 16], + [{a: 0, b: 0}, {b: 0, a: 0}], + [0, , , 1, 2], + [, 1], + [0,,], + [,,], +] + +for (const obj of objects) { + assertDeepEq(deserialize(serialize(obj)), obj); + assertDeepEq(deserialize(serialize(wrapWithProto(obj, null))), obj); +} diff --git a/js/src/jit-test/tests/structured-clone/sab-errMsg.js b/js/src/jit-test/tests/structured-clone/sab-errMsg.js new file mode 100644 index 0000000000..ea8c7de0fd --- /dev/null +++ b/js/src/jit-test/tests/structured-clone/sab-errMsg.js @@ -0,0 +1,26 @@ +// |jit-test| skip-if: !sharedMemoryEnabled() + +// Check the error mssage when the prefs for COOP/COEP are both enable or not. +var g = newGlobal(); +var ex; +const sab = new SharedArrayBuffer(); +try { + g.serialize(sab); +} catch (e) { + ex = e; +} +assertEq(ex.toString(), + `TypeError: The SharedArrayBuffer object cannot be serialized. The ` + + `Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy HTTP ` + + `headers will enable this in the future.`); + +var h = newGlobal({enableCoopAndCoep: true}); +try { + h.serialize(sab); +} catch (e) { + ex = e; +} +assertEq(ex.toString(), + `TypeError: The SharedArrayBuffer object cannot be serialized. The ` + + `Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy HTTP ` + + `headers can be used to enable this.`); diff --git a/js/src/jit-test/tests/structured-clone/saved-stack.js b/js/src/jit-test/tests/structured-clone/saved-stack.js new file mode 100644 index 0000000000..dd2d4a3240 --- /dev/null +++ b/js/src/jit-test/tests/structured-clone/saved-stack.js @@ -0,0 +1,37 @@ +// The following binary data was created with: +// JS_STRUCTURED_CLONE_VERSION = 8 +// +// ``` +// function f() { +// return saveStack(); +// } +// function g() { +// return f(); +// } +// +// let stack = g(); +// print(valueToSource(serialize(stack, undefined, {scope: "DifferentProcess"}).clonebuffer)) +// ``` + +function checkStack(stack) { + print(stack.toString()); + + assertEq(stack.functionDisplayName, "f"); + assertEq(stack.parent.functionDisplayName, "g"); + assertEq(stack.parent.parent.functionDisplayName, null); + assertEq(stack.parent.parent.parent, null); +} + +var clonebuffer = serialize("dummy"); +clonebuffer.clonebuffer = "\x02\x00\x00\x00\x00\x00\xF1\xFF\x18\x00\xFF\xFF\x16\x00\xFF\xFF \x00\x00\x80\x04\x00\xFF\xFF/home/tom/Desktop/saved-stack.js\x11\x00\x00\x00\x03\x00\xFF\xFF\t\x00\x00\x00\x03\x00\xFF\xFF\x01\x00\x00\x80\x04\x00\xFF\xFFf\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x18\x00\xFF\xFF\x16\x00\xFF\xFF \x00\x00\x80\x04\x00\xFF\xFF/home/tom/Desktop/saved-stack.js\x14\x00\x00\x00\x03\x00\xFF\xFF\t\x00\x00\x00\x03\x00\xFF\xFF\x01\x00\x00\x80\x04\x00\xFF\xFFg\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x18\x00\xFF\xFF\x16\x00\xFF\xFF \x00\x00\x80\x04\x00\xFF\xFF/home/tom/Desktop/saved-stack.js\x17\x00\x00\x00\x03\x00\xFF\xFF\r\x00\x00\x00\x03\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00\x00\x00\x13\x00\xFF\xFF\x00\x00\x00\x00\x13\x00\xFF\xFF\x00\x00\x00\x00\x13\x00\xFF\xFF"; +var stack = deserialize(clonebuffer); +checkStack(stack); + +function f() { + return saveStack(); +} +function g() { + return f(); +} +stack = deserialize(serialize(g())); +checkStack(stack); diff --git a/js/src/jit-test/tests/structured-clone/transferable-across-segments.js b/js/src/jit-test/tests/structured-clone/transferable-across-segments.js new file mode 100644 index 0000000000..9b31260ae7 --- /dev/null +++ b/js/src/jit-test/tests/structured-clone/transferable-across-segments.js @@ -0,0 +1,13 @@ +// Default capacity is 4096 bytes and each entry requires 24 bytes, so when +// the transferables list contains >170 entries, more than one segment is +// used, because 171 * 24 = 4104 and 4104 > 4096. + +const transferables = []; +for (let i = 0; i < 170 + 1; ++i) { + transferables.push(new ArrayBuffer(1)); +} + +// Just don't crash. +serialize([], transferables, { + scope: "DifferentProcess", +}); diff --git a/js/src/jit-test/tests/structured-clone/version3.js b/js/src/jit-test/tests/structured-clone/version3.js new file mode 100644 index 0000000000..c3b3041ad6 --- /dev/null +++ b/js/src/jit-test/tests/structured-clone/version3.js @@ -0,0 +1,13 @@ +// Created with JS_STRUCTURED_CLONE_VERSION = 3 +// var x = { +// "ab": 1, +// 12: 2, +// }; +// print(uneval(serialize(x).clonebuffer)); + +var clonebuffer = serialize("abc"); +clonebuffer.clonebuffer = "\x00\x00\x00\x00\b\x00\xFF\xFF\f\x00\x00\x00\x03\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00@\x02\x00\x00\x00\x04\x00\xFF\xFFa\x00b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xF0?\x00\x00\x00\x00\x00\x00\xFF\xFF" +var obj = deserialize(clonebuffer) +assertEq(obj.ab, 1); +assertEq(obj[12], 2); +assertEq(Object.keys(obj).toString(), "12,ab"); |