summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/structured-clone
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /js/src/jit-test/tests/structured-clone
parentInitial commit. (diff)
downloadfirefox-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')
-rw-r--r--js/src/jit-test/tests/structured-clone/Map-Set-cross-compartment.js11
-rw-r--r--js/src/jit-test/tests/structured-clone/Map.js112
-rw-r--r--js/src/jit-test/tests/structured-clone/Set.js84
-rw-r--r--js/src/jit-test/tests/structured-clone/array-buffers.js80
-rw-r--r--js/src/jit-test/tests/structured-clone/bug1687243.js30
-rw-r--r--js/src/jit-test/tests/structured-clone/roundtrip.js30
-rw-r--r--js/src/jit-test/tests/structured-clone/sab-errMsg.js26
-rw-r--r--js/src/jit-test/tests/structured-clone/saved-stack.js37
-rw-r--r--js/src/jit-test/tests/structured-clone/transferable-across-segments.js13
-rw-r--r--js/src/jit-test/tests/structured-clone/version3.js13
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");