"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"
);
});