summaryrefslogtreecommitdiffstats
path: root/dom/base/test/unit/test_structuredcloneholder.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/base/test/unit/test_structuredcloneholder.js')
-rw-r--r--dom/base/test/unit/test_structuredcloneholder.js159
1 files changed, 159 insertions, 0 deletions
diff --git a/dom/base/test/unit/test_structuredcloneholder.js b/dom/base/test/unit/test_structuredcloneholder.js
new file mode 100644
index 0000000000..fd9afc7f03
--- /dev/null
+++ b/dom/base/test/unit/test_structuredcloneholder.js
@@ -0,0 +1,159 @@
+"use strict";
+
+const global = this;
+
+add_task(async function test_structuredCloneHolder() {
+ let principal = Services.scriptSecurityManager.createContentPrincipal(
+ Services.io.newURI("http://example.com/"),
+ {}
+ );
+
+ let sandbox = Cu.Sandbox(principal);
+
+ const obj = { foo: [{ bar: "baz" }] };
+
+ let holder = new StructuredCloneHolder("", "", obj);
+
+ // Test same-compartment deserialization
+
+ let res = holder.deserialize(global, true);
+
+ notEqual(
+ res,
+ obj,
+ "Deserialized result is a different object from the original"
+ );
+
+ deepEqual(
+ res,
+ obj,
+ "Deserialized result is deeply equivalent to the original"
+ );
+
+ equal(
+ Cu.getObjectPrincipal(res),
+ Cu.getObjectPrincipal(global),
+ "Deserialized result has the correct principal"
+ );
+
+ // Test non-object-value round-trip.
+
+ equal(
+ new StructuredCloneHolder("", "", "foo").deserialize(global),
+ "foo",
+ "Round-tripping non-object values works as expected"
+ );
+
+ // Test cross-compartment deserialization
+
+ res = holder.deserialize(sandbox, true);
+
+ notEqual(
+ res,
+ obj,
+ "Cross-compartment-deserialized result is a different object from the original"
+ );
+
+ deepEqual(
+ res,
+ obj,
+ "Cross-compartment-deserialized result is deeply equivalent to the original"
+ );
+
+ equal(
+ Cu.getObjectPrincipal(res),
+ principal,
+ "Cross-compartment-deserialized result has the correct principal"
+ );
+
+ // Test message manager transportability
+
+ const MSG = "StructuredCloneHolder";
+
+ let resultPromise = new Promise(resolve => {
+ Services.ppmm.addMessageListener(MSG, resolve);
+ });
+
+ Services.cpmm.sendAsyncMessage(MSG, holder);
+
+ res = await resultPromise;
+
+ ok(
+ StructuredCloneHolder.isInstance(res.data),
+ "Sending structured clone holders through message managers works as expected"
+ );
+
+ deepEqual(
+ res.data.deserialize(global, true),
+ obj,
+ "Sending structured clone holders through message managers works as expected"
+ );
+
+ // Test that attempting to deserialize a neutered holder throws.
+
+ deepEqual(
+ holder.deserialize(global),
+ obj,
+ "Deserialized result is correct when discarding data"
+ );
+
+ Assert.throws(
+ () => holder.deserialize(global),
+ err => err.result == Cr.NS_ERROR_NOT_INITIALIZED,
+ "Attempting to deserialize neutered holder throws"
+ );
+
+ Assert.throws(
+ () => holder.deserialize(global, true),
+ err => err.result == Cr.NS_ERROR_NOT_INITIALIZED,
+ "Attempting to deserialize neutered holder throws"
+ );
+});
+
+// Test that X-rays passed to an exported function are serialized
+// through their exported wrappers.
+add_task(async function test_structuredCloneHolder_xray() {
+ let principal = Services.scriptSecurityManager.createContentPrincipal(
+ Services.io.newURI("http://example.com/"),
+ {}
+ );
+
+ let sandbox1 = Cu.Sandbox(principal, { wantXrays: true });
+
+ let sandbox2 = Cu.Sandbox(principal, { wantXrays: true });
+ Cu.evalInSandbox(`this.x = {y: "z", get z() { return "q" }}`, sandbox2);
+
+ sandbox1.x = sandbox2.x;
+
+ let holder;
+ Cu.exportFunction(
+ function serialize(val) {
+ holder = new StructuredCloneHolder("", "", val, sandbox1);
+ },
+ sandbox1,
+ { defineAs: "serialize" }
+ );
+
+ Cu.evalInSandbox(`serialize(x)`, sandbox1);
+
+ const obj = { y: "z" };
+
+ let res = holder.deserialize(global);
+
+ deepEqual(
+ res,
+ obj,
+ "Deserialized result is deeply equivalent to the expected object"
+ );
+ deepEqual(
+ res,
+ sandbox2.x,
+ "Deserialized result is deeply equivalent to the X-ray-wrapped object"
+ );
+
+ equal(
+ Cu.getObjectPrincipal(res),
+ Cu.getObjectPrincipal(global),
+ "Deserialized result has the correct principal"
+ );
+});