test_cloneInto.xhtml (5882B)
1 <?xml version="1.0"?> 2 <?xml-stylesheet type="text/css" href="chrome://global/skin"?> 3 <?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> 4 <window title="Mozilla Bug 503926" 5 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> 6 <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> 7 8 <!-- test results are displayed in the html:body --> 9 <body xmlns="http://www.w3.org/1999/xhtml"> 10 <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=964293" 11 target="_blank">Cu.cloneInto()</a> 12 </body> 13 14 <!-- test code goes here --> 15 <script type="application/javascript"> 16 <![CDATA[ 17 18 const TypedArrayThings = [ 19 'Int8Array', 20 'Uint8Array', 21 'Uint8ClampedArray', 22 'Int16Array', 23 'Uint16Array', 24 'Int32Array', 25 'Uint32Array', 26 'Float32Array', 27 'Float64Array', 28 ]; 29 30 function checkThrows(f, msg, rgxp) { 31 try { 32 f(); 33 ok(false, "Should have thrown: " + msg); 34 } catch (e) { 35 ok(true, "Threw correctly - " + msg + " - " + e); 36 if (rgxp) 37 ok(rgxp.test(e), "Should throw correct exception: " + e); 38 } 39 } 40 41 function getType(a) { 42 if (a === null || a === undefined) 43 return 'null'; 44 45 if (Array.isArray(a)) 46 return 'array'; 47 48 if (File.isInstance(a)) 49 return 'file'; 50 51 if (Blob.isInstance(a)) 52 return 'blob'; 53 54 if (TypedArrayThings.includes(a.constructor.name)) 55 return a.constructor.name; 56 57 if (typeof a == 'object') 58 return 'object'; 59 60 if (typeof a == 'function') 61 return 'function'; 62 63 return 'primitive'; 64 } 65 66 function compare(a, b) { 67 is (getType(a), getType(b), 'Type matches'); 68 69 var type = getType(a); 70 if (type == 'array') { 71 is (a.length, b.length, 'Array.length matches'); 72 for (var i = 0; i < a.length; ++i) { 73 compare(a[i], b[i]); 74 } 75 76 return; 77 } 78 79 if (type == 'file' || type == 'blob') { 80 ok ( a === b, 'They should match'); 81 return; 82 } 83 84 if (type == 'object') { 85 ok ( a !== b, 'They should not match'); 86 87 var aProps = []; 88 for (let p in a) aProps.push(p); 89 90 var bProps = []; 91 for (let p in b) bProps.push(p); 92 93 is (aProps.length, bProps.length, 'Props match'); 94 is (aProps.sort().toString(), bProps.sort().toString(), 'Props names match'); 95 96 for (let p in a) { 97 compare(a[p], b[p]); 98 } 99 100 return; 101 } 102 103 if (type == 'function') { 104 ok ( a !== b, 'They should not match'); 105 return; 106 } 107 108 if (type != 'null') { 109 is (a, b, 'Same value'); 110 } 111 } 112 113 var sandboxOptions = { 114 wantXrays: true, 115 wantExportHelpers: true, 116 }; 117 var sandbox = new Cu.Sandbox(window, sandboxOptions); 118 // The second sandbox is for testing the exportHelper version of the cloneInto 119 var sandbox2 = new Cu.Sandbox("https://example.com", sandboxOptions); 120 sandbox.sandbox2 = sandbox2; 121 sandbox2.sandbox = sandbox; 122 123 function cloneAndTest(test) { 124 var output = sandbox.test = Cu.cloneInto(test, sandbox); 125 compare(test, output); 126 127 output = Cu.evalInSandbox('cloneInto(test, sandbox2)', sandbox); 128 compare(test, output); 129 } 130 131 function cloneAndTestWithFunctions(test) { 132 var output = sandbox.test = Cu.cloneInto(test, sandbox, { cloneFunctions: true }); 133 compare(test, output); 134 135 output = Cu.evalInSandbox('cloneInto(test, sandbox2, { cloneFunctions: true })', sandbox); 136 // Note - We need to waive here, because functions are filtered out by object Xrays. 137 compare(test, Cu.waiveXrays(output)); 138 } 139 140 var tests = [ 141 1, 142 null, 143 true, 144 'hello world', 145 [1, 2, 3], 146 { a: 1, b: 2 }, 147 new Date(), 148 { a: 1, b: {}, c: [1, 2, 3, {} ], e: 'hello world' }, 149 ]; 150 151 for (var i = 0; i < tests.length; ++i) { 152 cloneAndTest(tests[i]); 153 } 154 155 checkThrows(function() { Cu.cloneInto({ a() {} }, sandbox); }, 156 'Function should not be cloned by default'); 157 158 checkThrows(function() { Cu.cloneInto({ a: document }, sandbox); }, 159 'Reflectors should not be wrapped by default'); 160 161 var withReflectors = Cu.cloneInto({ doc: document, win: window }, sandbox, 162 { wrapReflectors: true }); 163 is(Cu.unwaiveXrays(Cu.waiveXrays(withReflectors).doc), document, "Document passes"); 164 is(Cu.unwaiveXrays(Cu.waiveXrays(withReflectors).win), window, "Window passes"); 165 166 167 checkThrows(function() { Cu.evalInSandbox('cloneInto({}, sandbox)', sandbox2); }, 168 'CloneInto should only work on less privileged target scopes.', 169 /denied|insecure/); 170 171 var cloneTarget = new Cu.Sandbox("https://example.com"); 172 var sameOriginSB = new Cu.Sandbox("https://example.com", { wantGlobalProperties: ['XMLHttpRequest'] }); 173 var crossOriginSB = new Cu.Sandbox("https://example.net", { wantGlobalProperties: ['XMLHttpRequest'] }); 174 sandbox2.cloneTarget = cloneTarget; 175 sandbox2.soXHR = Cu.evalInSandbox('new XMLHttpRequest()', sameOriginSB); 176 sandbox2.xoXHR = Cu.evalInSandbox('new XMLHttpRequest()', crossOriginSB); 177 sandbox2.chromeDoc = document; 178 Cu.evalInSandbox('function tryToClone(x) { return cloneInto({val: x}, cloneTarget, { wrapReflectors: true }).val; }', sandbox2); 179 is(Cu.evalInSandbox('tryToClone(soXHR)', sandbox2), sandbox2.soXHR, 'Same-origin wrapReflectors works'); 180 checkThrows(function() { Cu.evalInSandbox('tryToClone(chromeDoc)', sandbox2); }, 181 'wrapReflectors may not wrap cross-origin reflectors', /unsupported value type/); 182 183 184 var test = { a() { return 42; } }; 185 cloneAndTestWithFunctions(test); 186 187 // Check that inputs are properly passed through cloned functions: 188 test = { a(obj) { return obj; } }; 189 var clonedTest = Cu.cloneInto(test, sandbox, {cloneFunctions: true}); 190 var testInput = {}; 191 is(clonedTest.a(testInput), testInput, "Objects should be identical"); 192 ]]> 193 </script> 194 </window>