test_structuredcloneholder.js (3720B)
1 "use strict"; 2 3 const global = this; 4 5 add_task(async function test_structuredCloneHolder() { 6 let principal = Services.scriptSecurityManager.createContentPrincipal( 7 Services.io.newURI("http://example.com/"), 8 {} 9 ); 10 11 let sandbox = Cu.Sandbox(principal); 12 13 const obj = { foo: [{ bar: "baz" }] }; 14 15 let holder = new StructuredCloneHolder("", "", obj); 16 17 // Test same-compartment deserialization 18 19 let res = holder.deserialize(global, true); 20 21 notEqual( 22 res, 23 obj, 24 "Deserialized result is a different object from the original" 25 ); 26 27 deepEqual( 28 res, 29 obj, 30 "Deserialized result is deeply equivalent to the original" 31 ); 32 33 equal( 34 Cu.getObjectPrincipal(res), 35 Cu.getObjectPrincipal(global), 36 "Deserialized result has the correct principal" 37 ); 38 39 // Test non-object-value round-trip. 40 41 equal( 42 new StructuredCloneHolder("", "", "foo").deserialize(global), 43 "foo", 44 "Round-tripping non-object values works as expected" 45 ); 46 47 // Test cross-compartment deserialization 48 49 res = holder.deserialize(sandbox, true); 50 51 notEqual( 52 res, 53 obj, 54 "Cross-compartment-deserialized result is a different object from the original" 55 ); 56 57 deepEqual( 58 res, 59 obj, 60 "Cross-compartment-deserialized result is deeply equivalent to the original" 61 ); 62 63 equal( 64 Cu.getObjectPrincipal(res), 65 principal, 66 "Cross-compartment-deserialized result has the correct principal" 67 ); 68 69 // Test message manager transportability 70 71 const MSG = "StructuredCloneHolder"; 72 73 let resultPromise = new Promise(resolve => { 74 Services.ppmm.addMessageListener(MSG, resolve); 75 }); 76 77 Services.cpmm.sendAsyncMessage(MSG, holder); 78 79 res = await resultPromise; 80 81 ok( 82 StructuredCloneHolder.isInstance(res.data), 83 "Sending structured clone holders through message managers works as expected" 84 ); 85 86 deepEqual( 87 res.data.deserialize(global, true), 88 obj, 89 "Sending structured clone holders through message managers works as expected" 90 ); 91 92 // Test that attempting to deserialize a neutered holder throws. 93 94 deepEqual( 95 holder.deserialize(global), 96 obj, 97 "Deserialized result is correct when discarding data" 98 ); 99 100 Assert.throws( 101 () => holder.deserialize(global), 102 err => err.result == Cr.NS_ERROR_NOT_INITIALIZED, 103 "Attempting to deserialize neutered holder throws" 104 ); 105 106 Assert.throws( 107 () => holder.deserialize(global, true), 108 err => err.result == Cr.NS_ERROR_NOT_INITIALIZED, 109 "Attempting to deserialize neutered holder throws" 110 ); 111 }); 112 113 // Test that X-rays passed to an exported function are serialized 114 // through their exported wrappers. 115 add_task(async function test_structuredCloneHolder_xray() { 116 let principal = Services.scriptSecurityManager.createContentPrincipal( 117 Services.io.newURI("http://example.com/"), 118 {} 119 ); 120 121 let sandbox1 = Cu.Sandbox(principal, { wantXrays: true }); 122 123 let sandbox2 = Cu.Sandbox(principal, { wantXrays: true }); 124 Cu.evalInSandbox(`this.x = {y: "z", get z() { return "q" }}`, sandbox2); 125 126 sandbox1.x = sandbox2.x; 127 128 let holder; 129 Cu.exportFunction( 130 function serialize(val) { 131 holder = new StructuredCloneHolder("", "", val, sandbox1); 132 }, 133 sandbox1, 134 { defineAs: "serialize" } 135 ); 136 137 Cu.evalInSandbox(`serialize(x)`, sandbox1); 138 139 const obj = { y: "z" }; 140 141 let res = holder.deserialize(global); 142 143 deepEqual( 144 res, 145 obj, 146 "Deserialized result is deeply equivalent to the expected object" 147 ); 148 deepEqual( 149 res, 150 sandbox2.x, 151 "Deserialized result is deeply equivalent to the X-ray-wrapped object" 152 ); 153 154 equal( 155 Cu.getObjectPrincipal(res), 156 Cu.getObjectPrincipal(global), 157 "Deserialized result has the correct principal" 158 ); 159 });