diff options
Diffstat (limited to '')
106 files changed, 6849 insertions, 0 deletions
diff --git a/js/xpconnect/tests/chrome/bug503926.xhtml b/js/xpconnect/tests/chrome/bug503926.xhtml new file mode 100644 index 0000000000..d62a6b575f --- /dev/null +++ b/js/xpconnect/tests/chrome/bug503926.xhtml @@ -0,0 +1,30 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=503926 +--> +<window title="Mozilla Bug 503926" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=503926" + target="_blank">Mozilla Bug 503926</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + var gWindowUtils = window.windowUtils; + var passed = false; + // eslint-disable-next-line mozilla/use-chromeutils-generateqi + var obj = { QueryInterface() { passed = true; } } + gWindowUtils.xpconnectArgument(obj); + var isDialog = location.hash != '#iframe'; + var outer = Cu.waiveXrays(isDialog ? window.arguments[0] : parent); + outer.ok(passed, "chrome/chrome test passed: " + (isDialog ? "dialog" : "iframe")); + if (isDialog) + close(); + ]]> + </script> +</window> diff --git a/js/xpconnect/tests/chrome/chrome.ini b/js/xpconnect/tests/chrome/chrome.ini new file mode 100644 index 0000000000..0057d6e193 --- /dev/null +++ b/js/xpconnect/tests/chrome/chrome.ini @@ -0,0 +1,128 @@ +[DEFAULT] +skip-if = os == 'android' +support-files = + bug503926.xhtml + file_bug484459.html + file_bug618176.xhtml + file_bug996069.html + file_bug1281071.html + file_discardSystemSource.html + file_empty.html + file_evalInSandbox.html + file_expandosharing.jsm + outoflinexulscript.js + subscript.js + utf8_subscript.js + worker_discardSystemSource.js + !/js/xpconnect/tests/mochitest/bug500931_helper.html + !/js/xpconnect/tests/mochitest/bug571849_helper.html + !/js/xpconnect/tests/mochitest/chrome_wrappers_helper.html + !/js/xpconnect/tests/mochitest/file_bug706301.html + !/js/xpconnect/tests/mochitest/file_bug738244.html + !/js/xpconnect/tests/mochitest/file_bug760131.html + !/js/xpconnect/tests/mochitest/file_bug795275.html + !/js/xpconnect/tests/mochitest/file_bug799348.html + !/js/xpconnect/tests/mochitest/file_bug860494.html + !/js/xpconnect/tests/mochitest/file_documentdomain.html + !/js/xpconnect/tests/mochitest/file_doublewrappedcompartments.html + !/js/xpconnect/tests/mochitest/file_empty.html + !/js/xpconnect/tests/mochitest/file_exnstack.html + !/js/xpconnect/tests/mochitest/file_expandosharing.html + !/js/xpconnect/tests/mochitest/file_nodelists.html + !/js/xpconnect/tests/mochitest/file_evalInSandbox.html + !/js/xpconnect/tests/mochitest/file_xrayic.html +prefs = + javascript.options.large_arraybuffers=true + javascript.options.experimental.enable_new_set_methods=false + +[test_APIExposer.xhtml] +[test_bug361111.xhtml] +[test_bug448587.xhtml] +[test_bug484459.xhtml] +skip-if = os == 'win' || os == 'mac' || (os == 'linux' && !debug) # bug 1131110, 1255284 +[test_bug500931.xhtml] +[test_bug503926.xhtml] +[test_bug533596.xhtml] +[test_bug571849.xhtml] +[test_bug610390.xhtml] +[test_bug614757.xhtml] +[test_bug616992.xhtml] +[test_bug618176.xhtml] +[test_bug654370.xhtml] +[test_bug658560.xhtml] +[test_bug658909.xhtml] +[test_bug664689.xhtml] +[test_bug679861.xhtml] +[test_bug706301.xhtml] +[test_bug726949.xhtml] +[test_bug732665.xhtml] +[test_bug738244.xhtml] +[test_bug743843.xhtml] +[test_bug760076.xhtml] +[test_bug760131.html] +[test_bug763343.xhtml] +[test_bug771429.xhtml] +[test_bug773962.xhtml] +[test_bug792280.xhtml] +[test_bug793433.xhtml] +[test_bug795275.xhtml] +[test_bug799348.xhtml] +[test_bug801241.xhtml] +[test_bug812415.xhtml] +[test_bug853283.xhtml] +[test_bug853571.xhtml] +[test_bug858101.xhtml] +[test_bug860494.xhtml] +[test_bug865948.xhtml] +[test_bug866823.xhtml] +[test_bug895340.xhtml] +[test_bug932906.xhtml] +allow_xul_xbl = true +[test_bug996069.xhtml] +[test_bug1041626.xhtml] +[test_bug1042436.xhtml] +[test_bug1065185.html] +[test_bug1074863.html] +[test_bug1092477.xhtml] +[test_bug1124898.html] +[test_bug1126911.html] +[test_bug1281071.xhtml] +[test_bug1390159.xhtml] +[test_bug1430164.html] +[test_bug1516237.html] +[test_chrometoSource.xhtml] +[test_cloneInto.xhtml] +[test_cows.xhtml] +[test_private_field_cows.xhtml] +[test_discardSystemSource.xhtml] +[test_documentdomain.xhtml] +[test_doublewrappedcompartments.xhtml] +[test_evalInSandbox.xhtml] +[test_evalInWindow.xhtml] +[test_exnstack.xhtml] +[test_expandosharing.xhtml] +[test_exposeInDerived.xhtml] +[test_inlineScripts.html] +[test_localstorage_with_nsEp.xhtml] +[test_matches.xhtml] +[test_nodelists.xhtml] +[test_nsScriptErrorWithStack.html] +[test_onGarbageCollection.html] +[test_precisegc.xhtml] +[test_sandboxImport.xhtml] +[test_secureContexts.html] +[test_scriptSettings.xhtml] +[test_scripterror.html] +[test_sharedChromeCompartment.html] +[test_weakmap_keys_preserved.xhtml] +[test_weakmap_keys_preserved2.xhtml] +[test_weakref.xhtml] +[test_windowProxyDeadWrapper.html] +[test_wrappers.xhtml] +[test_xrayic.xhtml] +[test_xrayLargeTypedArray.html] +skip-if = bits == 32 # Large ArrayBuffers not supported on 32-bit. +[test_xrayToJS.xhtml] +[test_bug1530146.html] +support-files = file_bug1530146.html file_bug1530146_inner.html +[test_envChain_event_handler.html] diff --git a/js/xpconnect/tests/chrome/file_bug1281071.html b/js/xpconnect/tests/chrome/file_bug1281071.html new file mode 100644 index 0000000000..2398ce4a57 --- /dev/null +++ b/js/xpconnect/tests/chrome/file_bug1281071.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<script> + function tryLocationGet() { + var desc = Object.getOwnPropertyDescriptor(window, "location"); + try { + desc.get.call(parent); + return "get succeeded"; + } catch (e) { + return e.message; + } + } +</script> + diff --git a/js/xpconnect/tests/chrome/file_bug1530146.html b/js/xpconnect/tests/chrome/file_bug1530146.html new file mode 100644 index 0000000000..5414ea407d --- /dev/null +++ b/js/xpconnect/tests/chrome/file_bug1530146.html @@ -0,0 +1,6 @@ +<!DOCTYPE html> +<script> + // eslint-disable-next-line no-self-assign + document.domain = document.domain; +</script> +<iframe></iframe> diff --git a/js/xpconnect/tests/chrome/file_bug1530146_inner.html b/js/xpconnect/tests/chrome/file_bug1530146_inner.html new file mode 100644 index 0000000000..db642cf81d --- /dev/null +++ b/js/xpconnect/tests/chrome/file_bug1530146_inner.html @@ -0,0 +1,4 @@ +<!DOCTYPE html> +<script> + var obj = { a: "hello" } +</script> diff --git a/js/xpconnect/tests/chrome/file_bug484459.html b/js/xpconnect/tests/chrome/file_bug484459.html new file mode 100644 index 0000000000..27be5463a2 --- /dev/null +++ b/js/xpconnect/tests/chrome/file_bug484459.html @@ -0,0 +1,10 @@ +<html> +<head> + <title>helper for bug 484459</title> +</head> +<body> + <script type="application/javascript"> + var x=3; + </script> +</body> +</html> diff --git a/js/xpconnect/tests/chrome/file_bug618176.xhtml b/js/xpconnect/tests/chrome/file_bug618176.xhtml new file mode 100644 index 0000000000..3aea153159 --- /dev/null +++ b/js/xpconnect/tests/chrome/file_bug618176.xhtml @@ -0,0 +1,48 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=618176 +--> +<window title="Mozilla Bug 618176" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + onload="start()"> + <label value="Mozilla Bug 618176"/> + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + /* global messageManager */ + const TEST_PAGE = Services.io.newURI( + "data:text/html,<script>var a=[1,2,3];</script>Hi" + ); + + const FRAME_SCRIPT = +"data:,addEventListener('pageshow', function() { sendAsyncMessage('test', content.wrappedJSObject.a) }, false);"; + // s/content.wrappedJSObject.a/[ 1, 2, 3]/ and the test passes + + function recvTest(m) { + var a = m.json; + window.arguments[0].is(a.length, 3, "array was serialized and deserialized"); + + messageManager.removeMessageListener("test", recvTest); + finish(); + } + + function start() { + messageManager.addMessageListener("test", recvTest); + messageManager.loadFrameScript(FRAME_SCRIPT, true); + let triggeringPrincipal = Services.scriptSecurityManager.getSystemPrincipal(); + setTimeout(function () { + document.getElementById("browser").loadURI(TEST_PAGE, {triggeringPrincipal}); + }, 0); + } + + function finish() { + window.arguments[0].setTimeout(function() { this.done(); }, 0); + window.close(); + } + + ]]></script> + + <browser id="browser" type="content" style="width: 200px; height: 200px;"/> +</window> diff --git a/js/xpconnect/tests/chrome/file_bug996069.html b/js/xpconnect/tests/chrome/file_bug996069.html new file mode 100644 index 0000000000..e4bed07806 --- /dev/null +++ b/js/xpconnect/tests/chrome/file_bug996069.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> +<head></head> +<body> + <script> + if (window.opener && window.opener.finishTest) { + window.opener.finishTest(); + } + </script> +</body> +</html> diff --git a/js/xpconnect/tests/chrome/file_discardSystemSource.html b/js/xpconnect/tests/chrome/file_discardSystemSource.html new file mode 100644 index 0000000000..5dc9e9e7ba --- /dev/null +++ b/js/xpconnect/tests/chrome/file_discardSystemSource.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html> +<head> +<script> + function canary() { + // eslint-disable-next-line no-unused-vars + var someBitOfSource = 42; + } + function inner() { + throw new Error("some error"); + } + function throwSomething() { + inner(); + } +</script> +</head> +<body onload="someBitOfSource = 42"> +</body> +</html> diff --git a/js/xpconnect/tests/chrome/file_empty.html b/js/xpconnect/tests/chrome/file_empty.html new file mode 100644 index 0000000000..b3bfe19c0b --- /dev/null +++ b/js/xpconnect/tests/chrome/file_empty.html @@ -0,0 +1,2 @@ +<!DOCTYPE html> +<html><head><title>test page</title></head><body>there is nothing to see</body></html> diff --git a/js/xpconnect/tests/chrome/file_evalInSandbox.html b/js/xpconnect/tests/chrome/file_evalInSandbox.html new file mode 100644 index 0000000000..fb58f2bb41 --- /dev/null +++ b/js/xpconnect/tests/chrome/file_evalInSandbox.html @@ -0,0 +1 @@ +<html><body><script>document.foo = 'bar';</script></body></html> diff --git a/js/xpconnect/tests/chrome/file_expandosharing.jsm b/js/xpconnect/tests/chrome/file_expandosharing.jsm new file mode 100644 index 0000000000..f680ae20a9 --- /dev/null +++ b/js/xpconnect/tests/chrome/file_expandosharing.jsm @@ -0,0 +1,12 @@ +var EXPORTED_SYMBOLS = ["checkFromJSM"]; + +function checkFromJSM(target, is_op) { + is_op(target.numProp, 42, "Number expando works"); + is_op(target.strProp, "foo", "String expando works"); + // If is_op is todo_is, target.objProp will be undefined. + try { + is_op(target.objProp.bar, "baz", "Object expando works"); + } catch (e) { + is_op(0, 1, "No object expando"); + } +} diff --git a/js/xpconnect/tests/chrome/moz.build b/js/xpconnect/tests/chrome/moz.build new file mode 100644 index 0000000000..d371d3051f --- /dev/null +++ b/js/xpconnect/tests/chrome/moz.build @@ -0,0 +1,12 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +MOCHITEST_CHROME_MANIFESTS += ["chrome.ini"] + +TEST_HARNESS_FILES.testing.mochitest.tests.js.xpconnect.tests.chrome += [ + "file_discardSystemSource.html", + "worker_discardSystemSource.js", +] diff --git a/js/xpconnect/tests/chrome/outoflinexulscript.js b/js/xpconnect/tests/chrome/outoflinexulscript.js new file mode 100644 index 0000000000..14b99048e9 --- /dev/null +++ b/js/xpconnect/tests/chrome/outoflinexulscript.js @@ -0,0 +1,5 @@ +// Some unicode characters that must be decoded: +// ……………………………………………………………………………………………………………………………… +function outoflinefunction() { + return 42; +} diff --git a/js/xpconnect/tests/chrome/subscript.js b/js/xpconnect/tests/chrome/subscript.js new file mode 100644 index 0000000000..c2708f6e9b --- /dev/null +++ b/js/xpconnect/tests/chrome/subscript.js @@ -0,0 +1,4 @@ +/* global base */ +var ns = {}; +Services.scriptloader.loadSubScript(base + "file_expandosharing.jsm", ns); +var checkFromJSM = ns.checkFromJSM; diff --git a/js/xpconnect/tests/chrome/test_APIExposer.xhtml b/js/xpconnect/tests/chrome/test_APIExposer.xhtml new file mode 100644 index 0000000000..b327abe44d --- /dev/null +++ b/js/xpconnect/tests/chrome/test_APIExposer.xhtml @@ -0,0 +1,48 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=634156 +--> +<window title="Testing API exposing capabilities" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=634156" + target="_blank">Mozilla Bug 634156</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + var sandbox = new Cu.Sandbox("about:blank"); + sandbox.ok = ok; + sandbox.is = is; + Cu.evalInSandbox("Object.defineProperty(Object.prototype, 'getProp', { get: function() { throw 'FAIL: called getter' }, set: function() { throw 'FAIL: called setter'; } })", sandbox); + + var obj = Cu.createObjectIn(sandbox); + is(obj, Cu.waiveXrays(obj), "createObjectIn waives"); + is(Object.getPrototypeOf(obj), Cu.waiveXrays(Cu.evalInSandbox("Object.prototype", sandbox)), + "Object is a sandbox object"); + + function genPropDesc(value) { + return { enumerable: true, configurable: true, writable: true, + value }; + } + const props = { + 'getProp': genPropDesc(function() { ok(true, "called prop that shadowed a getter"); }), + 'argument': genPropDesc(function(arg) { is(arg, 42, "can pass arguments through"); }), + 'returnval': genPropDesc(function() { return 42; }) + }; + Object.defineProperties(obj, props); + Cu.makeObjectPropsNormal(obj); + + sandbox.api = obj; + Cu.evalInSandbox("ok(Object.getPrototypeOf(api) === Object.prototype, 'we have the object we expected'); \ + api.getProp(); api.argument(42); is(api.returnval(), 42, 'return value was correct');\ + ok(typeof api.getProp === 'function', 'functions are functions');\ + ok(Object.getPrototypeOf(api.getProp) === Function.prototype, 'functions come from our scope');", sandbox); + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug1041626.xhtml b/js/xpconnect/tests/chrome/test_bug1041626.xhtml new file mode 100644 index 0000000000..61d7630838 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug1041626.xhtml @@ -0,0 +1,60 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1041626 +--> +<window title="Mozilla Bug 1041626" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1041626" + target="_blank">Mozilla Bug 1041626</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 1041626 **/ + SimpleTest.waitForExplicitFinish(); + function go() { + + // + // Location + // + + ok(Cu.isXrayWrapper(window[0].location), "Location is Xrayed"); + let xrayOwnProperties = Object.getOwnPropertyNames(window[0].location); + + let realOwnProperties = Object.getOwnPropertyNames(window[0].wrappedJSObject.location); + ok(realOwnProperties.length > 2); + + is(xrayOwnProperties.sort().toSource(), realOwnProperties.sort().toSource(), + "Xray enumerates location properties properly"); + + // + // Document + // + + ok(Cu.isXrayWrapper(window[0].document), "Document is Xrayed"); + xrayOwnProperties = Object.getOwnPropertyNames(window[0].document); + + realOwnProperties = Object.getOwnPropertyNames(window[0].wrappedJSObject.document); + ok(!!realOwnProperties.length); + + is(xrayOwnProperties.sort().toSource(), realOwnProperties.sort().toSource(), + "Xray enumerates document properties properly"); + + + + SimpleTest.finish(); + } + + + + ]]> + </script> + <iframe onload="go();" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug1042436.xhtml b/js/xpconnect/tests/chrome/test_bug1042436.xhtml new file mode 100644 index 0000000000..4c86839fd9 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug1042436.xhtml @@ -0,0 +1,54 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1042436 +--> +<window title="Mozilla Bug 1042436" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1042436" + target="_blank">Mozilla Bug 1042436</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 1042436 **/ + SimpleTest.waitForExplicitFinish(); + + var contentSb = Cu.Sandbox("https://www.example.com"); + var nonXrayableObj = contentSb.eval("new Map()[Symbol.iterator]()"); + nonXrayableObj.wrappedJSObject.someExpandoProperty = 42; + nonXrayableObj.wrappedJSObject.someOtherExpandoProperty = 52; + + + SimpleTest.expectConsoleMessages(function() { + // Create sandboxes in fresh compartments, because the warning state is + // stored per compartment. + var chromeSb1 = Cu.Sandbox(this, {freshCompartment: true}); + chromeSb1.nonXrayableObj = nonXrayableObj; + Cu.evalInSandbox(` + nonXrayableObj.someExpandoProperty; + nonXrayableObj.someOtherExpandoProperty; + `, chromeSb1); + + var chromeSb2 = Cu.Sandbox(this, {freshCompartment: true}); + var contentObjWithGetter = contentSb.eval('({ get getterProp() {return 42;}, valueProp: 42 })'); + is(contentObjWithGetter.wrappedJSObject.getterProp, 42, "Getter prop set up correctly"); + is(contentObjWithGetter.getterProp, undefined, "Xrays work right"); + is(contentObjWithGetter.valueProp, 42, "Getter prop set up correctly"); + chromeSb2.contentObjWithGetter = contentObjWithGetter; + Cu.evalInSandbox('contentObjWithGetter.getterProp; contentObjWithGetter.valueProp; contentObjWithGetter.getterProp;', + chromeSb2, "1.7", "https://phony.example.com/file.js", 99); + }, + [{ errorMessage: /property "someExpandoProperty" \(reason: object is not safely Xrayable/, sourceName: /test_bug1042436/, isWarning: true }, + { errorMessage: /property "getterProp" \(reason: property has accessor/, sourceName: /phony/, lineNumber: 99, isWarning: true } ], + SimpleTest.finish.bind(SimpleTest)); + + ]]> + </script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug1065185.html b/js/xpconnect/tests/chrome/test_bug1065185.html new file mode 100644 index 0000000000..bc5b6027f2 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug1065185.html @@ -0,0 +1,64 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1065185 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1065185</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://global/skin"/> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 1065185 **/ + SimpleTest.waitForExplicitFinish(); + + function doMonitor(rgxps) { + var messages = rgxps.map((x) => ({ errorMessage: x, isWarning: true })); + info("Expecting console messages: " + messages.toSource()); + SimpleTest.monitorConsole(() => SimpleTest.executeSoon(() => window[0].location.reload()), messages, /* forbidUnexpected = */ true); + } + function endMonitor() { + SimpleTest.executeSoon(SimpleTest.endMonitorConsole.bind(SimpleTest)); + } + + var gLoadCount = 0; + function loaded() { + switch(gLoadCount++) { + case 0: + doMonitor([/access to property "a"/i]); + window[0].wrappedJSObject.probe = { a: 2 }; + is(window[0].eval('probe.a'), undefined, "Accessed exposed prop"); + endMonitor(); + break; + case 1: + doMonitor([/access to property "a"/i]); + window[0].wrappedJSObject.probe = { a: 2 }; + is(window[0].eval('probe.a'), undefined, "Non-exposed prop undefined"); + is(window[0].eval('probe.a'), undefined, "Non-exposed prop undefined again"); + endMonitor(); + break; + case 2: + SimpleTest.finish(); + break; + default: + ok(false, "Unexpected load"); + SimpleTest.finish(); + break; + } + } + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1065185">Mozilla Bug 1065185</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +<iframe onload="loaded();" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" /> +</body> +</html> diff --git a/js/xpconnect/tests/chrome/test_bug1074863.html b/js/xpconnect/tests/chrome/test_bug1074863.html new file mode 100644 index 0000000000..2fbe69a547 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug1074863.html @@ -0,0 +1,31 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1074863 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1074863</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://global/skin"/> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 1074863 **/ + var sb = new Cu.Sandbox("https://www.example.com"); + sb.namedCtor = Image; + ok(true, "Didn't assert"); + + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1074863">Mozilla Bug 1074863</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/js/xpconnect/tests/chrome/test_bug1092477.xhtml b/js/xpconnect/tests/chrome/test_bug1092477.xhtml new file mode 100644 index 0000000000..d79cd6604d --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug1092477.xhtml @@ -0,0 +1,33 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1092477 +--> +<window title="Mozilla Bug 1092477" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1092477" + target="_blank">Mozilla Bug 1092477</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + +var exn; +var url = "resource://non-existent/script.js"; +try { + Services.scriptloader.loadSubScript(url); + ok(false, "This line should never be reached!"); +} +catch (e) { + exn = String(e); +} +var msg = "loadSubScript should throw an exception for trying to load a non-existent script" +is(exn, "Error opening input stream (invalid filename?): " + url, msg); + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug1124898.html b/js/xpconnect/tests/chrome/test_bug1124898.html new file mode 100644 index 0000000000..0b6c2b7451 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug1124898.html @@ -0,0 +1,52 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1124898 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1124898</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://global/skin"/> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 1124898 **/ + SimpleTest.waitForExplicitFinish(); + (async () => { + await SpecialPowers.pushPrefEnv({"set": [["security.allow_eval_with_system_principal", true]]}); + + SimpleTest.expectAssertions(0, 1); // Dumb unrelated widget assertion - see bug 1126023. + + var w = window.browsingContext.topChromeWindow.open("about:blank", "w", "chrome"); + is(w.eval('typeof getAttention'), 'function', 'getAttention exists on regular chrome window'); + is(w.eval('typeof messageManager'), 'object', 'messageManager exists on regular chrome window'); + var contentURL = "https://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html"; + w.location = contentURL; + tryWindow(); + + function tryWindow() { + if (w.document.title != 'empty test page') { + info("Document not loaded yet - retrying"); + SimpleTest.executeSoon(tryWindow); + return; + } + is(w.eval('typeof getAttention'), 'undefined', 'getAttention doesnt exist on content-in-chrome window'); + is(w.eval('typeof messageManager'), 'undefined', 'messageManager doesnt exist on content-in-chrome window'); + w.close(); + SimpleTest.finish(); + } + })(); + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1124898">Mozilla Bug 1124898</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/js/xpconnect/tests/chrome/test_bug1126911.html b/js/xpconnect/tests/chrome/test_bug1126911.html new file mode 100644 index 0000000000..bbb2a00f54 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug1126911.html @@ -0,0 +1,40 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1126911 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1126911</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://global/skin"/> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 1126911 **/ + var sb = new Cu.Sandbox(null); + sb.win = window; + sb.loc = location; + function checkThrows(expr) { + try { + Cu.evalInSandbox(expr, sb); + ok(false, "Should have thrown: " + expr); + } catch (e) { + ok(/denied|insecure/.test(e), "should get security exception: " + e); + } + } + checkThrows('win.top'); + checkThrows('loc.replace'); + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1126911">Mozilla Bug 1126911</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/js/xpconnect/tests/chrome/test_bug1281071.xhtml b/js/xpconnect/tests/chrome/test_bug1281071.xhtml new file mode 100644 index 0000000000..e1ab036d55 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug1281071.xhtml @@ -0,0 +1,32 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1281071 +--> +<window title="Mozilla Bug 1281071" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + SimpleTest.waitForExplicitFinish(); + function go() { + var w = $('ifr').contentWindow.wrappedJSObject; + is(w.tryLocationGet(), "Permission to call 'get location' denied.", + "Trying to get our location object should throw"); + SimpleTest.finish(); + } + ]]></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <iframe type="content" + src="http://mochi.test:8888/chrome/js/xpconnect/tests/chrome/file_bug1281071.html" + onload="go()" + id="ifr"> + </iframe> + </body> + +</window> diff --git a/js/xpconnect/tests/chrome/test_bug1390159.xhtml b/js/xpconnect/tests/chrome/test_bug1390159.xhtml new file mode 100644 index 0000000000..7d5b917a27 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug1390159.xhtml @@ -0,0 +1,44 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1390159 +--> +<window title="Mozilla Bug 1390159" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + function test() { + var xulRuntime = Services.appinfo; + + // Make sure it has an inSafeMode property. This is just an arbitrary + // readonly property. + var oldValue = xulRuntime.inSafeMode; + is(typeof oldValue, "boolean", "Expected an inSafeMode property"); + + // Changing a readonly property doesn't throw, but shouldn't change + // the value. + xulRuntime.inSafeMode = !oldValue; + is(xulRuntime.inSafeMode, oldValue, "Should not have modified prop"); + + // Adding a new property should throw. + let ex = null; + try { + xulRuntime.foobar = 1; + } catch (e) { + ex = e; + } + is(ex.toString().includes("Cannot modify"), true, "Expected an error"); + is(xulRuntime.foobar, undefined, "Property not defined"); + } + test(); + ]]></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + </body> + +</window> diff --git a/js/xpconnect/tests/chrome/test_bug1430164.html b/js/xpconnect/tests/chrome/test_bug1430164.html new file mode 100644 index 0000000000..609e662ad5 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug1430164.html @@ -0,0 +1,31 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1430164 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1430164</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://global/skin"/> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + /** Test for Bug 1430164 **/ + var s = new Cu.Sandbox(window, { sandboxPrototype: window } ); + var t; + var desc; + try { + t = Cu.evalInSandbox('Node === Node', s); + ok(t, "Object identity should be sane"); + + t = Cu.evalInSandbox('Node === this.Node', s); + ok(t, "Node should match this.Node in toplevel"); + + t = Cu.evalInSandbox('Node === window.Node', s); + ok(t, "Node should match window.Node"); + } catch (e) { + ok(false, "Should not get an exception: " + e); + } + </script> +</head> +</html> diff --git a/js/xpconnect/tests/chrome/test_bug1516237.html b/js/xpconnect/tests/chrome/test_bug1516237.html new file mode 100644 index 0000000000..e7b92461bf --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug1516237.html @@ -0,0 +1,50 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1516237 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1516237</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://global/skin"/> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + +/** Test for Bug 1516237 **/ +ChromeUtils.import("resource://testing-common/TestUtils.jsm"); + +function go() { + SimpleTest.waitForExplicitFinish(); + + var frame = $('subframe'); + frame.onload = null; + + // Get a CCW wrapping an Xray waiver wrapping a WindowProxy. + var w = frame.contentWindow; + var ccwToWaiver = w.wrappedJSObject; + ccwToWaiver.testProp = 1; + is(ccwToWaiver.testProp, 1, "Can set properties on content window"); + + // Load a chrome page in the content frame. This might create a realm in + // the current chrome compartment - in that case we nuke the CCW to the + // waiver. + frame.onload = function() { + is(Cu.getClassName(w.Math, /* unwrap = */ false), "Math", + "Window must be in same system compartment"); + ok(Cu.isDeadWrapper(ccwToWaiver), + "Nuked CCW to same-compartment window"); + SimpleTest.finish(); + }; + frame.src = "file_empty.html"; +} + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1516237">Mozilla Bug 1516237</a> + +<iframe id="subframe" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" onload="go()"></iframe> + +</body> +</html> diff --git a/js/xpconnect/tests/chrome/test_bug1530146.html b/js/xpconnect/tests/chrome/test_bug1530146.html new file mode 100644 index 0000000000..59be912027 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug1530146.html @@ -0,0 +1,58 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1530146 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1530146</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://global/skin"/> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + + /** Test for Bug 1530146 **/ + SimpleTest.waitForExplicitFinish(); + + addLoadEvent(setupTest); + + var sb; + + function setupTest() { + // Create a sandbox with an expanded principal for our iframe. + sb = new Cu.Sandbox([frames[0].document.nodePrincipal], + {sandboxPrototype: frames[0]}); + // Grab a waiver for the subframe in the sandbox to make sure the waiver + // stays alive. It would be nice if we could just use waiveXray in the + // sandbox: https://bugzilla.mozilla.org/show_bug.cgi?id=1531614 + Cu.evalInSandbox('this.waiver = document.querySelector("iframe").contentWindow.wrappedJSObject', + sb); + var ifr = frames[0].document.querySelector("iframe"); + ifr.onload = doTest; + ifr.src = "file_bug1530146_inner.html"; + } + +function doTest() { + // Create a new sandbox for the iframe's subframe + var sb2 = new Cu.Sandbox([frames[0][0].document.nodePrincipal], + {sandboxPrototype: frames[0][0]}); + // Reget the waiver; this is where things can go awry. + Cu.evalInSandbox('this.waiver = window.wrappedJSObject', sb2); + is(Cu.evalInSandbox("this.waiver.obj.a", sb2), "hello", + "Should get the right value and not crash"); + is(Cu.evalInSandbox("(new this.waiver.Image()).localName", sb2), "img", + "Should create an image and not crash"); + SimpleTest.finish(); + } + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1530146">Mozilla Bug 1530146</a> +<p id="display"></p> +<div id="content" style="display: none"> +<iframe src="http://mochi.test:8888/chrome/js/xpconnect/tests/chrome/file_bug1530146.html"></iframe> +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/js/xpconnect/tests/chrome/test_bug361111.xhtml b/js/xpconnect/tests/chrome/test_bug361111.xhtml new file mode 100644 index 0000000000..4f1f89cf86 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug361111.xhtml @@ -0,0 +1,33 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=361111 +--> +<window title="Mozilla Bug 361111" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=361111" + target="_blank">Mozilla Bug 361111</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + + /** Test for Bug 361111 **/ + window.onerror = null; + SimpleTest.waitForExplicitFinish(); + document.documentElement.setAttribute("onclick", "%"); + is(1, 1, "Good, setting a bogus onclick did not throw."); + + // Bonus test - make sure that flushPrefEnv is appropriately + // called at the end of the test. It would be nice if there were + // somewhere in the harness that this could live, but there isn't. + SpecialPowers.pushPrefEnv({set: [['testing.some_arbitrary_pref', true]]}, + function() { SimpleTest.finish(); }); + + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug448587.xhtml b/js/xpconnect/tests/chrome/test_bug448587.xhtml new file mode 100644 index 0000000000..cedab9ebbd --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug448587.xhtml @@ -0,0 +1,35 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=448587.xul +--> +<window title="Mozilla Bug 503926" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=448587" + target="_blank">Mozilla Bug 448587</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + + // Bonus test - collaborate with test_bug361111.xhtml to make sure that + // flushPrefEnv is appropriately called. + ok(!SpecialPowers.Services.prefs.prefHasUserValue('testing.some_arbitrary_pref'), + "Pref shouldn't carry over from previous test!"); + + + /** Test for Bug 448587 **/ + var sandbox = new Cu.Sandbox("about:blank"); + var fwrapper = Cu.evalInSandbox("function f() {} f", sandbox); + is(Cu.unwaiveXrays(Cu.waiveXrays(fwrapper).prototype), Cu.evalInSandbox("f.prototype", sandbox), + ".prototype visible through .wrappedJSObject"); + is(fwrapper.prototype, undefined, ".prototype invisible through Xrays"); + ]]> + </script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug484459.xhtml b/js/xpconnect/tests/chrome/test_bug484459.xhtml new file mode 100644 index 0000000000..59f2f4ea60 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug484459.xhtml @@ -0,0 +1,37 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=484459 +--> +<window title="Mozilla Bug 484459" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <iframe type="content" + src="./file_bug484459.html" + onload="go()" + id="ifr"> + </iframe> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + SimpleTest.waitForExplicitFinish(); + var url = "chrome://mochitests/content/chrome/js/xpconnect/tests/chrome/test_bug484459.xhtml"; + function go() { + var w = $('ifr').contentWindow.wrappedJSObject; + var sandbox = new Cu.Sandbox(w); + sandbox.__proto__ = w; + is(location.href, url, "location.href is set properly"); + ok(w.location.href.endsWith("file_bug484459.html"), + "contents of w.location are correct"); + is(Cu.evalInSandbox("x * 4", sandbox), 12, + "Unexpected return from the sandbox"); + SimpleTest.finish(); + } + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug500931.xhtml b/js/xpconnect/tests/chrome/test_bug500931.xhtml new file mode 100644 index 0000000000..68effb7342 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug500931.xhtml @@ -0,0 +1,40 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=500931 +--> +<window title="Mozilla Bug 500931" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=500931" + target="_blank">Mozilla Bug 500931</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + + /** Test for Bug 500931 **/ + + function go() { + var ifr = document.getElementById("ifr"); + var doc = ifr.contentDocument; + ok(Cu.isXrayWrapper(doc), "doc is an XrayWrapper"); + var weak = Cu.getWeakReference(doc); + ok(Cu.isXrayWrapper(weak.get()), "weak reference returns a wrapper"); + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + + ]]></script> + <iframe type="content" + src="http://example.org/tests/js/xpconnect/tests/mochitest/bug500931_helper.html" + onload="go()" + id="ifr"> + </iframe> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug503926.xhtml b/js/xpconnect/tests/chrome/test_bug503926.xhtml new file mode 100644 index 0000000000..cfe6315fd8 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug503926.xhtml @@ -0,0 +1,58 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=503926 +--> +<window title="Mozilla Bug 503926" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=503926" + target="_blank">Mozilla Bug 503926</a> + + <iframe id="ifr" type="content" onload="loaded()" src="bug503926.xhtml#iframe"/> + <iframe id="ifrContent" type="content" onload="loaded()" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html"/> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + + SimpleTest.expectAssertions(0, 1); + + var gLoadCount = 0; + function loaded() { + if (++gLoadCount == 2) + go(); + } + + /** Test for Bug 503926 **/ + function go() { + var gWindowUtils = window.windowUtils; + + // Try with a chrome object. + var passed = false; + // eslint-disable-next-line mozilla/use-chromeutils-generateqi + var obj = { QueryInterface() { passed = true; } }; + gWindowUtils.xpconnectArgument(obj); + ok(passed, "trusted QIs should be called"); + + // Try with a content object. + var contentWin = $('ifrContent').contentWindow.wrappedJSObject; + contentWin.passed = false; + var contentObj = contentWin.eval('({ QueryInterface: function() { passed = true; } })'); + gWindowUtils.xpconnectArgument(contentObj); + ok(!contentWin.passed, "untrusted QI should not be called"); + + // Try with a dialog. + window.browsingContext.topChromeWindow.openDialog("bug503926.xhtml", "chromeDialog", "modal", window); + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + ]]> + </script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug533596.xhtml b/js/xpconnect/tests/chrome/test_bug533596.xhtml new file mode 100644 index 0000000000..3c3e610e81 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug533596.xhtml @@ -0,0 +1,58 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=533596 +--> +<window title="Mozilla Bug 533596" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=533596" + target="_blank">Mozilla Bug 533596</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + + // XPCNativeWrapper is not defined globally in ESLint as it may be going away. + // See bug 1481337. + /* global XPCNativeWrapper */ + + /** Test for Bug 533596 **/ + + function go() { + try { XPCNativeWrapper.unwrap(); } catch (e) {} + try { XPCNativeWrapper.unwrap(0); } catch (e) {} + try { XPCNativeWrapper.unwrap(null); } catch (e) {} + + var o = {}; + is(o, XPCNativeWrapper.unwrap(o), "unwrap on a random object returns it"); + + var win = $('ifr').contentWindow; + var utils = window.windowUtils; + is(utils.getClassName(win), "Proxy", "win is a Proxy"); + ok("x" in XPCNativeWrapper.unwrap(win), "actually unwrapped"); + is(utils.getClassName(XPCNativeWrapper.unwrap(win)), "Proxy", + "unwrap on an Proxy returns the same object"); + is(utils.getClassName(XPCNativeWrapper.unwrap(new XPCNativeWrapper(win))), "Proxy", + "unwrap on an explicit NW works too"); + + ok(utils.getClassName(window) !== "XPCNativeWrapper", "window is not a native wrapper"); + ok(utils.getClassName(XPCNativeWrapper.unwrap(new XPCNativeWrapper(window))) !== "XPCSafeJSObjectWrapper", + "unwrapping a chrome object returns the object itself"); + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + + ]]></script> + <iframe type="content" + src="http://example.org/tests/js/xpconnect/tests/mochitest/bug500931_helper.html" + onload="go()" + id="ifr"> + </iframe> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug571849.xhtml b/js/xpconnect/tests/chrome/test_bug571849.xhtml new file mode 100644 index 0000000000..3e4f6d6cc1 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug571849.xhtml @@ -0,0 +1,44 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=500931 +--> +<window title="Mozilla Bug 500931" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=500931" + target="_blank">Mozilla Bug 500931</a> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + + /** Test for Bug 500931 **/ + + function go() { + var ifr = document.getElementById('ifr'); + var docnodes = ifr.contentDocument.body.childNodes; + var index, value; + for (let i of Object.entries(docnodes)) { + index = i[0]; + value = i[1]; + } + is(index, "0", "enumerated the 0th element"); + ok(Text.isInstance(value), "the 0th element was a text node"); + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + + ]]></script> + <iframe type="content" + src="http://example.org/tests/js/xpconnect/tests/mochitest/bug571849_helper.html" + onload="go()" + id="ifr"> + </iframe> + </body> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug610390.xhtml b/js/xpconnect/tests/chrome/test_bug610390.xhtml new file mode 100644 index 0000000000..e4d8a48477 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug610390.xhtml @@ -0,0 +1,32 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=610390 +--> +<window title="Mozilla Bug 610390" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <iframe type="content" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + src="data:text/html,<script>var x=3</script>" + onload="go()" + id="ifr"> + </iframe> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + SimpleTest.waitForExplicitFinish(); + + function go() { + var w = $('ifr').contentWindow; + is(w.wrappedJSObject, w.wrappedJSObject, "wrappedJSObject identity not maintained"); + SimpleTest.finish(); + } + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug614757.xhtml b/js/xpconnect/tests/chrome/test_bug614757.xhtml new file mode 100644 index 0000000000..34058e38a3 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug614757.xhtml @@ -0,0 +1,33 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=614757 +--> +<window title="Mozilla Bug 601803" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=614757" + target="_blank">Mozilla Bug 614757</a> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + + /** Test for Bug 614757 **/ + + function go() { + is($('ifr').contentDocument.wrappedJSObject.getElementsByTagName('body')[0].toString().indexOf('Xray'), + -1, "Properly deep wrap"); + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + + ]]></script> + <iframe type="content" src="http://mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_evalInSandbox.html" onload="go()" id="ifr" /> + </body> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug616992.xhtml b/js/xpconnect/tests/chrome/test_bug616992.xhtml new file mode 100644 index 0000000000..52a97cee3d --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug616992.xhtml @@ -0,0 +1,30 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=616992 +--> +<window title="Mozilla Bug 601803" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=616992" + target="_blank">Mozilla Bug 616992</a> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + + /** Test for Bug 616992 **/ + + var sandbox = new Cu.Sandbox(window); + sandbox.w = window; + var actual = Cu.evalInSandbox("Object.keys(w.NodeFilter)", sandbox).sort().toString(); + var expected = Object.keys(NodeFilter).sort().toString(); + is(actual, expected, "interface constants are visible inside sandboxes"); + + ]]></script> + </body> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug618176.xhtml b/js/xpconnect/tests/chrome/test_bug618176.xhtml new file mode 100644 index 0000000000..63e93c9b56 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug618176.xhtml @@ -0,0 +1,30 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=618176 +--> +<window title="Mozilla Bug 618176" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=618176" + target="_blank">Mozilla Bug 618176</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + SimpleTest.waitForExplicitFinish(); + + function done() { + SimpleTest.finish(); + } + + addLoadEvent(function() { + window.openDialog("file_bug618176.xhtml", "", "chrome,noopener", window); + }); + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug654370.xhtml b/js/xpconnect/tests/chrome/test_bug654370.xhtml new file mode 100644 index 0000000000..e1afc32e38 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug654370.xhtml @@ -0,0 +1,27 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=654370 +--> +<window title="Mozilla Bug 654370" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=654370" + target="_blank">Mozilla Bug 654370</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + +var sandbox = new Cu.Sandbox(window); +var script = "(function (obj, type) { return obj instanceof type; })"; +var instanceOf = Cu.evalInSandbox(script, sandbox, "1.8", "Test", 1); +ok(!instanceOf({}, Window), "instanceOf from the sandbox gets the right result"); + + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug658560.xhtml b/js/xpconnect/tests/chrome/test_bug658560.xhtml new file mode 100644 index 0000000000..78b623a828 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug658560.xhtml @@ -0,0 +1,38 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=658560 +--> +<window title="Mozilla Bug 658560" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=658560" + target="_blank">Mozilla Bug 658560</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + + SimpleTest.waitForExplicitFinish(); + function go() { + var win = $('ifr').contentWindow.wrappedJSObject; + let o = { prop: true }; + win.foo = o; + + is(win.foo, o, "should have === identity through a CrossOriginWrapper"); + SimpleTest.finish(); + } + + ]]></script> + + <iframe + src="http://example.org/tests/js/xpconnect/tests/mochitest/file_bug658560.html" + id="ifr" + type="content" + onload="go()" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug658909.xhtml b/js/xpconnect/tests/chrome/test_bug658909.xhtml new file mode 100644 index 0000000000..360b8045e2 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug658909.xhtml @@ -0,0 +1,92 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=658909 +--> +<window title="Mozilla Bug 658909" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=658909" + target="_blank">Mozilla Bug 658909</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for call/apply-ing Xray methods.**/ + SimpleTest.waitForExplicitFinish(); + + let gLoadCount = 0; + function frameLoaded() { + if (++gLoadCount == frames.length) + go(); + } + + function msg(a, b, testName) { + return "(" + a.name + ", " + b.name + "): " + testName; + } + + var testFunctions = { + testDocumentElement(a, b, name) { + var getter = Object.prototype.__lookupGetter__.call(a.document, 'documentElement'); + is(getter.call(b.document), b.document.documentElement, msg(a, b, name)); + }, + + testInvalidCall(a, b, name) { + var getter = Object.prototype.__lookupGetter__.call(a.document, 'documentElement'); + var threw = false; + try { getter.call(b.document.body); } catch (e) { threw = true; }; + ok(threw, msg(a, b, name)); + }, + + testStatus(a, b, name) { + var setter = Object.prototype.__lookupSetter__.call(a, 'status'); + is(b.status, "", "Empty status"); + setter.call(b, "foopy"); + is(b.status, "foopy", msg(a, b, name)); + b.status = ""; + }, + + testCreateElement(a, b, name) { + is(a.document.createElement.call(b.document, 'div').ownerDocument, b.document, msg(a, b, name)); + }, + + testWindowName(a, b, name) { + var getter = Object.prototype.__lookupGetter__.call(a, 'name'); + is(getter.call(b), b.name, msg(a, b, name)); + }, + + testCanvas(a, b, name) { + var canvasA = a.document.createElement('canvas'); + var canvasB = b.document.createElement('canvas'); + var contextA = canvasA.getContext('2d'); + var contextB = canvasB.getContext('2d'); + var getter = Object.prototype.__lookupGetter__.call(contextA, 'canvas'); + is(getter.call(contextB), canvasB, msg(a, b, name)); + } + }; + + function go() { + for (let i = 0; i < frames.length; ++i) + frames[i].name = 'frame' + i; + for (let i = 0; i < frames.length; ++i) { + for (let j = 0; j < frames.length; ++j) { + for (let k in testFunctions) + testFunctions[k](frames[i], frames[j], k); + } + } + + SimpleTest.finish(); + } + + + ]]> + </script> + <iframe id="frame1" onload="frameLoaded();" type="content" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" /> + <iframe id="frame2" onload="frameLoaded();" type="content" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" /> + <iframe id="frame3" onload="frameLoaded();" type="content" src="http://example.com/tests/js/xpconnect/tests/mochitest/file_empty.html" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug664689.xhtml b/js/xpconnect/tests/chrome/test_bug664689.xhtml new file mode 100644 index 0000000000..45a39b1be9 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug664689.xhtml @@ -0,0 +1,28 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=658560 +--> +<window title="Mozilla Bug 658560" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=658560" + target="_blank">Mozilla Bug 658560</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + + var sandbox = new Cu.Sandbox("about:blank"); + var contentObj = Cu.evalInSandbox("({ get foo() { return 42 } })", sandbox); + var propdesc = Object.getOwnPropertyDescriptor(Cu.waiveXrays(contentObj), "foo"); + is(typeof propdesc, "object", "got a property descriptor back"); + ok("get" in propdesc, "getter exists"); + + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug679861.xhtml b/js/xpconnect/tests/chrome/test_bug679861.xhtml new file mode 100644 index 0000000000..302b66c966 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug679861.xhtml @@ -0,0 +1,38 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=500931 +--> +<window title="Mozilla Bug 601803" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=601803" + target="_blank">Mozilla Bug 601803</a> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + + /** Test for Bug 601803 **/ + + function go() { + var doc = document.getElementById('ifr').contentDocument; + var list = doc.getElementsByTagName("body"); + var zeroAsString = "0"; + is(typeof list[zeroAsString], "object", + "can lookup nodelist items by string"); + is(typeof list[0], "object", + "can lookup nodelist items by integer after the lookup by string"); + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + + ]]></script> + <iframe type="content" src="about:blank" onload="go()" id="ifr" /> + </body> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug706301.xhtml b/js/xpconnect/tests/chrome/test_bug706301.xhtml new file mode 100644 index 0000000000..867f9222d2 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug706301.xhtml @@ -0,0 +1,52 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=706301 +--> +<window title="Mozilla Bug 706301" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=706301" + target="_blank">Mozilla Bug 706301</a> + <iframe id="ifr" src="http://mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_bug706301.html" onload="doTest();" /> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 706301 **/ + + SimpleTest.waitForExplicitFinish(); + + function getLengthInChrome(nodelist) { + + // Make sure the object is Xray wrapped. + is(nodelist, Cu.unwaiveXrays(nodelist), + "object passed from content to chrome should be Xray-wrapped."); + + // Perform the operation. + Object.getOwnPropertyDescriptor(nodelist, 'length'); + return !nodelist.length; + } + + function finishTestInChrome() { + SimpleTest.finish(); + } + + function doTest() { + + // Set up the callbacks for content. + $('ifr').contentWindow.wrappedJSObject.getLengthInChrome = getLengthInChrome; + $('ifr').contentWindow.wrappedJSObject.finishTestInChrome = finishTestInChrome; + $('ifr').contentWindow.wrappedJSObject.ok = ok; + + // Kick off the test. + $('ifr').contentWindow.postMessage({}, '*'); + } + ]]> + </script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug720619.xhtml b/js/xpconnect/tests/chrome/test_bug720619.xhtml new file mode 100644 index 0000000000..335218886b --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug720619.xhtml @@ -0,0 +1,46 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=720619 +--> +<window title="Mozilla Bug 720619" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=720619" + target="_blank">Mozilla Bug 720619</a> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + /** Test for Bug 720619 **/ + var obj = { + valueOf () { + return 42; + }, + toString () { + return 'str'; + } + }; + + var content = new Cu.Sandbox("about:blank"); + content.obj = obj; + + ok(Cu.evalInSandbox("obj + ''", content) == "[object Object]"); + ok(Cu.evalInSandbox("'' + obj", content) == "[object Object]"); + ok(isNaN(Cu.evalInSandbox("obj - 0", content))); + ok(Cu.evalInSandbox("String(obj)", content) == "[object Object]"); + + var chrome = new Cu.Sandbox(window); + chrome.obj = obj; + + ok(Cu.evalInSandbox("obj + ''", chrome) == "42"); + ok(Cu.evalInSandbox("'' + obj", chrome) == "42"); + ok(Cu.evalInSandbox("obj - 0", chrome) == 42); + ok(Cu.evalInSandbox("String(obj)", chrome) == "str"); + ]]></script> + </body> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug726949.xhtml b/js/xpconnect/tests/chrome/test_bug726949.xhtml new file mode 100644 index 0000000000..b02b200893 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug726949.xhtml @@ -0,0 +1,41 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=726949 +--> +<window title="Mozilla Bug 726949" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + style="display: block;"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=726949" + target="_blank">Mozilla Bug 726949</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 726949 **/ + var s = new Cu.Sandbox(window, { sandboxPrototype: window } ); + var t; + var desc; + try { + t = Cu.evalInSandbox('top', s); + is(t, window.top, "Should have gotten the right thing back"); + desc = Cu.evalInSandbox('Object.getOwnPropertyDescriptor(Object.getPrototypeOf(this), "Cu")', s); + isnot(desc, undefined, + "Should have an own 'Cu' property"); + is(desc.value, Cu, "Should have the right value"); + var loc = Cu.evalInSandbox('location', s); + is(loc.href, location.href, "Should have the right location"); + var display = Cu.evalInSandbox('getComputedStyle(document.documentElement, "").display', s); + is(display, "block", "Should be able to call getComputedStyle"); + } catch (e) { + ok(false, "Should not get an exception: " + e); + } + ]]> + </script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug732665.xhtml b/js/xpconnect/tests/chrome/test_bug732665.xhtml new file mode 100644 index 0000000000..0ffba66ebc --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug732665.xhtml @@ -0,0 +1,92 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=732665 +--> +<window title="Mozilla Bug 732665" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=732665" + target="_blank">Mozilla Bug 732665</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + +add_task(async () => { + await SpecialPowers.pushPrefEnv({"set": [["security.allow_eval_with_system_principal", + true]]}); + // + // Important! If this test starts failing after a tricky platform-y change, + // the stack quota numbers in XPCJSContext probably need twiddling. We want + // to maintain the invariants in this test (at least to some approximation) + // for security reasons. + // + + // Executes f() d steps from the probed native stack limit, and returns + // the number of steps to the recursion limit from the caller. + function nearNativeStackLimit(d, f) { + f = f || function() {}; + let failed = null; + function inner() { + try { + // eslint-disable-next-line no-eval + var stepsFromLimit = eval("inner()"); // Use eval to force a number of native stackframes to be created. + if (stepsFromLimit == d) { + try { + f(); + } catch(e) { + // If we didn't have enough stack space to call the (possibly + // trivial) test function above, we obviously can't expect to call + // into the test harness assertion code successfully. + failed = e; + } + } + return stepsFromLimit + 1; + } catch(e) { + // It would be nice to check here that the exception is actually an + // over-recursion here. But doing so would require toString()ing the + // exception, which we may not have the stack space to do. + return 0; + } + } + let result = inner(); + ok(!failed, `nearNativeStackLimit callback threw: ${failed}`); + return result; + } + + var contentSb = new Cu.Sandbox("https://www.example.com"); + var chromeSb = new Cu.Sandbox(window); + chromeSb.ok = contentSb.ok = ok; + Cu.evalInSandbox(nearNativeStackLimit.toSource(), chromeSb); + Cu.evalInSandbox(nearNativeStackLimit.toSource(), contentSb); + var chromeLimit = Cu.evalInSandbox("nearNativeStackLimit(0);", chromeSb); + var contentLimit = Cu.evalInSandbox("nearNativeStackLimit(0)", contentSb); + ok(chromeLimit >= contentLimit + 10, + "Chrome should be able to have at least 10 heavy frames more stack than content: " + chromeLimit + ", " + contentLimit); + + // Exhaust the stack space in content, and then make sure we can still get 10 + // heavy frames in chrome. + // + // Note that sometimes, if we pass |0| to nearNativeStackLimit, we can end up + // so close to the border in content that we can't even get ourselves together + // enough to make the cross-compartment call. So rather than exhausting the + // stack entirely and then checking for 10 chrome frames, we leave ourselves + // one frame's worth, and check for 11. + // + // If this assertion fails, the current work-around so far is to measure + // again the worst frame size, by using the JS Shell to run + // test_bug732665_meta.js . This script will output numbers to update + // XPCJSContext.cpp comment, as well as the kTrustedScriptBuffer constant. + contentSb.nnslChrome = chromeSb.nearNativeStackLimit; + var nestedLimit = Cu.evalInSandbox("nearNativeStackLimit(1, function() { nestedLimit = nnslChrome(0);}); nestedLimit;", contentSb); + ok(nestedLimit >= 11, "Chrome should be invokable from content script with an exhausted stack: " + nestedLimit); +}); + ]]> + </script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug732665_meta.js b/js/xpconnect/tests/chrome/test_bug732665_meta.js new file mode 100644 index 0000000000..92bf9066b3 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug732665_meta.js @@ -0,0 +1,34 @@ +/* globals stackPointerInfo */ + +var stackBottom = stackPointerInfo(); +var stackTop = stackBottom; + +function nearNativeStackLimit() { + function inner() { + try { + stackTop = stackPointerInfo(); + // eslint-disable-next-line no-eval + var stepsFromLimit = eval("inner()"); // Use eval to force a number of native stackframes to be created. + return stepsFromLimit + 1; + } catch (e) { + // It would be nice to check here that the exception is actually an + // over-recursion here. But doing so would require toString()ing the + // exception, which we may not have the stack space to do. + return 1; + } + } + return inner(); +} + +var nbFrames = nearNativeStackLimit(); +var frameSize = stackBottom - stackTop; +print( + "Max stack size:", + frameSize, + "bytes", + "\nMaximum number of frames:", + nbFrames, + "\nAverage frame size:", + Math.ceil(frameSize / nbFrames), + "bytes" +); diff --git a/js/xpconnect/tests/chrome/test_bug738244.xhtml b/js/xpconnect/tests/chrome/test_bug738244.xhtml new file mode 100644 index 0000000000..96d0d880e6 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug738244.xhtml @@ -0,0 +1,58 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=533596 +--> +<window title="Mozilla Bug 533596" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + + <iframe src="http://example.org/tests/js/xpconnect/tests/mochitest/file_bug738244.html" + onload="xrayTest(this)"> + </iframe> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + + SimpleTest.waitForExplicitFinish(); + + function xrayTest(ifr) { + var win = ifr.contentWindow; + var doc = ifr.contentDocument; + + doc.getElementById = 42; + is(doc.getElementById, 42, + "Native property cannot be shadowed on the xray"); + + is(doc.form1.name, "form1", + "Form elements cannot be found by name on the document through xray"); + + is(doc.form1.input1.name, "input1", + "Input element cannot be found by name on a form element through xray"); + + is(typeof doc.form1.appendChild, "function", + "Input element shadows native property with its name through xray"); + + is(win.frame1, undefined, + "IFrames should not be found by name on the window through xray"); + + is(win[0].name, "frame1", + "IFrames should be found by index on the window through xray"); + + win["1000"] = "foopy"; + ok(!("1000" in win), "Shouldn't be able to add indexed expandos to xray"); + + win["1000a"] = "foopy"; + ok("1000a" in win, "Should be able to add named expandos to xray"); + + SimpleTest.finish(); + } + + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug743843.xhtml b/js/xpconnect/tests/chrome/test_bug743843.xhtml new file mode 100644 index 0000000000..a80134ff9e --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug743843.xhtml @@ -0,0 +1,39 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=743843 +--> +<window title="Mozilla Bug 743843" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=743843" + target="_blank">Mozilla Bug 743843</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Components.Exception options objects. **/ + + // Note: We pass |window| as the 'data' field here because Components.Exception + // doesn't handle JS Objects here all that nicely. See bug 743121. + + // Test the old interface. + var e1 = Components.Exception('foo', Cr.NS_BINDING_ABORTED, null, window); + is(e1.result, Cr.NS_BINDING_ABORTED, "Result should get set properly"); + is(e1.data, window, "User data should get set properly"); + + // Test the options object. + var e2 = Components.Exception('foo', { result: Cr.NS_BINDING_ABORTED, + data: window, + foobar: 2 }); + is(e2.result, Cr.NS_BINDING_ABORTED, "Result should get set properly"); + is(e2.data.window, window, "User data should get set properly"); + + ]]> + </script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug760076.xhtml b/js/xpconnect/tests/chrome/test_bug760076.xhtml new file mode 100644 index 0000000000..9d56455024 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug760076.xhtml @@ -0,0 +1,49 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=760076 +--> +<window title="Mozilla Bug 760076" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=760076" + target="_blank">Mozilla Bug 760076</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for constructing COW-ed functions in content. **/ + + // This gets decompiled and run in the sandbox. + function sandboxCode() { + /* globals chromeFunction */ + try { + is(chromeFunction(), 42, "Should call successfully"); + } catch(e) { ok(false, "Shouldn't throw when calling"); } + + try { + ok(typeof (new chromeFunction()) !== 'undefined', + "Should construct successfully"); + } catch(e) { ok(false, "Shouldn't throw when constructing"); } + } + + // Set up the sandbox. + var sb = new Cu.Sandbox("https://www.example.com"); + + // Import the functions it needs. + sb.ok = ok; + sb.is = is; + sb.chromeFunction = function() { ok(true, "Called chrome function"); return 42; } + Cu.evalInSandbox(sandboxCode.toSource(), sb); + + // Do the test. + Cu.evalInSandbox("sandboxCode();", sb); + + ]]> + </script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug760131.html b/js/xpconnect/tests/chrome/test_bug760131.html new file mode 100644 index 0000000000..eca4467c8d --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug760131.html @@ -0,0 +1,48 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=760131 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 760131</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=760131">Mozilla Bug 760131</a> +<p id="display"></p> +<div id="content" style="display: none"> + <iframe id="frame"></iframe> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 760131 **/ + +var frame = document.getElementById("frame"); +function runTest() +{ + var win = frame.contentWindow; + win.wrappedJSObject.ok = ok; + var doc = win.document; + var empty = doc.createTouchList(); + var event = doc.createEvent("touchevent"); + event.initTouchEvent("touchstart", true, true, win, 0, false, false, false, false, empty, empty, empty); + doc.getElementById("target").dispatchEvent(event); + + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); +SpecialPowers.pushPrefEnv( + {"set": [["dom.w3c_touch_events.legacy_apis.enabled", true]]}, + function() { + frame.onload = runTest; + frame.src = "http://mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_bug760131.html"; + } +); +</script> +</pre> +</body> +</html> diff --git a/js/xpconnect/tests/chrome/test_bug763343.xhtml b/js/xpconnect/tests/chrome/test_bug763343.xhtml new file mode 100644 index 0000000000..db3acd37c0 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug763343.xhtml @@ -0,0 +1,35 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=763343 +--> +<window title="Mozilla Bug 763343" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=763343" + target="_blank">Mozilla Bug 763343</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + + /** Test for Cross-compartment nsIClassInfo singleton wrapping. **/ + // We need an object here that has singleton classinfo. For now, the console + // service works. + var singleton = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIClassInfo); + ok(singleton.flags & Ci.nsIClassInfo.SINGLETON_CLASSINFO, + "Should have singleton classinfo"); + var sb = new Cu.Sandbox(window); + + // Don't crash. + sb.singleton = singleton; + ok(true, "didn't crash"); + + ]]> + </script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug771429.xhtml b/js/xpconnect/tests/chrome/test_bug771429.xhtml new file mode 100644 index 0000000000..c5846dd6ac --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug771429.xhtml @@ -0,0 +1,66 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=771429 +--> +<window title="Mozilla Bug 771429" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=771429" + target="_blank">Mozilla Bug 771429</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 771429 **/ + function f() {} + function g() { return this; } + function h() { "use strict"; return this; } + function ctor() { this.x = 1; } + f.x = 2; + f.g = g; + function test(freshCompartment) { + var s = new Cu.Sandbox(window, { + sandboxPrototype: window, + freshCompartment, + }); + try { + is(Cu.evalInSandbox('g()', s), window, + "Should get window as this object of non-strict global function"); + is(Cu.evalInSandbox('h()', s), undefined, + "Should get undefined as this object of strict global function"); + is(Cu.evalInSandbox('f.x', s), 2, + "Should have gotten the right thing back"); + if (freshCompartment) { + is(Cu.evalInSandbox('f.g()', s), f, + "Should have the right function object"); + } else { + // In the same-compartment case we don't go through a compartment + // boundary so when we call f.g() we don't unwrap the "callable + // proxy" around f and the test above fails. We accept this slight + // difference in behavior and assert a weaker invariant. + is(Cu.evalInSandbox('f.g()', s).toString(), f.toString(), + "Should have the right function object"); + } + is(Cu.evalInSandbox('var x = { z: 7 }; g.call(x).z', s), 7, + "Should not rebind calls that are already bound"); + // And test what happens when we use the normal Function.prototype.call + // on g instead of whatever our proxies happen to return. + is(Cu.evalInSandbox('var x = { z: 7 }; Function.prototype.call.call(g, x).z', s), 7, + "Should not rebind calls that are already bound"); + is(Cu.evalInSandbox('new ctor();', s).x, 1, + "Should get a properly constructed object out of the sandbox"); + } catch (e) { + ok(false, "Should not get an exception: " + e); + } + } + test(false); + test(true); + ]]> + </script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug773962.xhtml b/js/xpconnect/tests/chrome/test_bug773962.xhtml new file mode 100644 index 0000000000..2bdb43f6fc --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug773962.xhtml @@ -0,0 +1,88 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=773962 +--> +<window title="Mozilla Bug 773962" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=773962" + target="_blank">Mozilla Bug 773962</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + + /** Test for remapping Xray waivers during brain transplant. **/ + SimpleTest.waitForExplicitFinish(); + + var gFramesLoaded = 0; + function frameLoaded() { + ++gFramesLoaded; + if (gFramesLoaded == 2) + startTest(); + if (gFramesLoaded == 3) + finishTest(); + } + + var win1; + var win2; + var node1; + var loc1; + var win1Waiver; + var node1Waiver; + var loc1Waiver; + + function startTest() { + // grab the windows and the node. + win1 = document.getElementById('frame1').contentWindow; + win2 = document.getElementById('frame2').contentWindow; + node1 = win1.document.getElementById('text'); + loc1 = win1.location; + + // Grab some Xray waivers. + win1Waiver = win1.wrappedJSObject; + node1Waiver = node1.wrappedJSObject; + loc1Waiver = win1Waiver.location; + + // Adopt node1 into win2. This causes node1 to be transplanted. + win2.document.adoptNode(node1); + + // Navigate win1. This causes win1 to be transplanted. + win1.location = "https://test2.example.org/tests/js/xpconnect/tests/mochitest/file_empty.html"; + + // The above happens async. Our onload handler will call finishTest() when we're ready. + } + + function finishTest() { + // Now, recompute some wrappers. + Cu.recomputeWrappers(); + + // First, pat ourselves on the back for not asserting/crashing. That's most of + // what we're really testing here. + ok(true, "Didn't crash!"); + + // Now, make sure everything is set up how we expect. + ok(Cu.isDeadWrapper(win1Waiver), "window waiver should go away after navigation"); + ok(node1Waiver === node1.wrappedJSObject, "waivers still work"); + ok(Cu.unwaiveXrays(node1Waiver) === node1, "waivers still work"); + + // The semantics of location are tricky, because win1 now has a new location object. + // In fact, loc1 should be a dead object proxy. Let's make sure we get this right. + ok(loc1 !== win1.location, "navigation means different window.location"); + ok(loc1Waiver !== win1.location.wrappedJSObject, "navigation means different window.location"); + + // Whew. + SimpleTest.finish(); + } + + ]]> + </script> + <iframe id="frame1" onload="frameLoaded();" type="content" src="https://test1.example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" /> + <iframe id="frame2" onload="frameLoaded();" type="content" src="https://test1.example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug792280.xhtml b/js/xpconnect/tests/chrome/test_bug792280.xhtml new file mode 100644 index 0000000000..1e1a197e57 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug792280.xhtml @@ -0,0 +1,43 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=792280 +--> +<window title="Mozilla Bug 792280" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=792280" + target="_blank">Mozilla Bug 792280</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 792280 **/ + function checkSb(sb, expect) { + var target = new Cu.Sandbox("https://www.example.com"); + Cu.evalInSandbox('function fun() { return arguments.callee.caller; };', target); + sb.fun = target.fun; + let allowed = false; + try { + allowed = Cu.evalInSandbox('function doTest() { return fun() == doTest; }; doTest()', sb); + isnot(expect, "throw", "Should have thrown"); + } catch (e) { + is(expect, "throw", "Should expect exception"); + ok(/denied|insecure/.test(e), "Should be a security exception: " + e); + } + is(allowed, expect == "allow", "should censor appropriately"); + } + + // Note that COWs are callable, but XOWs are not. + checkSb(new Cu.Sandbox("https://www.example.com"), "allow"); + checkSb(new Cu.Sandbox("https://www.example.org"), "throw"); + checkSb(new Cu.Sandbox(window), "censor"); + + ]]> + </script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug793433.xhtml b/js/xpconnect/tests/chrome/test_bug793433.xhtml new file mode 100644 index 0000000000..eed7166efc --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug793433.xhtml @@ -0,0 +1,44 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=793433 +--> +<window title="Mozilla Bug 793433" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=793433" + target="_blank">Mozilla Bug 793433</a> + <p id="display"></p> + <div id="content" style="display: none"/> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + +function shouldThrow(fun, args, msg) { + try { + fun.apply(this, args); + ok(false, msg); + } catch (e) { + ok(true, msg+" -- "+e); + } +} + +function do_registerTopLevelWindow(win) { + Services.appShell.registerTopLevelWindow(win); +} + +shouldThrow( + do_registerTopLevelWindow, [null], + "registering null as a top-level window should throw"); + +shouldThrow( + do_registerTopLevelWindow, [{}], + "registering a void object as a top-level window should throw"); + + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug795275.xhtml b/js/xpconnect/tests/chrome/test_bug795275.xhtml new file mode 100644 index 0000000000..a151a1a2b7 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug795275.xhtml @@ -0,0 +1,80 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=795275 +--> +<window title="Mozilla Bug 795275" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=795275" + target="_blank">Mozilla Bug 795275</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Warning in content scopes about Components. **/ + + SimpleTest.waitForExplicitFinish(); + SimpleTest.executeSoon(function() { + SpecialPowers.pushPrefEnv({set: [["dom.use_components_shim", true]]}, + startLoad) + }); + function startLoad() { + for (var i = 1; i <= document.getElementsByTagName('iframe').length; ++i) { + var frame = document.getElementById('frame' + i); + frame.contentWindow.location = 'http://mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_bug795275.html'; + frame.onload = frameLoaded; + } + } + + // Set up our console listener. + var gWarnings = 0; + function onWarning(consoleMessage) { + if (/soon be removed/.test(consoleMessage.message)) + gWarnings++; + } + var gListener = { + observe: onWarning, + QueryInterface: ChromeUtils.generateQI(["nsIConsoleListener"]) + }; + Services.console.registerListener(gListener); + + // Wait for all four child frame to load. + var gLoadCount = 0; + function frameLoaded() { + if (++gLoadCount == document.getElementsByTagName('iframe').length) + go(); + } + + function getWin(id) { return document.getElementById(id).contentWindow.wrappedJSObject; } + function go() { + getWin('frame1').touchComponents(); + getWin('frame2').touchInterfaces(); + getWin('frame4').touchComponents(); + getWin('frame4').touchInterfaces(); + + // Warnings are dispatched async, so stick ourselves at the end of the event + // queue. + setTimeout(done, 0); + } + + function done() { + Services.console.unregisterListener(gListener); + is(gWarnings, 3, "Got the right number of warnings"); + SimpleTest.finish(); + } + + ]]> + + </script> + <iframe id="frame1"/> + <iframe id="frame2"/> + <iframe id="frame3"/> + <iframe id="frame4"/> + +</window> diff --git a/js/xpconnect/tests/chrome/test_bug799348.xhtml b/js/xpconnect/tests/chrome/test_bug799348.xhtml new file mode 100644 index 0000000000..91de48164f --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug799348.xhtml @@ -0,0 +1,47 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=799348 +--> +<window title="Mozilla Bug 799348" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=799348" + target="_blank">Mozilla Bug 799348</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 799348 **/ + SimpleTest.waitForExplicitFinish(); + var gCalledOnload = false; + var myObserver = { + QueryInterface: ChromeUtils.generateQI(["nsIObserver"]), + observe(win, topic, data) { + if (topic == "domwindowopened") { + ok(!gCalledOnload, "domwindowopened notification fired before onload"); + win.addEventListener("load", function(evt) { + gCalledOnload = true; + win.close(); + }); + } else if (topic == "domwindowclosed") { + ok(gCalledOnload, "should have called onload"); + Services.ww.unregisterNotification(myObserver); + SimpleTest.finish(); + } else { + ok(false, "unknown topic"); + } + } + }; + Services.ww.registerNotification(myObserver); + + + ]]> + </script> + <iframe id="frame" type="content" src="http://test1.example.org/tests/js/xpconnect/tests/mochitest/file_bug799348.html" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug801241.xhtml b/js/xpconnect/tests/chrome/test_bug801241.xhtml new file mode 100644 index 0000000000..5c83429afa --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug801241.xhtml @@ -0,0 +1,48 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=801241 +--> +<window title="Mozilla Bug 801241" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=801241" + target="_blank">Mozilla Bug 801241</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 801241 **/ + SimpleTest.waitForExplicitFinish(); + + /* globals win */ + + // This is decompiled and run inside the sandbox; + function sbCode() { + try { + // eslint-disable-next-line no-self-assign + win.location = win.location; + ok(true, "Didn't throw setting from location"); + } catch (e) { + ok(false, "Threw setting location from sandbox"); + } + } + + function go() { + document.getElementById('ifr').onload = null; + var sb = new Cu.Sandbox(this); + sb.win = document.getElementById('ifr').contentWindow; + sb.ok = ok; + Cu.evalInSandbox('(' + sbCode.toSource() + ')()', sb); + SimpleTest.finish(); + } + + ]]> + </script> + <iframe id="ifr" onload="go();" type="content" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug812415.xhtml b/js/xpconnect/tests/chrome/test_bug812415.xhtml new file mode 100644 index 0000000000..71dc23768e --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug812415.xhtml @@ -0,0 +1,90 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=812415 +--> +<window title="Mozilla Bug 812415" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=812415" + target="_blank">Mozilla Bug 812415</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 812415 and Bug 823348 **/ + + SimpleTest.waitForExplicitFinish(); + + function testWaiving(iwin, sb) { + sb.win = iwin; + is(Cu.evalInSandbox('win', sb), iwin, "Basic identity works"); + is(Cu.evalInSandbox('win.wrappedJSObject.expando', sb), 42, "Waivers work via .wrappedJSObject"); + is(Cu.evalInSandbox('XPCNativeWrapper.unwrap(win).expando', sb), 42, "Waivers work via XPCNativeWrapper.unwrap"); + is(Cu.evalInSandbox('win.wrappedJSObject.document.defaultView.expando', sb), 42, "Waivers are deep"); + } + + function checkThrows(expression, sb, msg) { + var result = Cu.evalInSandbox('(function() { try { ' + expression + '; return "allowed"; } catch (e) { return e.toString(); }})();', sb); + ok(!!/denied/.exec(result), msg); + } + + function testAsymmetric(regular, expanded) { + + // Set up objects. + expanded.regFun = Cu.evalInSandbox('function reg() { return 42; }; reg', regular); + expanded.regObj = Cu.evalInSandbox('new Object({foo: 2})', regular); + regular.expFun = Cu.evalInSandbox('function exp() { return 41; }; exp', expanded); + regular.expObj = Cu.evalInSandbox('new Object({bar: 3})', expanded); + + // Check objects. + is(Cu.evalInSandbox('regObj.foo', expanded), 2, "Expanded can see regular object prop"); + checkThrows('expObj.bar', regular, "Regular shouldn't read properties"); + Cu.evalInSandbox('regObj.foo = 20', expanded); + is(expanded.regObj.foo, 20, "Expanded can set properties"); + checkThrows('expFun.bar = 0', regular, "Regular shouldn't write properties"); + + // Check functions. + is(Cu.evalInSandbox('regFun()', expanded), 42, "Expanded can call regular function"); + checkThrows('expFun()', regular, "Regular cannot call expanded function"); + is(Cu.evalInSandbox('regFun.name', expanded), 'reg', "Expanded can see regular function's name"); + checkThrows('expFun.name', regular, "Regular can't see expanded function's name"); + Cu.evalInSandbox('regFun.expando = 30', expanded); + is(Cu.evalInSandbox('regFun.expando', expanded), 30, "Expanded can set expandos"); + checkThrows('expFun.expando = 29', regular, "Regular can't set expandos"); + + // Check __proto__ stuff. + is(Cu.evalInSandbox('regFun.__proto__', expanded), regular.Function.prototype, "expanded can get __proto__"); + checkThrows('expFun.__proto__', regular, "regular can't use __proto__"); + checkThrows('expFun.__proto__ = {}', regular, "regular can't mutate __proto__"); + } + + function go() { + var iwin = document.getElementById('ifr').contentWindow; + iwin.wrappedJSObject.expando = 42; + + // Make our sandboxes. We pass wantXrays=false for the nsEP to ensure that + // the Xrays we get are the result of being an nsEP, not from the wantXrays + // flag. + var regular = new Cu.Sandbox(iwin); + var expanded = new Cu.Sandbox([iwin], {wantXrays: false}); + + // Because of the crazy secret life of wantXrays, passing wantXrays=false + // has the side effect of waiving Xrays on the returned sandbox. Undo that. + expanded = Cu.unwaiveXrays(expanded); + + testWaiving(iwin, regular); + testWaiving(iwin, expanded); + testAsymmetric(regular, expanded); + SimpleTest.finish(); + } + + ]]> + </script> + <iframe id="ifr" onload="go();" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug853283.xhtml b/js/xpconnect/tests/chrome/test_bug853283.xhtml new file mode 100644 index 0000000000..6cdd5027b8 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug853283.xhtml @@ -0,0 +1,40 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=853283 +--> +<window title="Mozilla Bug 853283" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=853283" + target="_blank">Mozilla Bug 853283</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test nsNavigatorSH::Resolve in conjunction with Xrays.**/ + SimpleTest.waitForExplicitFinish(); + + function go() { + // This chrome document already has Xrays to the content scope, but we use a + // a sandbox anyway to make sure that the global in play here isn't an + // nsIDOMWindow. Otherwise, the resolve hook might just end up squeaking by + // with the chrome window. + var iwin = $('ifr').contentWindow; + var sb = new Cu.Sandbox(window); + sb.iwin = iwin; + sb.ok = ok; + Cu.evalInSandbox('try {iwin.navigator.mozContacts; ok(true, "Didnt throw"); } catch (e) { ok(false, "Threw: " + e);}', sb); + SimpleTest.finish(); + } + + + ]]> + </script> + <iframe id="ifr" onload="go();" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug853571.xhtml b/js/xpconnect/tests/chrome/test_bug853571.xhtml new file mode 100644 index 0000000000..2f16915666 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug853571.xhtml @@ -0,0 +1,62 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=853571 +--> +<window title="Mozilla Bug 853571" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=853571" + target="_blank">Mozilla Bug 853571</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 853571 **/ + SimpleTest.waitForExplicitFinish(); + + function* mainTest() { + var iwin = $('ifr').contentWindow; + + // Test with a simple sandbox with no prototype. + checkSource(iwin, new Cu.Sandbox(iwin), null, "should get null source with no sandboxPrototype"); + yield; + + // Test with a sandboxPrototype. + checkSource(iwin, new Cu.Sandbox(iwin, { sandboxPrototype: iwin }), iwin, "should be able to impersonate the prototype"); + yield; + + SimpleTest.finish(); + yield; // Prevent StopIteration from being thrown. + } + + var gen; + function runTest() { + gen = mainTest(); + gen.next(); + } + + function checkSource(target, sb, expectedSource, message) { + target.addEventListener("message", function listener(event) { + is(event.source, expectedSource, message); + let {done} = gen.next(); + if (done) { + // We're done. + } + }, + { once: true}); + + sb.target = target; + Cu.evalInSandbox("target.postMessage('foo', '*');", sb); + } + + + ]]> + </script> + <iframe id="ifr" type="content" onload="runTest()" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug858101.xhtml b/js/xpconnect/tests/chrome/test_bug858101.xhtml new file mode 100644 index 0000000000..5ff9f28dc7 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug858101.xhtml @@ -0,0 +1,55 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=858101 +--> +<window title="Mozilla Bug 858101" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=858101" + target="_blank">Mozilla Bug 858101</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + + /** Test for [[DefaultValue]] on XrayWrappers. **/ + SimpleTest.waitForExplicitFinish(); + + function muckWithToString() { + function tricky() { return "hah"; }; + + window.toString = document.toString = document.body.toString = tricky; + window.valueOf = document.valueOf = document.body.valueOf = tricky; + + Window.prototype.toString = Window.prototype.valueOf = tricky; + Document.prototype.toString = Document.prototype.valueOf = tricky; + HTMLBodyElement.toString = HTMLBodyElement.valueOf = tricky; + } + + function go() { + var iwin = $('ifr').contentWindow; + iwin.wrappedJSObject.eval('(' + muckWithToString.toSource() + ')()'); + + // Check behavior with vanilla CCWs. + ok(!!/hah/.exec(iwin.wrappedJSObject + ""), "Waivers should get content-defined window stringification"); + ok(!!/hah/.exec(iwin.document.wrappedJSObject + ""), "Waivers should get content-defined document stringification"); + ok(!!/hah/.exec(iwin.document.body.wrappedJSObject + ""), "Waivers should get content-defined body stringification"); + + // Check Xray behavior. + ok(!/hah/.exec(iwin + ""), "Xrays should not get content-defined window stringification"); + ok(!/hah/.exec(iwin.document + ""), "Xrays should not get content-defined document stringification"); + ok(!/hah/.exec(iwin.document.body + ""), "Xrays should not get content-defined body stringification"); + + SimpleTest.finish(); + } + + ]]> + </script> + <iframe id="ifr" onload="go();" type="content" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug860494.xhtml b/js/xpconnect/tests/chrome/test_bug860494.xhtml new file mode 100644 index 0000000000..26bd1e13bd --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug860494.xhtml @@ -0,0 +1,57 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=860494 +--> +<window title="Mozilla Bug 860494" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=860494" + target="_blank">Mozilla Bug 860494</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 860494 **/ + + SimpleTest.waitForExplicitFinish(); + + function go() { + var iwin = $('ifr').contentWindow; + // NB: mochitest-chrome actually runs the test as a content docshell. + is(iwin.top, window.top, "iframe names shouldn't shadow |top| via Xray"); + is(iwin.parent, window, "iframe names shouldn't shadow |parent| via Xray"); + ok(!!/http/.exec(iwin.location), "iframe names shouldn't shadow |location| via Xray"); + is(iwin.length, 7, "iframe names shouldn't shadow |length| via Xray"); + is(iwin.window, iwin, "iframe names shouldn't shadow |window| via Xray"); + is(iwin.navigator, Cu.unwaiveXrays(iwin.wrappedJSObject.navigator), + "iframe names shouldn't shadow |navigator| via Xray"); + ok(iwin.alert instanceof Function, + "iframe names shouldn't shadow |alert| via Xray"); + + // Now test XOWs. + var sb = new Cu.Sandbox("https://www.example.com"); + sb.win = iwin; + sb.topWin = top; + sb.parentWin = window; + sb.is = is; + sb.ok = ok; + Cu.evalInSandbox('ok(win.top === topWin, "iframe names shouldnt shadow |top| via cross-origin Xray");', sb); + Cu.evalInSandbox('ok(win.parent === parentWin, "iframe names shouldnt shadow |parent| via cross-origin Xray");', sb); + Cu.evalInSandbox('is(win.length, 7, "iframe names shouldnt shadow |length| via cross-origin Xray");', sb); + Cu.evalInSandbox('ok(win.window === win, "iframe names shouldnt shadow |window| via cross-origin Xray");', sb); + Cu.evalInSandbox('ok(win.navigator === win[5], "iframe names that correspond to non-cross-origin-visible properties should expose the subframe: navigator");', sb); + Cu.evalInSandbox('ok(win.alert === win[6], "iframe names that correspond to non-cross-origin-visible properties should expose the subframe: alert");', sb); + + SimpleTest.finish(); + } + + ]]> + </script> + <iframe id="ifr" type="content" onload="go();" src="https://example.org/tests/js/xpconnect/tests/mochitest/file_bug860494.html" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug865948.xhtml b/js/xpconnect/tests/chrome/test_bug865948.xhtml new file mode 100644 index 0000000000..85fb86874d --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug865948.xhtml @@ -0,0 +1,35 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=865948 +--> +<window title="Mozilla Bug 865948" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=865948" + target="_blank">Mozilla Bug 865948</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + + /** Test for Bug 865948 **/ + SimpleTest.waitForExplicitFinish(); + function go() { + $('ifr').onload = null; + var sb = Cu.Sandbox(["https://example.com", "https://example.org"]); + sb.iwin = $('ifr').contentWindow; + sb.ok = ok; + Cu.evalInSandbox('try { iwin.location = "about:mozilla"; ok(false, "didnt throw"); } catch (e) { ok(!!/denied/.exec(e), "threw: " + e); }', sb); + SimpleTest.finish(); + } + + ]]> + </script> +<iframe id="ifr" type="content" onload="go();" src="https://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug866823.xhtml b/js/xpconnect/tests/chrome/test_bug866823.xhtml new file mode 100644 index 0000000000..39a24fc14e --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug866823.xhtml @@ -0,0 +1,49 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=866823 +--> +<window title="Mozilla Bug 866823" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=866823" + target="_blank">Mozilla Bug 866823</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 866823 **/ + SimpleTest.waitForExplicitFinish(); + + function go() { + var iwin = $('ifr').contentWindow; + + // Make sure that Xray waivers can't be transitively extended onto objects + // for whom the extender may not waive. + var sb = new Cu.Sandbox(iwin, { wantXrays: true }); + sb.iwin = iwin; + ok(Cu.evalInSandbox('iwin.wrappedJSObject.top == iwin.top', sb), "Waiver does not propagate"); + Cu.evalInSandbox('iwin.wrappedJSObject.waiver = iwin.wrappedJSObject', sb); + ok(iwin.wrappedJSObject.eval('waiver == window'), "Waivers disappear same-compartment"); + + // Make sure that standard prototypes don't get COWs. + sb.objProto = Object.prototype; + try { + sb.eval('objProto.toString;', sb); + ok(false, "Should have thrown"); + } catch (e) { + ok(/denied|insecure/, "No silent failure when accessing properties on forbidden prototype"); + } + + SimpleTest.finish(); + } + + ]]> + </script> + <iframe id="ifr" onload="go();" type="content" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug895340.xhtml b/js/xpconnect/tests/chrome/test_bug895340.xhtml new file mode 100644 index 0000000000..ded70e6dd4 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug895340.xhtml @@ -0,0 +1,50 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=895340 +--> +<window title="Mozilla Bug 895340" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=895340 " + target="_blank">Mozilla Bug 895340 </a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + + SimpleTest.waitForExplicitFinish(); + SimpleTest.expectUncaughtException(); + + var finished = false; + + let listener = { + QueryInterface: ChromeUtils.generateQI(["nsIConsoleListener"]) + }; + + listener.observe = function(aMessage) { + if (aMessage.message.includes("Will you report me?") && !finished) { + finished = true; + ok(true, "exception reported"); + Services.console.unregisterListener(listener); + SimpleTest.finish(); + } + }; + + Services.console.registerListener(listener); + + /* Throw an exception and verify that it gets reported. */ + let foo_obs = function() { + throw new Error("Will you report me?"); + }; + + Services.obs.addObserver(foo_obs, "foo"); + Services.obs.notifyObservers(null, "foo", "foo"); + Services.obs.removeObserver(foo_obs, "foo"); + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug932906.xhtml b/js/xpconnect/tests/chrome/test_bug932906.xhtml new file mode 100644 index 0000000000..f7e839d980 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug932906.xhtml @@ -0,0 +1,69 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=932906 +--> +<window title="Mozilla Bug 932906" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=932906" + target="_blank">Mozilla Bug 932906</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 932906 **/ + SimpleTest.waitForExplicitFinish(); + + function passToContent(shouldThrow) { + try { + $('ifr').contentWindow.obs = Services.obs; + ok(!shouldThrow, "Didn't throw when passing non-DOM XPCWN to content"); + } catch (e) { + ok(shouldThrow, "Threw when passing non-DOM XPCWN to content"); + ok(/denied/.test(e), "Threw correct exception: " + e); + } + } + + var gLoadCount = 0; + function loaded() { + ++gLoadCount; + if (gLoadCount == 1) + part1(); + else if (gLoadCount == 2) + part2(); + else + ok(false, "Didn't expect three loads"); + } + + function part1() { + + // Make sure that the pref is what we expect for mochitests. + is(Services.prefs.getBoolPref('dom.use_xbl_scopes_for_remote_xul'), true, + "Test harness set up like we expect"); + + + // First, test that we can't normally pass non-DOM XPCWNs to content. + passToContent(/* shouldThrow = */ true); + + // Now, make sure we _can_ for the remote xul case. We use SpecialPowers + // for the pref munging because it cleans up after us. + SpecialPowers.pushPrefEnv({set: [['dom.use_xbl_scopes_for_remote_xul', false]]}, function() { + $('ifr').contentWindow.location.reload(); + }); + } + + function part2() { + passToContent(/* shouldThrow = */ false); + SimpleTest.finish(); + } + + ]]> + </script> + <iframe id="ifr" onload="loaded();" type="content" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_bug996069.xhtml b/js/xpconnect/tests/chrome/test_bug996069.xhtml new file mode 100644 index 0000000000..5693fd3447 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_bug996069.xhtml @@ -0,0 +1,52 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=996069 +--> +<window title="Mozilla Bug 996069" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=996069" + target="_blank">Mozilla Bug 996069</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 996069 **/ + SimpleTest.waitForExplicitFinish(); + + function loaded() { + var ifr = document.getElementById("ifr").contentWindow; + var sb = new Cu.Sandbox([ifr], + { sandboxPrototype: ifr }); + + ifr.wrappedJSObject.finishTest = function() { + // If we got here we did not hit the NS_ReleaseAssert... + ok(true, "ExpandedPrincipal should not be inherited by content windows"); + + // But let's be sure that the new window does not have nsEP + newWin.wrappedJSObject.obj = Cu.evalInSandbox("var obj = { foo: 'bar' }; obj", sb); + try { + newWin.eval("obj.foo"); + ok(false, "newWin should not have access to object from a scope with ExpandedPrincipal"); + } catch (e) { + ok(/Permission denied/.exec(e.message), "newWin should not have access to object from a scope with ExpandedPrincipal"); + } + newWin.close(); + SimpleTest.finish(); + }; + + var newWin = Cu.evalInSandbox( + "window.open('https://example.org/chrome/js/xpconnect/tests/chrome/file_bug996069.html');", + sb); + } + + ]]> + </script> + <iframe id="ifr" onload="loaded();" type="content" src="https://example.org/chrome/js/xpconnect/tests/chrome/file_bug996069.html" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_chrometoSource.xhtml b/js/xpconnect/tests/chrome/test_chrometoSource.xhtml new file mode 100644 index 0000000000..b9920603a0 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_chrometoSource.xhtml @@ -0,0 +1,68 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<window title="Mozilla Bug 761723" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=761723" target="_blank">Mozilla Bug 761723</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript" src="outoflinexulscript.js"></script> + <script type="application/javascript"><![CDATA[ +const {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm"); +let base = /.*\//.exec(window.location.href)[0]; +const {checkFromJSM} = ChromeUtils.import(base + "file_expandosharing.jsm"); + +function inlinefunction() { + return 42; +} + +var src; +src = inlinefunction.toSource(); +isnot(src.indexOf("return 42"), -1, "inline XUL script should have source"); +is(src.charAt(src.length - 1), "}", "inline XUL source should end with '}'"); +src = outoflinefunction.toSource(); +isnot(src.indexOf("return 42"), -1, "out of line XUL script should have source") +is(src.charAt(src.length - 1), "}", "out of line XUL source should end with '}'"); +src = checkFromJSM.toSource(); +isnot(src.indexOf("catch"), -1, "JSM should have source"); +var ns = {}; +Services.scriptloader.loadSubScript(base + "file_expandosharing.jsm", ns); +src = ns.checkFromJSM.toSource(); +isnot(src.indexOf("catch"), -1, "subscript should have source"); + +var reg = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIChromeRegistry); +var resolvedBase = reg.convertChromeURL(NetUtil.newURI(base)).spec; + +ns = { + base, +}; +Services.scriptloader.loadSubScript(resolvedBase + "subscript.js", ns); +src = ns.checkFromJSM.toSource(); +isnot(src.indexOf("catch"), -1, "subscript of a subscript should have source"); + +ns = {}; +Services.scriptloader.loadSubScript(resolvedBase + "utf8_subscript.js", ns); +src = ns.f.toSource(); +isnot(src.indexOf("return 42;"), -1, "encoded subscript should have correct source"); + +ns = {}; +Services.scriptloader.loadSubScriptWithOptions(resolvedBase + "utf8_subscript.js", + {target: ns, ignoreCache: true}); +src = ns.f.toSource(); +isnot(src.indexOf("return 42;"), -1, "encoded subscript should have correct source"); + +ns = {}; +let b = new Blob([ + "var Exported = 17;" +]); +var blobUrl = URL.createObjectURL(b); +Services.scriptloader.loadSubScript(blobUrl, ns); +is(ns.Exported, 17, "subscript from a blob URL should work"); + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_cloneInto.xhtml b/js/xpconnect/tests/chrome/test_cloneInto.xhtml new file mode 100644 index 0000000000..aa874bda96 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_cloneInto.xhtml @@ -0,0 +1,194 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<window title="Mozilla Bug 503926" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=964293" + target="_blank">Cu.cloneInto()</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + + const TypedArrayThings = [ + 'Int8Array', + 'Uint8Array', + 'Uint8ClampedArray', + 'Int16Array', + 'Uint16Array', + 'Int32Array', + 'Uint32Array', + 'Float32Array', + 'Float64Array', + ]; + + function checkThrows(f, msg, rgxp) { + try { + f(); + ok(false, "Should have thrown: " + msg); + } catch (e) { + ok(true, "Threw correctly - " + msg + " - " + e); + if (rgxp) + ok(rgxp.test(e), "Should throw correct exception: " + e); + } + } + + function getType(a) { + if (a === null || a === undefined) + return 'null'; + + if (Array.isArray(a)) + return 'array'; + + if (File.isInstance(a)) + return 'file'; + + if (Blob.isInstance(a)) + return 'blob'; + + if (TypedArrayThings.includes(a.constructor.name)) + return a.constructor.name; + + if (typeof a == 'object') + return 'object'; + + if (typeof a == 'function') + return 'function'; + + return 'primitive'; + } + + function compare(a, b) { + is (getType(a), getType(b), 'Type matches'); + + var type = getType(a); + if (type == 'array') { + is (a.length, b.length, 'Array.length matches'); + for (var i = 0; i < a.length; ++i) { + compare(a[i], b[i]); + } + + return; + } + + if (type == 'file' || type == 'blob') { + ok ( a === b, 'They should match'); + return; + } + + if (type == 'object') { + ok ( a !== b, 'They should not match'); + + var aProps = []; + for (let p in a) aProps.push(p); + + var bProps = []; + for (let p in b) bProps.push(p); + + is (aProps.length, bProps.length, 'Props match'); + is (aProps.sort().toString(), bProps.sort().toString(), 'Props names match'); + + for (let p in a) { + compare(a[p], b[p]); + } + + return; + } + + if (type == 'function') { + ok ( a !== b, 'They should not match'); + return; + } + + if (type != 'null') { + is (a, b, 'Same value'); + } + } + + var sandboxOptions = { + wantXrays: true, + wantExportHelpers: true, + }; + var sandbox = new Cu.Sandbox(window, sandboxOptions); + // The second sandbox is for testing the exportHelper version of the cloneInto + var sandbox2 = new Cu.Sandbox("https://example.com", sandboxOptions); + sandbox.sandbox2 = sandbox2; + sandbox2.sandbox = sandbox; + + function cloneAndTest(test) { + var output = sandbox.test = Cu.cloneInto(test, sandbox); + compare(test, output); + + output = Cu.evalInSandbox('cloneInto(test, sandbox2)', sandbox); + compare(test, output); + } + + function cloneAndTestWithFunctions(test) { + var output = sandbox.test = Cu.cloneInto(test, sandbox, { cloneFunctions: true }); + compare(test, output); + + output = Cu.evalInSandbox('cloneInto(test, sandbox2, { cloneFunctions: true })', sandbox); + // Note - We need to waive here, because functions are filtered out by object Xrays. + compare(test, Cu.waiveXrays(output)); + } + + var tests = [ + 1, + null, + true, + 'hello world', + [1, 2, 3], + { a: 1, b: 2 }, + new Date(), + { a: 1, b: {}, c: [1, 2, 3, {} ], e: 'hello world' }, + ]; + + for (var i = 0; i < tests.length; ++i) { + cloneAndTest(tests[i]); + } + + checkThrows(function() { Cu.cloneInto({ a() {} }, sandbox); }, + 'Function should not be cloned by default'); + + checkThrows(function() { Cu.cloneInto({ a: document }, sandbox); }, + 'Reflectors should not be wrapped by default'); + + var withReflectors = Cu.cloneInto({ doc: document, win: window }, sandbox, + { wrapReflectors: true }); + is(Cu.unwaiveXrays(Cu.waiveXrays(withReflectors).doc), document, "Document passes"); + is(Cu.unwaiveXrays(Cu.waiveXrays(withReflectors).win), window, "Window passes"); + + + checkThrows(function() { Cu.evalInSandbox('cloneInto({}, sandbox)', sandbox2); }, + 'CloneInto should only work on less privileged target scopes.', + /denied|insecure/); + + var cloneTarget = new Cu.Sandbox("https://example.com"); + var sameOriginSB = new Cu.Sandbox("https://example.com", { wantGlobalProperties: ['XMLHttpRequest'] }); + var crossOriginSB = new Cu.Sandbox("https://example.net", { wantGlobalProperties: ['XMLHttpRequest'] }); + sandbox2.cloneTarget = cloneTarget; + sandbox2.soXHR = Cu.evalInSandbox('new XMLHttpRequest()', sameOriginSB); + sandbox2.xoXHR = Cu.evalInSandbox('new XMLHttpRequest()', crossOriginSB); + sandbox2.chromeDoc = document; + Cu.evalInSandbox('function tryToClone(x) { return cloneInto({val: x}, cloneTarget, { wrapReflectors: true }).val; }', sandbox2); + is(Cu.evalInSandbox('tryToClone(soXHR)', sandbox2), sandbox2.soXHR, 'Same-origin wrapReflectors works'); + checkThrows(function() { Cu.evalInSandbox('tryToClone(chromeDoc)', sandbox2); }, + 'wrapReflectors may not wrap cross-origin reflectors', /unsupported value type/); + + + var test = { a() { return 42; } }; + cloneAndTestWithFunctions(test); + + // Check that inputs are properly passed through cloned functions: + test = { a(obj) { return obj; } }; + var clonedTest = Cu.cloneInto(test, sandbox, {cloneFunctions: true}); + var testInput = {}; + is(clonedTest.a(testInput), testInput, "Objects should be identical"); + ]]> + </script> +</window> diff --git a/js/xpconnect/tests/chrome/test_cows.xhtml b/js/xpconnect/tests/chrome/test_cows.xhtml new file mode 100644 index 0000000000..69d7d3e9e6 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_cows.xhtml @@ -0,0 +1,207 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=500931 +--> +<window title="Mozilla Bug 522764" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=522764 " + target="_blank">Mozilla Bug 522764 </a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ +add_task(async () => { +var sandbox = new Cu.Sandbox("about:blank"); + +await SpecialPowers.pushPrefEnv({"set": [["security.allow_eval_with_system_principal", + true]]}); + +/* eslint-disable no-eval */ + +function getCOW(x) { + if (typeof x != 'object' && typeof x != 'function') + return x; + x = Cu.waiveXrays(x); + var rval = {}; + if (typeof x == "function") + rval = eval(`(${x.toString()})`); + for (var i in x) { + if (x.__lookupGetter__(i)) + rval.__defineGetter__(i, eval(`(${x.__lookupGetter__(i).toString()})`)) + else + rval[i] = getCOW(x[i]); + } + return rval; +} + +// Give the sandbox a way to create ChromeObjectWrapped objects. +sandbox.getCOW = getCOW; + +// Define test API functions in the sandbox. +const TEST_API = ['is', 'isnot', 'ok', 'todo_is', 'todo_isnot', 'todo']; +TEST_API.forEach(function(name) { sandbox[name] = window[name]; }); + +sandbox.chromeGet = function (obj, prop) { return obj[prop]; }; + +function COWTests() { + function getNames(cow) { + let names = []; + for (let name in cow) { + names.push(name); + } + return names; + } + + // This function is actually stringified and run inside a + // sandbox with content privileges. + + // TODO: This could use some refactoring; creating helper + // functions like assertIsWritable(myObj, 'someproperty') might + // be useful. + + function isPropHidden(obj, propName, desc) { + try { + is(obj[propName], undefined, + "getting " + propName + " on " + desc + " should return undefined"); + ok(!(propName in obj), + propName + " on " + desc + " should act as if it doesn't exist"); + ok(!Object.hasOwnProperty.call(obj, propName), + propName + " on " + desc + " should act as if it doesn't exist"); + } catch (e) { + ok(false, "getting " + propName + " on " + desc + " threw " + e); + } + } + + const PROPS_TO_TEST = ['foo', 'bar', 'prototype']; + + var empty = {}; + var nonempty = {foo: 42, bar: 33}; + is(getCOW(empty).foo, undefined, + "shouldn't throw when accessing exposed properties that don't exist"); + + PROPS_TO_TEST.forEach(function(name) { + isPropHidden(getCOW(nonempty), name, "object without exposedProps"); + }); + + // Test function objects. + var func = function(x) { return 42; }; + func.foo = "foo property"; + var funcCOW = getCOW(func); + try { + funcCOW.foo; + ok(false, 'Functions are no longer COWable'); + } catch (e) { + ok(/denied|insecure/.test(e), 'Functions are no longer COWable'); + } + is(funcCOW(), 42, "Chrome functions should be callable"); + + // Test writable property + var writable = getCOW({}); + try { + ok(!("foo" in writable), + "non-existing write-only property shouldn't exist"); + writable.foo = 5; + ok(false, "writing to a write-only exposed prop should throw"); + } catch (e) { + ok(/Permission denied/.test(e), + "writing to a write-only exposed prop should throw the right error"); + } + is(writable.foo, undefined, + "reading from a write-only exposed prop should return undefined"); + try { + delete writable.foo; + ok(false, "deleting a write-only exposed prop should throw"); + } catch (e) { + ok(true, "deleting a write-only exposed prop should throw " + e); + } + + // Test readable property + var readable = { foo: 5, + bar: 6 }; + try { + isPropHidden(getCOW(readable), "foo", undefined, + "reading from a readable exposed prop shouldn't work"); + } catch (e) { + ok(false, "reading from a readable exposed prop shouldn't throw " + e); + } + try { + getCOW(readable).foo = 1; + ok(false, "writing to a read-only exposed prop should fail"); + } catch (e) { + ok(/Permission denied/.test(e), + "writing to a read-only exposed prop should fail"); + } + try { + delete getCOW(readable).foo; + ok(false, "deleting a read-only exposed prop shouldn't work"); + } catch (e) { + ok(/Permission denied/.test(e), + "deleting a read-only exposed prop should throw error"); + } + + try { + var props = getNames(getCOW(readable)); + is(props.length, 0, "COW w/ one exposed prop should not enumerate"); + } catch (e) { + ok(false, "COW w/ a readable prop should not raise exc " + + "on enumeration: " + e); + } + + // Test read/write property + var readwrite = getCOW({}); + try { + ok(!("foo" in readwrite), + "non-existing readwrite property shouldn't exist"); + readwrite.foo = 5; + ok(false, "writing to a readwrite exposed prop should throw"); + } catch (e) { + ok(/Permission denied/.test(e), + "writing to a readwrite exposed prop should throw the right error"); + } + try { + delete readwrite.foo; + ok(false, "deleting a readwrite prop should throw"); + } catch (e) { + ok(/Permission denied/.test(e), + "deleting a readwrite exposed prop should throw the right error"); + } + + // Readables and functions + try { + var COWFunc = getCOW((function() { return 5; })); + is(COWFunc(), 5, "COWed functions should be callable"); + } catch (e) { + todo(false, "COWed functions should not raise " + e); + } +} + +// Stringify the COW test suite and directly evaluate it in the sandbox. +Cu.evalInSandbox('(' + COWTests.toString() + ')()', sandbox); + +// Test that COWed objects passing from content to chrome get unwrapped. +function returnCOW() { + return getCOW({bar: 6}); +} + +var unwrapped = Cu.evalInSandbox( + '(' + returnCOW.toString() + ')()', + sandbox +); + +try { + is(unwrapped.bar, 6, + "COWs should be unwrapped when entering chrome space"); +} catch (e) { + todo(false, "COWs should be unwrapped when entering chrome space, " + + "not raise " + e); +} +}); + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_discardSystemSource.xhtml b/js/xpconnect/tests/chrome/test_discardSystemSource.xhtml new file mode 100644 index 0000000000..86a353e580 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_discardSystemSource.xhtml @@ -0,0 +1,81 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=990353 +--> +<window title="Mozilla Bug 990353" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=990353" + target="_blank">Mozilla Bug 990353</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 990353 **/ + SimpleTest.waitForExplicitFinish(); + + function canary() { + // eslint-disable-next-line no-unused-vars + var someBitOfSource = 42; + } + + var gLoadCount = 0; + function frameLoaded() { + switch (++gLoadCount) { + case 1: + ok(/native code/.test(window[0].canary.toString()), "System function should be sourceless: " + window[0].canary.toString()); + ok(/native code/.test(window[0].onload.toString()), "System event handler should be sourceless: " + window[0].onload.toString()); + var sb = new Cu.Sandbox("https://www.example.com", { discardSource: true }); + Cu.evalInSandbox('function canary() { var someBitOfSource = 42; }', sb); + ok(/native code/.test(sb.canary.toString()), "Function from sandbox with explicit discarding should be sourceless"); + try { + window[0].throwSomething(); + ok(false, "should have thrown"); + } catch (e) { + ok(/some error/.test(e), "Threw exception as expected: " + e); + ok(/throwSomething/.test(e.stack), "Exception stack trace works: " + e.stack); + } + window[0].location = "https://example.org/tests/js/xpconnect/tests/chrome/file_discardSystemSource.html"; + break; + case 2: + ok(/someBitOfSource/.test(Cu.waiveXrays(window[0]).canary.toString()), "Content function should have source"); + ok(/someBitOfSource/.test(Cu.waiveXrays(window[0]).onload.toString()), "Content event handler should have source"); + testWorker(); + break; + } + } + + function testWorker() { + var worker = new window[0].wrappedJSObject.Worker('worker_discardSystemSource.js'); + worker.onmessage = function(evt) { + ok(/someBitOfSource/.test(evt.data), "Non-chrome worker should have source: " + evt.data); + var chromeWorker = new Worker('worker_discardSystemSource.js'); + chromeWorker.onmessage = function(evt) { + ok(/native code/.test(evt.data), "Chrome worker should not have source: " + evt.data); + SimpleTest.finish(); + } + } + } + + function go() { + // We should have our own source, because the pref wasn't enabled when we + // were loaded. + ok(/someBitOfSource/.test(canary.toString()), "Should have own source"); + + window[0].frameElement.onload = frameLoaded; + window[0].location = "file_discardSystemSource.html"; + } + addLoadEvent(function() { + SpecialPowers.pushPrefEnv({set: [['javascript.options.discardSystemSource', true]]}, go); + }); + + ]]> + </script> + <iframe></iframe> +</window> diff --git a/js/xpconnect/tests/chrome/test_documentdomain.xhtml b/js/xpconnect/tests/chrome/test_documentdomain.xhtml new file mode 100644 index 0000000000..8cffdc8e46 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_documentdomain.xhtml @@ -0,0 +1,100 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=601277 +--> +<window title="Mozilla Bug 601277" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=601277" + target="_blank">Mozilla Bug 601277</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Tests for document.domain. **/ + + SimpleTest.waitForExplicitFinish(); + + // Wait for the frames to load. + var gFramesLoaded = 0; + function frameLoaded() { + gFramesLoaded++; + if (gFramesLoaded == document.getElementsByTagName('iframe').length) + startTest(); + } + + function startTest() { + + // Grab all the content windows and waive Xray. Xray waivers only apply to + // chrome, so we can pass these references directly to content. + var win1A = document.getElementById('test1A').contentWindow.wrappedJSObject; + var win1B = document.getElementById('test1B').contentWindow.wrappedJSObject; + var win2 = document.getElementById('test2').contentWindow.wrappedJSObject; + var winBase = document.getElementById('base').contentWindow.wrappedJSObject; + + // Check the basics. + ok(win1A.tryToAccess(win1B), + "Same-origin windows should grant access"); + ok(!win1A.tryToAccess(win2), + "Cross-origin windows should not grant access"); + ok(!win1A.tryToAccess(winBase), + "Subdomain windows should not receive access"); + + // Store references now, while test1A and test1B are same-origin. + win1A.storeReference(win1B); + win1B.storeReference(win1A); + ok(win1A.tryToAccessStored(), "Stored references work when same-origin"); + win1A.evalFromB = Cu.unwaiveXrays(win1B.eval); // Crashtest for bug 1040181. + win1B.functionFromA = Cu.unwaiveXrays(win1A.Function); // Crashtest for bug 1040181. + ok(!win1A.invokingFunctionThrowsSecurityException('evalFromB'), "Should allow before document.domain"); + ok(!win1B.invokingFunctionThrowsSecurityException('functionFromA'), "Should allow before document.domain"); + + // Set document.domain on test1A. This should grant no access, since nobody + // else set it. + win1A.setDomain('example.org'); + ok(!win1A.tryToAccess(winBase), "base must collaborate too"); + ok(!winBase.tryToAccess(win1A), "base must collaborate too"); + ok(!win1A.tryToAccess(win1B), "No longer same-origin"); + ok(win1A.tryToAccessStored(), "We don't revoke access except through Window and Location"); + ok(!win1B.tryToAccess(win1A), "No longer same-origin"); + ok(win1B.tryToAccessStored(), "We don't revoke access except through Window and Location"); + ok(!win1A.invokingFunctionThrowsSecurityException('evalFromB'), "We don't revoke access except through Window and Location"); + ok(!win1B.invokingFunctionThrowsSecurityException('functionFromA'), "We don't revoke access except through Window and Location"); + + // Set document.domain on test1B. Now we're cooking with gas. + win1B.setDomain('example.org'); + ok(!win1B.tryToAccess(winBase), "base must collaborate too"); + ok(!winBase.tryToAccess(win1B), "base must collaborate too"); + ok(win1A.tryToAccess(win1B), "same-origin"); + ok(win1A.tryToAccessStored(), "same-origin"); + ok(win1B.tryToAccess(win1A), "same-origin"); + ok(win1B.tryToAccessStored(), "same-origin"); + + // Explicitly collaborate with base. + winBase.setDomain('example.org'); + ok(winBase.tryToAccess(win1A), "base collaborates"); + ok(win1A.tryToAccess(winBase), "base collaborates"); + + // All done. + SimpleTest.finish(); + } + + + ]]> + </script> + + <iframe id="test1A" onload="frameLoaded();" type="content" + src="http://test1.example.org/tests/js/xpconnect/tests/mochitest/file_documentdomain.html" /> + <iframe id="test1B" onload="frameLoaded();" type="content" + src="http://test1.example.org/tests/js/xpconnect/tests/mochitest/file_documentdomain.html" /> + <iframe id="test2" onload="frameLoaded();" type="content" + src="http://test2.example.org/tests/js/xpconnect/tests/mochitest/file_documentdomain.html" /> + <iframe id="base" onload="frameLoaded();" type="content" + src="http://example.org/tests/js/xpconnect/tests/mochitest/file_documentdomain.html" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_doublewrappedcompartments.xhtml b/js/xpconnect/tests/chrome/test_doublewrappedcompartments.xhtml new file mode 100644 index 0000000000..dd8ddd1bef --- /dev/null +++ b/js/xpconnect/tests/chrome/test_doublewrappedcompartments.xhtml @@ -0,0 +1,41 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=533596 +--> +<window title="Mozilla Bug 533596" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + + <iframe type="content" + src="http://example.org/tests/js/xpconnect/tests/mochitest/file_doublewrappedcompartments.html" + onload="go()" + id="ifr"> + </iframe> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + const utils = SpecialPowers.DOMWindowUtils; + + function go() { + var wrappedWin = $('ifr').contentWindow; + is(typeof wrappedWin.expando, 'undefined', "Shouldn't be able to see the expando"); + + var unwrapped = wrappedWin.wrappedJSObject; + + var expando = unwrapped.expando; + isnot(expando, 'undefined', 'properly wrapped'); + is(typeof expando.querySelector, 'function', 'double wrapped'); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_envChain_event_handler.html b/js/xpconnect/tests/chrome/test_envChain_event_handler.html new file mode 100644 index 0000000000..f492e11512 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_envChain_event_handler.html @@ -0,0 +1,137 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1782450 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1782450</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://global/skin"/> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <script type="application/javascript"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); + +// Verify the environment chain for DOM event handlers described in +// js/src/vm/EnvironmentObject.h. + +let count = 0; +function check(envs, hasEval) { + is(envs.length, hasEval ? 8 : 6); + + let i = 0, env; + + if (hasEval) { + env = envs[i]; i++; + is(env.type, "BlockLexicalEnvironmentObject"); + is(env.qualified, false); + is(env.unqualified, false); + is(env.lexical, true, "lexical must live in the function lexical env"); + is(env.prop, false); + is(env.form_prop, false); + is(env.document_prop, false); + is(env.button_prop, false); + + env = envs[i]; i++; + is(env.type, "CallObject"); + is(env.qualified, true, "qualified var live in the function call object"); + is(env.unqualified, false); + is(env.lexical, false); + is(env.prop, false); + is(env.form_prop, false); + is(env.document_prop, false); + is(env.button_prop, false); + } else { + // qualified var and lexical live in function's frame. + } + + env = envs[i]; i++; + is(env.type, "NonSyntacticLexicalEnvironmentObject"); + is(env.qualified, false); + is(env.unqualified, false); + is(env.lexical, false); + is(env.prop, false); + is(env.form_prop, false); + is(env.document_prop, false); + is(env.button_prop, false); + + env = envs[i]; i++; + is(env.type, "WithEnvironmentObject"); + is(env.qualified, false); + is(env.unqualified, false); + is(env.lexical, false); + is(env.prop, true, "this property must live in the with env for button"); + is(env.form_prop, false); + is(env.document_prop, false); + is(env.button_prop, true, "button property must live in the with env for button"); + + env = envs[i]; i++; + is(env.type, "WithEnvironmentObject"); + is(env.qualified, false); + is(env.unqualified, false); + is(env.lexical, false); + is(env.prop, false); + is(env.form_prop, true, "form property must live in the with env for form"); + is(env.document_prop, false); + is(env.button_prop, false); + + env = envs[i]; i++; + is(env.type, "WithEnvironmentObject"); + is(env.qualified, false); + is(env.unqualified, false); + is(env.lexical, false); + is(env.prop, false); + is(env.form_prop, false); + is(env.document_prop, true, "document property must live in the with env for document"); + is(env.button_prop, false); + + env = envs[i]; i++; + is(env.type, "GlobalLexicalEnvironmentObject"); + is(env.qualified, false); + is(env.unqualified, false); + is(env.lexical, false); + is(env.prop, false); + is(env.form_prop, false); + is(env.document_prop, false); + is(env.button_prop, false); + + env = envs[i]; i++; + is(env.type, "*global*"); + is(env.qualified, false); + is(env.unqualified, true, "unqualified name must live in the global"); + is(env.lexical, false); + is(env.prop, false); + is(env.form_prop, false); + is(env.document_prop, false); + is(env.button_prop, false); + + count++; + if (count == 2) { + SimpleTest.finish(); + } +} + </script> +</head> +<body> +<form id="form"> +<button id="button_optimized" onclick="event.preventDefault(); var qualified = 10; unqualified = 20; let lexical = 30; this.prop = 40; const funcs = Cu.getJSTestingFunctions(); const envs = []; let env = funcs.getInnerMostEnvironmentObject(); while (env) { envs.push({ type: funcs.getEnvironmentObjectType(env) || '*global*', qualified: !!Object.getOwnPropertyDescriptor(env, 'qualified'), unqualified: !!Object.getOwnPropertyDescriptor(env, 'unqualified'), lexical: !!Object.getOwnPropertyDescriptor(env, 'lexical'), prop: !!Object.getOwnPropertyDescriptor(env, 'prop'), document_prop: !!Object.getOwnPropertyDescriptor(env, 'document_prop'), form_prop: !!Object.getOwnPropertyDescriptor(env, 'form_prop'), button_prop: !!Object.getOwnPropertyDescriptor(env, 'button_prop'), }); env = funcs.getEnclosingEnvironmentObject(env); } check(envs, false); return false;">Click Me!</button> +<!-- Put direct eval to de-optimize function scope --> +<button id="button_unoptimized" onclick="event.preventDefault(); eval(''); var qualified = 10; unqualified = 20; let lexical = 30; this.prop = 40; const funcs = Cu.getJSTestingFunctions(); const envs = []; let env = funcs.getInnerMostEnvironmentObject(); while (env) { envs.push({ type: funcs.getEnvironmentObjectType(env) || '*global*', qualified: !!Object.getOwnPropertyDescriptor(env, 'qualified'), unqualified: !!Object.getOwnPropertyDescriptor(env, 'unqualified'), lexical: !!Object.getOwnPropertyDescriptor(env, 'lexical'), prop: !!Object.getOwnPropertyDescriptor(env, 'prop'), document_prop: !!Object.getOwnPropertyDescriptor(env, 'document_prop'), form_prop: !!Object.getOwnPropertyDescriptor(env, 'form_prop'), button_prop: !!Object.getOwnPropertyDescriptor(env, 'button_prop'), }); env = funcs.getEnclosingEnvironmentObject(env); } check(envs, true);">Click Me!</button> +</form> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1782450">Mozilla Bug 1782450</a> +<script type="application/javascript"> +"use strict"; +document.document_prop = 50; +const form = document.getElementById("form"); +form.form_prop = 50; +const button_unoptimized = document.getElementById("button_unoptimized"); +button_unoptimized.button_prop = 60; +button_unoptimized.click(); +const button_optimized = document.getElementById("button_optimized"); +button_optimized.button_prop = 60; +button_optimized.click(); +</script> +</body> +</html> diff --git a/js/xpconnect/tests/chrome/test_evalInSandbox.xhtml b/js/xpconnect/tests/chrome/test_evalInSandbox.xhtml new file mode 100644 index 0000000000..ac65151101 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_evalInSandbox.xhtml @@ -0,0 +1,205 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=533596 +--> +<window title="Mozilla Bug 533596" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + + <iframe src="http://example.org/tests/js/xpconnect/tests/mochitest/file_evalInSandbox.html" + onload="checkCrossOrigin(this)"> + </iframe> + <iframe src="chrome://mochitests/content/chrome/js/xpconnect/tests/chrome/file_evalInSandbox.html" + onload="checkSameOrigin(this)"> + </iframe> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + const utils = window.windowUtils; + + function checkCrossOriginSandbox(sandbox) + { + is(utils.getClassName(sandbox), + "Proxy", + "sandbox was wrapped correctly"); + + is(utils.getClassName(Cu.evalInSandbox("this.document", sandbox)), + "Proxy", + "return value was rewrapped correctly"); + } + + function checkCrossOriginXrayedSandbox(sandbox) + { + ok(Cu.evalInSandbox("!('windowfoo' in window);", sandbox), + "the window itself Xray is an XrayWrapper"); + ok(Cu.evalInSandbox("('wrappedJSObject' in this.document);", sandbox), + "wrappers inside eIS are Xrays"); + ok(Cu.evalInSandbox("!('foo' in this.document);", sandbox), + "must not see expandos"); + ok('wrappedJSObject' in Cu.evalInSandbox("this.document", sandbox), + "wrappers returned from the sandbox are Xrays"); + ok(!("foo" in Cu.evalInSandbox("this.document", sandbox)), + "must not see expandos in wrappers returned from the sandbox"); + + ok('wrappedJSObject' in sandbox.document, + "values obtained from the sandbox are Xrays"); + ok(!("foo" in sandbox.document), + "must not see expandos in wrappers obtained from the sandbox"); + + } + + function checkCrossOrigin(ifr) { + var win = ifr.contentWindow; + var sandbox = + new Cu.Sandbox(win, { sandboxPrototype: win, wantXrays: true } ); + + checkCrossOriginSandbox(sandbox); + checkCrossOriginXrayedSandbox(sandbox); + + sandbox = + new Cu.Sandbox(win, { sandboxPrototype: win } ); + + checkCrossOriginSandbox(sandbox); + checkCrossOriginXrayedSandbox(sandbox); + + sandbox = + new Cu.Sandbox(win, { sandboxPrototype: win, wantXrays: false } ); + + checkCrossOriginSandbox(sandbox); + + ok(Cu.evalInSandbox("('foo' in this.document);", sandbox), + "can see expandos"); + ok(!("foo" in Cu.evalInSandbox("this.document", sandbox)), + "must not see expandos in wrappers returned from the sandbox"); + ok(("foo" in Cu.waiveXrays(Cu.evalInSandbox("this.document", sandbox))), + "must see expandos in waived wrappers returned from the sandbox"); + + ok(!("foo" in sandbox.document), + "must not see expandos in wrappers obtained from the sandbox"); + ok("foo" in Cu.waiveXrays(sandbox.document), + "must see expandos in wrappers obtained from the sandbox"); + + testDone(); + } + + function checkSameOrigin(ifr) { + var win = ifr.contentWindow; + var sandbox = + new Cu.Sandbox(win, { sandboxPrototype: win, wantXrays: true } ); + + ok(Cu.evalInSandbox("('foo' in this.document);", sandbox), + "must see expandos for a chrome sandbox"); + + sandbox = + new Cu.Sandbox(win, { sandboxPrototype: win } ); + + ok(Cu.evalInSandbox("('foo' in this.document);", sandbox), + "must see expandos for a chrome sandbox"); + + sandbox = + new Cu.Sandbox(win, { sandboxPrototype: win, wantXrays: false } ); + + ok(Cu.evalInSandbox("('foo' in this.document);", sandbox), + "can see expandos for a chrome sandbox"); + + testDone(); + } + + var testsRun = 0; + function testDone() { + if (++testsRun == 2) + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + + try { + var sandbox1 = new Cu.Sandbox(this, { sandboxPrototype: undefined } ); + ok(false, "undefined is not a valid prototype"); + } + catch (e) { + ok(true, "undefined is not a valid prototype"); + } + + try { + var sandbox2 = new Cu.Sandbox(this, { wantXrays: undefined } ); + ok(false, "undefined is not a valid value for wantXrays"); + } + catch (e) { + ok(true, "undefined is not a valid value for wantXrays"); + } + + // Crash test for bug 601829. + try { + Cu.evalInSandbox('', null); + } catch (e) { + ok(true, "didn't crash on a null sandbox object"); + } + + try { + var sandbox3 = new Cu.Sandbox(this, { sameZoneAs: this } ); + ok(true, "sameZoneAs works"); + } + catch (e) { + ok(false, "sameZoneAs works"); + } + + // The 'let' keyword only appears with JS 1.7 and above. We use this fact + // to make sure that sandboxes get explict JS versions and don't inherit + // them from the most recent scripted frame. + function checkExplicitVersions() { + // eslint-disable-next-line no-undef + var sb = new Cu.Sandbox(sop); + Cu.evalInSandbox('let someVariable = 42', sb, '1.7'); + ok(true, "Didn't throw with let"); + try { + Cu.evalInSandbox('let someVariable = 42', sb); + ok(false, "Should have thrown with let"); + } catch (e) { + ok(true, "Threw with let: " + e); + } + try { + Cu.evalInSandbox('let someVariable = 42', sb, '1.5'); + ok(false, "Should have thrown with let"); + } catch (e) { + ok(true, "Threw with let: " + e); + } + } + var outerSB = new Cu.Sandbox(this); + Cu.evalInSandbox(checkExplicitVersions.toSource(), outerSB, '1.7'); + outerSB.ok = ok; + outerSB.sop = this; + Cu.evalInSandbox('checkExplicitVersions();', outerSB); + + const {addDebuggerToGlobal} = ChromeUtils.importESModule("resource://gre/modules/jsdebugger.sys.mjs"); + addDebuggerToGlobal(globalThis); + + try { + let dbg = new Debugger(); + let sandbox = new Cu.Sandbox(this, { + invisibleToDebugger: false, + freshCompartment: true, + }); + dbg.addDebuggee(sandbox); + ok(true, "debugger added visible value"); + } catch(e) { + ok(false, "debugger could not add visible value"); + } + + try { + let dbg = new Debugger(); + let sandbox = new Cu.Sandbox(this, { invisibleToDebugger: true }); + dbg.addDebuggee(sandbox); + ok(false, "debugger added invisible value"); + } catch(e) { + ok(true, "debugger did not add invisible value"); + } + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_evalInWindow.xhtml b/js/xpconnect/tests/chrome/test_evalInWindow.xhtml new file mode 100644 index 0000000000..00299266f2 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_evalInWindow.xhtml @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=877673 +--> +<window title="Mozilla Bug 877673" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + SimpleTest.waitForExplicitFinish(); + var sb = new Cu.Sandbox("https://example.org", {wantExportHelpers: true}); + sb.ok = ok; + + function executeIn(frame, script, exceptionCb) { + sb.frame = frame; + sb.exceptionCb = exceptionCb; + if (exceptionCb) { + return Cu.evalInSandbox("try {frame.eval('" + script + "'); ok(false, 'Exception should have been thrown.')} catch(e) {exceptionCb(e)}", sb); + } + + return Cu.evalInSandbox("frame.eval('" + script + "')", sb); + } + + function testSameOrigin(frame) { + frame.contentWindow.document.wrappedJSObject.str = "foobar"; + is(executeIn(frame.contentWindow, "document.str"), "foobar", + "Same origin string property access."); + + executeIn(frame.contentWindow, 'document.obj = {prop: "foobar"}'); + is((executeIn(frame.contentWindow, "document.obj")).prop, "foobar", + "Same origin object property access (cloning)."); + isnot(executeIn(frame.contentWindow, "document.obj"), frame.contentWindow.document.wrappedJSObject.obj, + "Ensure cloning for js objects."); + is(executeIn(frame.contentWindow, "document"), frame.contentWindow.document, + "Xrayables should just pass without cloning."); + is( executeIn(frame.contentWindow, "({a:{doc: document}})").a.doc, frame.contentWindow.document, + "Deep cloning works."); + + executeIn(frame.contentWindow, "throw 42", function(e){is(e, 42, + "Exception was thrown from script.")}); + + testDone(); + } + + function testCrossOrigin(frame) { + executeIn(frame.contentWindow, "var a = 42;", function(e){ok(e.toString().indexOf("Permission denied") > -1, + "Executing script in a window from cross origin should throw.");}); + testDone(); + } + + var testsRun = 0; + function testDone() { + if (++testsRun == 2) + SimpleTest.finish(); + } + ]]></script> + <iframe src="https://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" + onload="testSameOrigin(this)"> + </iframe> + <iframe src="http://mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_empty.html" + onload="testCrossOrigin(this)"> + </iframe> +</window> diff --git a/js/xpconnect/tests/chrome/test_exnstack.xhtml b/js/xpconnect/tests/chrome/test_exnstack.xhtml new file mode 100644 index 0000000000..48bcac5243 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_exnstack.xhtml @@ -0,0 +1,68 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=735544 +--> +<window title="Mozilla Bug 735544" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=735544" + target="_blank">Mozilla Bug 735544</a> + <iframe id='ifr0' onload="frameDone(0);" src="http://mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_exnstack.html" /> + <iframe id='ifr1' onload="frameDone(1);" src="http://mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_exnstack.html" /> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 735544 - Allow exception stacks to cross compartment boundaries **/ + + SimpleTest.waitForExplicitFinish(); + + var gFramesDone = [false, false]; + function frameDone(idx) { + gFramesDone[idx] = true; + if (gFramesDone[0] && gFramesDone[1]) + startTest(); + } + + function throwAsChrome() { + + // Grab the iframe content windows. + var cwin0 = document.getElementById('ifr0').contentWindow; + var cwin1 = document.getElementById('ifr1').contentWindow; + + // Have cwin0 call a function on cwin1 that throws. + cwin0.wrappedJSObject.doThrow(cwin1); + } + + function startTest() { + + try { + throwAsChrome(); + ok(false, "should throw"); + } catch (e) { + + let stackFrames = e.stack.split("\n"); + + ok(/throwAsInner/.exec(stackFrames[0]), + "The bottom frame should be thrown by the inner"); + + ok(/throwAsOuter/.exec(stackFrames[2]), + "The 3rd-from-bottom frame should be thrown by the other"); + + ok(!/throwAsChrome/.exec(e.stack), + "The entire stack should not cross into chrome."); + } + + SimpleTest.finish(); + } + + ]]> + </script> + +</window> diff --git a/js/xpconnect/tests/chrome/test_expandosharing.xhtml b/js/xpconnect/tests/chrome/test_expandosharing.xhtml new file mode 100644 index 0000000000..1dc95239f4 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_expandosharing.xhtml @@ -0,0 +1,147 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=758415 +--> +<window title="Mozilla Bug 758415" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=758415" + target="_blank">Mozilla Bug 758415</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + + /** Test for Cross-Origin Xray Expando Sharing. **/ + SimpleTest.waitForExplicitFinish(); + + // Import our test JSM. We first strip the filename off + // the chrome url, then append the jsm filename. + var base = /.*\//.exec(window.location.href)[0]; + const {checkFromJSM} = ChromeUtils.import(base + "file_expandosharing.jsm"); + + // Wait for all child frames to load. + var gLoadCount = 0; + function frameLoaded() { + if (++gLoadCount == window.frames.length) + go(); + } + + function go() { + + // Empower the content windows with some functions. + var wins = document.getElementsByTagName('iframe'); + for (var i = 0; i < wins.length; ++i) { + var win = wins[i].contentWindow.wrappedJSObject; + win.ok = ok; + win.is = is; + } + + // Grab references to the content windows. We abbreviate the origins as follows: + // A: test1.example.org + // B: test2.example.org + // C: sub1.test1.example.org + window.gWinA1 = document.getElementById('frameA1').contentWindow; + window.gWinA2 = document.getElementById('frameA2').contentWindow; + window.gWinA3 = document.getElementById('frameA3').contentWindow; + window.gWinB = document.getElementById('frameB').contentWindow; + window.gWinC = document.getElementById('frameC').contentWindow; + + /* globals gWinA1, gWinA2, gWinA3, gWinB, gWinC */ + + // Test expando sharing with a JSM for different types of Xrays. + testJSM(Cu.unwaiveXrays(gWinC.wrappedJSObject.targetWN)); + testJSM(Cu.unwaiveXrays(gWinC.wrappedJSObject.targetDOM)); + testJSM(Cu.unwaiveXrays(gWinC.wrappedJSObject.targetJS)); + + // Make sure sandboxes never share expandos with anyone else. + testSandbox(Cu.unwaiveXrays(gWinB.wrappedJSObject.targetWN)); + testSandbox(Cu.unwaiveXrays(gWinB.wrappedJSObject.targetDOM)); + testSandbox(Cu.unwaiveXrays(gWinB.wrappedJSObject.targetJS)); + + // Test Content Xrays. + testContentXrays(); + + SimpleTest.finish(); + } + + // Make sure that expandos are shared between us and a JSM. + function testJSM(target) { + target.numProp = 42; + target.strProp = "foo"; + target.objProp = { bar: "baz" }; + checkFromJSM(target, is); + } + + function testSandbox(target) { + + // This gets both run in this scope and the sandbox scope. + var name = "harness"; + function placeExpando() { + target.prop = name; + } + + // Set up the sandboxes. Use an expanded principal to get xrays with + // exclusive expandos. + let sb1 = Cu.Sandbox(["https://test1.example.org", "https://test2.example.org"]); + let sb2 = Cu.Sandbox(["https://test1.example.org", "https://test2.example.org"]); + sb1.target = target; + sb2.target = target; + sb1.name = "sandbox1"; + sb2.name = "sandbox2"; + placeExpando(); + Cu.evalInSandbox(placeExpando.toSource() + "placeExpando();", sb1); + Cu.evalInSandbox(placeExpando.toSource() + "placeExpando();", sb2); + + // Make sure everyone sees a different value. + is(target.prop, "harness", "Harness sees its own value"); + is(Cu.evalInSandbox("target.prop", sb1), "sandbox1", "Sandbox 1 sees its own value"); + is(Cu.evalInSandbox("target.prop", sb2), "sandbox2", "Sandbox 2 sees its own value"); + } + + // Make sure that the origin tagging machinery works correctly and that we don't + // mix up chrome and content expandos. + function testContentXrays() { + + // Give A1 and A3 xrays to (same-origin) A2. + Cu.setWantXrays(gWinA1); + Cu.setWantXrays(gWinA3); + + gWinA1.wrappedJSObject.placeExpando('A1_expando', 11, gWinA2.document); + gWinA3.wrappedJSObject.placeExpando('A3_expando', 33, gWinA2.document); + gWinA2.document.Chrome_expando = 33; + + is(gWinA2.document.Chrome_expando, 33, "Read chrome expando properly"); + is(typeof gWinA2.document.A1_expando, 'undefined', "Chrome doesn't see content expandos"); + is(typeof gWinA2.document.A3_expando, 'undefined', "Chrome doesn't see content expandos"); + gWinA1.wrappedJSObject.checkExpando('A1_expando', 11, gWinA2.document, "Content sees proper expandos"); + gWinA3.wrappedJSObject.checkExpando('A1_expando', 11, gWinA2.document, "Content sees proper expandos"); + gWinA1.wrappedJSObject.checkExpando('A3_expando', 33, gWinA2.document, "Content sees proper expandos"); + gWinA3.wrappedJSObject.checkExpando('A3_expando', 33, gWinA2.document, "Content sees proper expandos"); + gWinA1.wrappedJSObject.checkExpando('Chrome_expando', null, gWinA2.document, "Content doesn't see chrome expandos"); + gWinA3.wrappedJSObject.checkExpando('Chrome_expando', null, gWinA2.document, "Content doesn't see chrome expandos"); + + // We very explicitly do not support expando sharing via document.domain. + // A comment in the implementation explains why. + gWinA1.document.domain = 'test1.example.org'; + gWinA2.document.domain = 'test1.example.org'; + gWinA3.document.domain = 'test1.example.org'; + gWinC.document.domain = 'test1.example.org'; + gWinC.wrappedJSObject.checkExpando('A1_expando', null, gWinA2.document, "document.domain should have no effect here"); + gWinC.wrappedJSObject.checkExpando('A3_expando', null, gWinA2.document, "document.domain should have no effect here"); + } + + ]]> + </script> + <iframe id="frameA1" onload="frameLoaded();" type="content" src="https://test1.example.org/tests/js/xpconnect/tests/mochitest/file_expandosharing.html" /> + <iframe id="frameA2" onload="frameLoaded();" type="content" src="https://test1.example.org/tests/js/xpconnect/tests/mochitest/file_expandosharing.html" /> + <iframe id="frameA3" onload="frameLoaded();" type="content" src="https://test1.example.org/tests/js/xpconnect/tests/mochitest/file_expandosharing.html" /> + <iframe id="frameB" onload="frameLoaded();" type="content" src="https://test2.example.org/tests/js/xpconnect/tests/mochitest/file_expandosharing.html" /> + <iframe id="frameC" onload="frameLoaded();" type="content" src="https://sub1.test1.example.org/tests/js/xpconnect/tests/mochitest/file_expandosharing.html" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_exposeInDerived.xhtml b/js/xpconnect/tests/chrome/test_exposeInDerived.xhtml new file mode 100644 index 0000000000..ee6ad2d229 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_exposeInDerived.xhtml @@ -0,0 +1,45 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=804630 +--> +<window title="Mozilla Bug 804630" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=804630" + target="_blank">Mozilla Bug 804630</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test to make sure that COWed objects can't expose properties from their prototypes. **/ + // Set up the sandbox. + var sb = new Cu.Sandbox("https://www.example.com"); + sb.ok = ok; + sb.is = is; + + // Make a chrome object that tries to expose objects off its prototype. + sb.proto = { read: 42, readWrite: 32 }; + sb.obj = {}; + sb.obj.__proto__ = sb.proto; + + // Make sure we can't access any of the properties on the prototype directly. + Cu.evalInSandbox('is(proto.read, undefined, "proto.read inaccessible");', sb); + Cu.evalInSandbox('var wrote = false; ' + + 'try { proto.readWrite = 12; wrote = true; } catch(e) {} ' + + ' ok(!wrote, "Should not write proto property");', sb); + + // Make sure we can't access the exposed properties via the derived object. + Cu.evalInSandbox('is(obj.read, undefined, "obj.read inaccessible");', sb); + Cu.evalInSandbox('is(obj.readWrite, undefined, "obj.readWrite is not readable");', sb); + Cu.evalInSandbox('try { obj.readWrite = 8; ok(false, "obj.readWrite is not writable"); } catch (e) {};', + sb); + + ]]> + </script> +</window> diff --git a/js/xpconnect/tests/chrome/test_inlineScripts.html b/js/xpconnect/tests/chrome/test_inlineScripts.html new file mode 100644 index 0000000000..cb5f5ed530 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_inlineScripts.html @@ -0,0 +1,53 @@ +<!DOCTYPE html> +<html> + <meta charset=utf-8> + <title>Tests for nsIScriptError</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <div id="log"></div> + + <!-- Verify that column is correct, even for inline scripts with HTML on the same line --> + <span>some html</span> <script>var inlineScriptStack = new Error().stack;</script> + <script> + function waitForError (expectedMessage){ + return new Promise(resolve => { + const listener = { + QueryInterface: ChromeUtils.generateQI(["nsIConsoleListener"]) + }; + + listener.observe = function(message) { + if (message.message.includes(expectedMessage)) { + message.QueryInterface(Ci.nsIScriptError); + resolve(message); + Services.console.unregisterListener(listener); + } + }; + + Services.console.registerListener(listener); + }); + } + + var onInlineScriptError = waitForError("doThrow"); + var onModuleError = waitForError("doThrowInModule"); + SimpleTest.expectUncaughtException(); + </script> + <span>some more html</span><script>doThrow() // eslint-disable-line no-undef</script> + <script>var b;</script><hr><script type="module">SimpleTest.expectUncaughtException();doThrowInModule() // eslint-disable-line no-undef</script> + <script> + add_task(async () => { + info("Check line and column information in Error#stack"); + const { groups } = inlineScriptStack.match(/(?<line>\d+):(?<column>\d+)/); + is(groups.line, "9", "line of Error#stack in inline script is correct"); + is(groups.column, "58", "column of Error#stack in inline script is correct"); + + info("Check line and column information Error message in inline script"); + const errorMessage = await onInlineScriptError; + is(errorMessage.lineNumber, 33, "The exception line is correct"); + is(errorMessage.columnNumber, 38, "The exception column is correct"); + + info("Check line and column information Error message in inline module"); + const errorMessageInModule = await onModuleError; + is(errorMessageInModule.lineNumber, 34, "The module exception line is correct"); + is(errorMessageInModule.columnNumber, 89, "The module exception column is correct"); + }); + </script> +</html>
\ No newline at end of file diff --git a/js/xpconnect/tests/chrome/test_localstorage_with_nsEp.xhtml b/js/xpconnect/tests/chrome/test_localstorage_with_nsEp.xhtml new file mode 100644 index 0000000000..dbc0ea6a61 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_localstorage_with_nsEp.xhtml @@ -0,0 +1,37 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=980023 +--> +<window title="Mozilla Bug 980023 " + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=980023" + target="_blank">Mozilla Bug 980023 </a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + + /** Test for localstorage access with expanded principal. **/ + SimpleTest.waitForExplicitFinish(); + + function go() { + var iwin = document.getElementById('ifr').contentWindow; + var sb = new Cu.Sandbox([iwin], {sandboxPrototype: iwin}); + Cu.evalInSandbox("window.localStorage.test_localstorage_with_nsEp = 3",sb); + is(Cu.evalInSandbox("window.localStorage.test_localstorage_with_nsEp",sb), "3"); + is(iwin.localStorage.test_localstorage_with_nsEp, "3"); + iwin.localStorage.removeItem("test_localstorage_with_nsEp"); + SimpleTest.finish(); + } + + ]]> + </script> + <iframe id="ifr" onload="go();" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_matches.xhtml b/js/xpconnect/tests/chrome/test_matches.xhtml new file mode 100644 index 0000000000..96472bc8ac --- /dev/null +++ b/js/xpconnect/tests/chrome/test_matches.xhtml @@ -0,0 +1,49 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=533596 +--> +<window title="Mozilla Bug 533596" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + + <iframe src="http://example.org/tests/js/xpconnect/tests/mochitest/file_matches.html" + onload="runTest(this)"> + </iframe> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + SimpleTest.waitForExplicitFinish(); + function runTest(ifr) + { + var doc = ifr.contentDocument; + var docElem = doc.documentElement; + + var res = doc.createElement('div').matches('div'); + is(res, true, "matches call through xray, regular case"); + + res = docElem.matches.call( + doc.createElement('div'), 'div'); + is(res, true, "matches call through xray, with .call"); + + var sb = new Cu.Sandbox(ifr.contentWindow); + sb.doc = doc; + var str = "doc.documentElement.matches.call(doc.createElement( 'div' ),'div')"; + res = Cu.evalInSandbox(str, sb); + is(res, true, "matches call through xray (same origin), with .call"); + + docElem.matches = function(){return false}; + res = docElem.matches.call(doc.createElement( 'div' ),'div'); + is(res, false, "shadowing matches with an expando on the xray wrapper"); + + SimpleTest.finish(); + } + + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_nodelists.xhtml b/js/xpconnect/tests/chrome/test_nodelists.xhtml new file mode 100644 index 0000000000..d3d4dfc34e --- /dev/null +++ b/js/xpconnect/tests/chrome/test_nodelists.xhtml @@ -0,0 +1,49 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<window title="Test nodelists from chrome" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + SimpleTest.waitForExplicitFinish(); + + function go() { + var win = $('ifr').contentWindow; + var list = win.document.getElementsByTagName('p'); + is(list.length, 3, "can get the length"); + ok(HTMLParagraphElement.isInstance(list[0]), "can get list[0]"); + is(list[0], list.item(0), "list.item works"); + is(list.item, list.item, "don't recreate functions for each get"); + + var list2 = list[2]; + ok(HTMLParagraphElement.isInstance(list[2]), "list[2] exists"); + ok("2" in list, "in operator works"); + + is(win.document.body.removeChild(win.document.body.lastChild), list2, "remove last paragraph element"); + ok(!("2" in list), "in operator doesn't see phantom element"); + is(list[2], undefined, "no node there!"); + + var optionList = win.document.createElement("select").options; + var option = win.document.createElement("option"); + optionList[0] = option; + is(optionList.item(0), option, "Creators work"); + + option = win.document.createElement("option"); + optionList[0] = option; + is(optionList.item(0), option, "Setters work"); + + SimpleTest.finish(); + } + ]]></script> + + <iframe id="ifr" + src="http://mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_nodelists.html" + onload="go()" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_nsScriptErrorWithStack.html b/js/xpconnect/tests/chrome/test_nsScriptErrorWithStack.html new file mode 100644 index 0000000000..99a4727756 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_nsScriptErrorWithStack.html @@ -0,0 +1,59 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Test for 814497</title> +<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> +<div id="log"></div> +<script> + var c = Cc; + + SimpleTest.waitForExplicitFinish(); + SimpleTest.expectUncaughtException(); + + // /!\ Line number is important in this test, + // we are asserting the following functions line # + function failingStack() { + nestedFunction(); + } + function nestedFunction() { + // eslint-disable-next-line no-undef + doesntExistsAndThrow(); + } + + var TestObserver = { + QueryInterface: ChromeUtils.generateQI(["nsIObserver"]), + + observe: function test_observe(aSubject) + { + if (!(aSubject instanceof Ci.nsIScriptError)) { + return; + } + dump("stack: "+aSubject.stack+"\n"); + + // Main assertions + var s = aSubject.stack; + ok(!!s, "has first frame"); + ok(s.source.includes("test_nsScriptErrorWithStack.html"), "source is correct"); + is(s.line, 19, "line is correct"); + is(s.column, 5, "column is correct"); + is(s.functionDisplayName, "nestedFunction"); + s = s.parent; + ok(!!s, "has second frame"); + ok(s.source.includes("test_nsScriptErrorWithStack.html"), "source is correct"); + is(s.line, 15, "line is correct"); + is(s.column, 5, "column is correct"); + is(s.functionDisplayName, "failingStack"); + // We shouldn't have any more frame as we used setTimeout + ok(!s.parent, "has no more frames"); + + // Cleanup + Services.console.unregisterListener(TestObserver); + SimpleTest.finish(); + } + }; + + Services.console.registerListener(TestObserver); + + // use setTimeout in order to prevent throwing from test frame + // and so have a clean stack frame with just our method calls + setTimeout(failingStack, 0); +</script> diff --git a/js/xpconnect/tests/chrome/test_onGarbageCollection.html b/js/xpconnect/tests/chrome/test_onGarbageCollection.html new file mode 100644 index 0000000000..ce056ed354 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_onGarbageCollection.html @@ -0,0 +1,48 @@ +<!doctype html> +<html> + <head> + <title>Bug 1150253 - Sanity test for the SpiderMonkey Debugger API's onGarbageCollection hook</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"> + </script> + </head> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1150253" + target="_blank">Mozilla Bug 1150253</a> + + <script type="application/javascript"> + SimpleTest.waitForExplicitFinish(); + + const { gc } = Cu.getJSTestingFunctions(); + + // Instantiate `Debugger` in a sandbox as Debugger requires to be created + // in a compartment different than the debuggee. + let sandbox = Cu.Sandbox( + Components.Constructor("@mozilla.org/systemprincipal;1", "nsIPrincipal")(), + { + freshCompartment: true, + wantGlobalProperties: ["ChromeUtils"], + } + ); + Cu.evalInSandbox(` +const { addDebuggerToGlobal } = ChromeUtils.importESModule( + 'resource://gre/modules/jsdebugger.sys.mjs' +); +addDebuggerToGlobal(globalThis); +`, sandbox + ); + + const dbg = new sandbox.Debugger(this); + + dbg.memory.onGarbageCollection = function (data) { + // Don't keep calling this hook after we finish. + dbg.memory.onGarbageCollection = undefined; + dbg.removeAllDebuggees(); + + ok(data, "The onGarbageCollection hook was fired."); + SimpleTest.finish(); + }; + + gc(); + </script> + </body> +</html> diff --git a/js/xpconnect/tests/chrome/test_precisegc.xhtml b/js/xpconnect/tests/chrome/test_precisegc.xhtml new file mode 100644 index 0000000000..56f047843e --- /dev/null +++ b/js/xpconnect/tests/chrome/test_precisegc.xhtml @@ -0,0 +1,26 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=533596 +--> +<window title="Mozilla Bug 661927" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + Cu.schedulePreciseGC( + function() { + ok(true, "callback executed"); + SimpleTest.finish(); + }); + SimpleTest.waitForExplicitFinish(); + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_private_field_cows.xhtml b/js/xpconnect/tests/chrome/test_private_field_cows.xhtml new file mode 100644 index 0000000000..24fe9d5e0a --- /dev/null +++ b/js/xpconnect/tests/chrome/test_private_field_cows.xhtml @@ -0,0 +1,131 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> + +<window title="Mozilla Bug ????" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=>?????" target="_blank">Mozilla Bug ???? </a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + /* eslint-disable no-eval */ + + add_task(async () => { + var sandbox = new Cu.Sandbox("about:blank"); + + await SpecialPowers.pushPrefEnv({ + "set": [["security.allow_eval_with_system_principal", + true]] + }); + + function getCOW(x) { + if (typeof x != 'object' && typeof x != 'function') + return x; + x = Cu.waiveXrays(x); + var rval = {}; + if (typeof x == "function") + rval = eval(`(${x.toString()})`); + for (var i in x) { + if (x.__lookupGetter__(i)) + rval.__defineGetter__(i, eval(`(${x.__lookupGetter__(i).toString()})`)) + else + rval[i] = getCOW(x[i]); + } + return rval; + } + + // Give the sandbox a way to create ChromeObjectWrapped objects. + sandbox.getCOW = getCOW; + + // Define test API functions in the sandbox. + const TEST_API = ['is', 'ok', 'info']; + TEST_API.forEach(function (name) { sandbox[name] = window[name]; }); + + + function COWTests() { + + var empty = {}; + var cow = getCOW(empty); + + // Because private fields may not be enabled, we construct A via the below eval of an IFFE, + // and return early if it syntax errors. + var A; + try { + A = eval(`(function(){ + class Base { + constructor(o) { + return o; + } + }; + + class A extends Base { + #x = 12; + static gx(o) { + return o.#x; + } + + static sx(o, v) { + o.#x = v; + } + }; + return A; + })();`); + } catch (e) { + is(e instanceof SyntaxError, true, "Syntax error: Private fields not enabled"); + is(/private fields are not currently supported/.test(e.message), true, "correct message"); + return; + } + + new A(empty); + is(A.gx(empty), 12, "Correct value read"); + A.sx(empty, 'wrapped'); + + function assertThrewInstance(f, error) { + var threw = true; + try { + f(); + threw = false; + } catch (e) { + is(e instanceof error, true, "Correct Error"); + } + is(threw, true, "Threw!"); + } + + // Note: These throw warnings: + // + // WARNING: Silently denied access to property ##x: Access to privileged JS object not permitted (@chrome://mochitests/content/chrome/js/xpconnect/tests/chrome/test_private_field_cows.xhtml:108:27): file /js/xpconnect/wrappers/XrayWrapper.cpp, line 226 + // + // It's not clear to me if we ougth to wire this up to -not-? I suspect this is a result of invoking + // the has + assertThrewInstance(() => A.gx(cow), TypeError); + assertThrewInstance(() => A.sx(cow, 'unwrapped'), TypeError); + assertThrewInstance(() => new A(cow), Error); + assertThrewInstance(() => A.gx(cow), TypeError); + } + + // Stringify the COW test suite and directly evaluate it in the sandbox. + Cu.evalInSandbox('(' + COWTests.toString() + ')()', sandbox); + + // Test that COWed objects passing from content to chrome get unwrapped. + function returnCOW() { + return getCOW({ + bar: 6 + }); + } + + // eslint-disable-next-line no-unused-vars + var unwrapped = Cu.evalInSandbox( + '(' + returnCOW.toString() + ')()', + sandbox + ); + + ok(true, "passed"); + }); + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_sandboxImport.xhtml b/js/xpconnect/tests/chrome/test_sandboxImport.xhtml new file mode 100644 index 0000000000..1ae1f02ad7 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_sandboxImport.xhtml @@ -0,0 +1,37 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=533596 +--> +<window title="Mozilla Bug 533596" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + + function checkWrapped(obj) { + var utils = window.windowUtils; + is(utils.getClassName(obj), "Proxy", "right type of wrapper"); + } + + var sandbox = new Cu.Sandbox("about:blank"); + sandbox.importFunction(function() { return "PASS"; }, "foo"); + sandbox.importFunction(function bar() { return "PASS"; }); + sandbox.importFunction(checkWrapped); + is(Cu.evalInSandbox("foo()", sandbox), "PASS", "importFunction works"); + is(Cu.evalInSandbox("bar()", sandbox), "PASS", "importFunction works"); + Cu.evalInSandbox("checkWrapped({})", sandbox); + + var importer = sandbox.importFunction; + importer(function() { return "PASS"; }, "bar"); + is(Cu.evalInSandbox("bar()", sandbox), "PASS", "unbound importFunction works"); + is(typeof this.bar, "undefined", "didn't import into our global"); + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_scriptSettings.xhtml b/js/xpconnect/tests/chrome/test_scriptSettings.xhtml new file mode 100644 index 0000000000..f78b921466 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_scriptSettings.xhtml @@ -0,0 +1,128 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=937317 +--> +<window title="Mozilla Bug 937317" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=937317" + target="_blank">Mozilla Bug 937317</a> + </body> + + <!-- test code goes here --> + <iframe src="./file_empty.html"></iframe> + <script type="application/javascript"> + <![CDATA[ + + /** Test for the script settings stack. **/ + SimpleTest.waitForExplicitFinish(); + SpecialPowers.pushPrefEnv({"set": [["security.allow_eval_with_system_principal", + true]]}); + addLoadEvent(function() { + const {PromiseUtils} = ChromeUtils.import("resource://gre/modules/PromiseUtils.jsm"); + let iwin = window[0]; + + // Smoketest. + is(Cu.getIncumbentGlobal(), window, "smoketest"); + + // Calling a cross-compartment non-scripted function changes the + // compartment, but not the incumbent script settings object. + var sb = new Cu.Sandbox(window, { wantComponents: true }); + is(sb.Components.utils.getIncumbentGlobal(), window, "cross-compartment sb non-scripted"); + is(iwin.Components.utils.getIncumbentGlobal(), window, "cross-compartment win non-scripted"); + + // If we call a scripted function in the other compartment, that becomes + // the incumbent script. + function gib() { return Cu.getIncumbentGlobal(); }; + Cu.evalInSandbox(gib.toSource(), sb); + iwin.eval(gib.toSource()); + is(sb.gib(), sb, "cross-compartment sb scripted"); + is(iwin.gib(), iwin, "cross-compartment win scripted"); + + // Eval-ing top-level script in another component makes that compartment the + // incumbent script. + is(Cu.evalInSandbox('Components.utils.getIncumbentGlobal()', sb), sb, 'eval sb'); + is(iwin.eval('Components.utils.getIncumbentGlobal()'), iwin, 'eval iwin'); + + // Make sure that the callback mechanism works. + function makeCallback(expectedGlobal, deferred, kind) { + function cb(incumbentGlobal) { + is(incumbentGlobal, expectedGlobal, "Callback got the right incumbent global: " + kind); + if (deferred) + deferred.resolve(); + } + info("Generated callback: " + kind); + return cb; + } + + var bound = Cu.getIncumbentGlobal.bind(Cu, makeCallback(window, undefined, "simple bound")); + is(bound(), window, "Bound method returns the right global"); + + // Callbacks grab the incumbent script at the time of invocation. + // + // Note - We avoid calling the initial defer |d| so that it's not in-scope for everything below. + let initialDefer = PromiseUtils.defer(); + setTimeout(Cu.getIncumbentGlobal.bind(Cu, makeCallback(window, initialDefer, "same-global setTimeout")), 0); + initialDefer.promise.then(function() { + + // Try cross-global setTimeout where |window| is the incumbent script when the callback is created. + let d = PromiseUtils.defer(); + iwin.setTimeout(Cu.getIncumbentGlobal.bind(Cu, makeCallback(window, d, "cross-global setTimeout by |window|")), 0); + return d.promise; + }).then(function() { + + // Try cross-global setTimeout where |iwin| is the incumbent script when the callback is created. + let d = PromiseUtils.defer(); + iwin.wrappedJSObject.timeoutFun = Cu.getIncumbentGlobal.bind(Cu, makeCallback(iwin, d, "cross-global setTimeout by |iwin|")); + iwin.eval('setTimeout(timeoutFun, 0);'); + return d.promise; + }).then(function() { + + // The incumbent script override doesn't take effect if the callback is scripted. + let d = PromiseUtils.defer(); + iwin.wrappedJSObject.timeoutFun2 = Cu.getIncumbentGlobal.bind(Cu, makeCallback(iwin, d, "cross-global setTimeout of scripted function")); + iwin.eval('var timeoutFun2Wrapper = function() { timeoutFun2(); }'); + setTimeout(iwin.wrappedJSObject.timeoutFun2Wrapper, 0); + return d.promise; + }).then(function() { + + // Try event listeners. + let d = PromiseUtils.defer(); + let body = iwin.document.body; + body.addEventListener('click', Cu.getIncumbentGlobal.bind(Cu, makeCallback(window, d, "cross-global event listener"))); + body.dispatchEvent(new iwin.MouseEvent('click')); + return d.promise; + + }).then(function() { + + // Try an event handler set by |iwin|. + let d = PromiseUtils.defer(); + let body = iwin.document.body; + iwin.wrappedJSObject.handler = Cu.getIncumbentGlobal.bind(Cu, makeCallback(iwin, d, "cross-global event handler")); + iwin.eval('document.body.onmousemove = handler'); + body.dispatchEvent(new iwin.MouseEvent('mousemove')); + return d.promise; + + }).then(function() { + + // Try an event handler compiled by a content attribute. + let d = PromiseUtils.defer(); + let body = iwin.document.body; + iwin.wrappedJSObject.innerHandler = Cu.getIncumbentGlobal.bind(Cu, makeCallback(iwin, d, "cross-global compiled event handler")); + iwin.eval("document.body.setAttribute('onmouseout', 'innerHandler()')"); + body.dispatchEvent(new iwin.MouseEvent('mouseout')); + return d.promise; + }).then(function() { + + SimpleTest.finish(); + }); + }); + + ]]> + </script> +</window> diff --git a/js/xpconnect/tests/chrome/test_scripterror.html b/js/xpconnect/tests/chrome/test_scripterror.html new file mode 100644 index 0000000000..38cb316467 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_scripterror.html @@ -0,0 +1,87 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Tests for nsIScriptError</title> +<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> +<div id="log"></div> +<script> +function awaitScriptError(fun) { + // Use setTimeout in order to prevent throwing from test frame + // and to have a clean stack frame. + setTimeout(fun, 0) + + return new Promise(resolve => { + const observer = { + QueryInterface: ChromeUtils.generateQI(["nsIObserver"]), + observe(message) { + if (!(message instanceof Ci.nsIScriptError)) { + return; + } + + Services.console.unregisterListener(observer); + resolve(message); + } + }; + + Services.console.registerListener(observer); + }); +} + +function hasExpectedProperties(message, exception) { + is(message.hasException, true, "has exception"); + is(message.exception, exception, "has correct exception"); + + ok(message.stack != null, "has stack"); + is(message.stack?.source, location.href, "correct stack source") + + is(message.sourceName, location.href, "has correct sourceName/filename"); + ok(message.lineNumber > 0, "has lineNumber"); + + is(message.innerWindowID, window.windowGlobalChild.innerWindowId, + "correct innerWindowID"); +} + +add_task(async () => { + await SpecialPowers.pushPrefEnv({"set": [ + ["javascript.options.asyncstack_capture_debuggee_only", false], + ]}); + + const TESTS = [ + "abc", + new Error("foobar"), + {foo: "bar"} + ]; + + for (let test of TESTS) { + // First test as regular throw + SimpleTest.expectUncaughtException(); + let message = await awaitScriptError(function testName() { + throw test; + }); + hasExpectedProperties(message, test); + is(message.isPromiseRejection, false, "not a rejected promise"); + + // Now test as uncaught promise rejection + message = await awaitScriptError(function testName() { + Promise.reject(test); + }); + hasExpectedProperties(message, test); + is(message.isPromiseRejection, true, "is a rejected promise"); + + // Uncaught rejection from async function + message = await awaitScriptError(async function testName() { + throw test; + }); + hasExpectedProperties(message, test); + is(message.isPromiseRejection, true, "is a rejected promise"); + + // Uncaught rejection from then callback + message = await awaitScriptError(async function testName() { + Promise.resolve().then(() => { + throw test; + }); + }); + hasExpectedProperties(message, test); + is(message.isPromiseRejection, true, "is a rejected promise"); + } +}); +</script> diff --git a/js/xpconnect/tests/chrome/test_secureContexts.html b/js/xpconnect/tests/chrome/test_secureContexts.html new file mode 100644 index 0000000000..956e609d5f --- /dev/null +++ b/js/xpconnect/tests/chrome/test_secureContexts.html @@ -0,0 +1,58 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1273687 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1430164</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://global/skin"/> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <iframe id="t" src="https://example.com"></iframe> + <iframe id="i" src="http://example.com"></iframe> + <script type="application/javascript"> + /** Test for Bug 1273687 **/ + SimpleTest.waitForExplicitFinish(); + + window.onload = () => { + /* globals t, i */ + runTest(t, true); + runTest(i, false); + + // Check we can inherit the system principal + var s = new Cu.Sandbox(window, { wantGlobalProperties: ["isSecureContext"] } ); + s.ok = ok; + Cu.evalInSandbox('ok(isSecureContext)', s); + + // Check options insecure works + let sb = new Cu.Sandbox('https://www.example.com', + { forceSecureContext: false, + wantGlobalProperties: + ["isSecureContext"] + }); + ok(!Cu.evalInSandbox('isSecureContext', sb)); + + // Check options secure works + let sb2 = new Cu.Sandbox('https://www.example.com', + { forceSecureContext: true, + wantGlobalProperties: + ["isSecureContext"] + }); + ok(Cu.evalInSandbox('isSecureContext', sb2)); + SimpleTest.finish(); + }; + + // Check dom window inheritance works + function runTest(ifr, expectIsSecureContext) { + let frameWin = ifr.contentWindow; + let s = new Cu.Sandbox(frameWin, { wantGlobalProperties: ["isSecureContext"] }); + is(expectIsSecureContext, Cu.evalInSandbox('isSecureContext', s)); + + // Ensure the implementation of 'wantGlobalProperties' matches the DOM window prototype + let s2 = new Cu.Sandbox(frameWin, { sandboxPrototype: frameWin }); + is(expectIsSecureContext, Cu.evalInSandbox('isSecureContext', s2)); + } + </script> +</head> +</html> diff --git a/js/xpconnect/tests/chrome/test_sharedChromeCompartment.html b/js/xpconnect/tests/chrome/test_sharedChromeCompartment.html new file mode 100644 index 0000000000..b653f19751 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_sharedChromeCompartment.html @@ -0,0 +1,63 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1517694 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1517694</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://global/skin"/> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <script type="application/javascript"> +"use strict"; + +/** Test for Bug 1517694 **/ +const { XPCOMUtils } = ChromeUtils.importESModule( + "resource://gre/modules/XPCOMUtils.sys.mjs" +); + +SimpleTest.waitForExplicitFinish(); + +function go() { + var frame = $('subframe'); + frame.onload = null; + + var isSameCompartment = Cu.getJSTestingFunctions().isSameCompartment; + + ok(isSameCompartment(window, frame.contentWindow), + "System window is in same compartment"); + + var sameCompSb = Cu.Sandbox(window); + ok(isSameCompartment(window, sameCompSb), + "System sandbox is in same compartment"); + + var ownCompSb = Cu.Sandbox(window, {freshCompartment: true}); + ok(!isSameCompartment(window, ownCompSb), + "Sandbox created with freshCompartment is in separate compartment"); + + // Sandbox created in fresh-compartment sandbox must be in shared + // compartment. + var sb = Cu.evalInSandbox(` + let principal = + Cc["@mozilla.org/systemprincipal;1"].getService(Ci.nsIPrincipal); + Cu.Sandbox(principal) + `, ownCompSb); + ok(isSameCompartment(window, sb), + "System sandbox created in different compartment is in system compartment"); + + ok(isSameCompartment(window, XPCOMUtils), + "Object defined in JSM is in same compartment"); + + SimpleTest.finish(); +} + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1517694">Mozilla Bug 1517694</a> + +<iframe id="subframe" src="file_empty.html" onload="go()"></iframe> + +</body> +</html> diff --git a/js/xpconnect/tests/chrome/test_weakmap_keys_preserved.xhtml b/js/xpconnect/tests/chrome/test_weakmap_keys_preserved.xhtml new file mode 100644 index 0000000000..c7c5d4369d --- /dev/null +++ b/js/xpconnect/tests/chrome/test_weakmap_keys_preserved.xhtml @@ -0,0 +1,33 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=673468 +--> +<window title="Mozilla Bug " + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=" + target="_blank">Mozilla Bug 673468</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 673468 **/ + + let system = Cc["@mozilla.org/systemprincipal;1"].createInstance(); + let sandbox = Cu.Sandbox(system); + let map = new sandbox.WeakMap(); + let obj = {}; + map.set(obj, {}); + + Cu.forceGC(); + + ok(map.has(obj), "Weakmap still contains our wrapper!"); + ]]> + </script> +</window> diff --git a/js/xpconnect/tests/chrome/test_weakmap_keys_preserved2.xhtml b/js/xpconnect/tests/chrome/test_weakmap_keys_preserved2.xhtml new file mode 100644 index 0000000000..faaaa8b9ac --- /dev/null +++ b/js/xpconnect/tests/chrome/test_weakmap_keys_preserved2.xhtml @@ -0,0 +1,80 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=673468 +--> +<window title="Mozilla Bug " + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a id="testelem" href="https://bugzilla.mozilla.org/show_bug.cgi?id=" + target="_blank">Mozilla Bug 673468</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + /** Test for Bug 673468 **/ + SimpleTest.waitForExplicitFinish(); + SpecialPowers.DOMWindowUtils.garbageCollect(); + + let get_live_dom = function () { + return document.getElementById("testelem"); + }; + + let wrappers_as_keys_test = function () { + let e = new MessageEvent("foo", { bubbles: false, cancellable: false, + data: { dummy: document.createXULElement("foo") }}); + window.eeeevent = e; + + let live_dom = e.data.dummy; + let dead_dom = document.createElementNS("http://www.w3.org/1999/xhtml", "div"); + let dead_child = document.createElementNS("http://www.w3.org/1999/xhtml", "div"); + dead_dom.appendChild(dead_child); + is(dead_dom.children.length, 1, "children have wrong length"); + let wrappee = {}; + + dead_dom.abcxyz = wrappee; + + let system = Cc["@mozilla.org/systemprincipal;1"].createInstance(); + let sandbox = Cu.Sandbox(system); + + sandbox.wrapper = wrappee; + sandbox.value = dead_dom; + let map = Cu.evalInSandbox("wm = new WeakMap(); wm.set(wrapper, value); wm", sandbox); + sandbox.wrapper = null; + sandbox.value = null; + + live_dom.xyzabc = {wrappee, m: map, sb: sandbox}; + + let key = ChromeUtils.nondeterministicGetWeakMapKeys(map)[0]; + let value = map.get(key); + is(value.children.length, 1, "children have wrong length"); + } + + wrappers_as_keys_test(); + + let check_wrappers_as_keys = function () { + let live_dom = window.eeeevent.data.dummy; + let live_map = live_dom.xyzabc.m; + is(ChromeUtils.nondeterministicGetWeakMapKeys(live_map).length, 1, + "Map should not be empty."); + let key = ChromeUtils.nondeterministicGetWeakMapKeys(live_map)[0]; + let value = live_map.get(key); + is(value.children.length, 1, "children have wrong length"); + } + + Cu.schedulePreciseGC(function () { + SpecialPowers.DOMWindowUtils.cycleCollect(); + SpecialPowers.DOMWindowUtils.garbageCollect(); + + check_wrappers_as_keys(); + SimpleTest.finish(); + }); + + ]]> + </script> +</window> diff --git a/js/xpconnect/tests/chrome/test_weakref.xhtml b/js/xpconnect/tests/chrome/test_weakref.xhtml new file mode 100644 index 0000000000..21986cbf34 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_weakref.xhtml @@ -0,0 +1,32 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=484459 +--> +<window title="Weakrefs" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <iframe type="content" id="ifr"> + </iframe> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + SimpleTest.waitForExplicitFinish(); + var util = window.windowUtils; + var weakUtil = Cu.getWeakReference(util); + util = null; + + function callback() { + ok(weakUtil.get(), "Should still be alive here"); + SimpleTest.finish(); + } + + SpecialPowers.exactGC(callback); + ]]></script> +</window> diff --git a/js/xpconnect/tests/chrome/test_windowProxyDeadWrapper.html b/js/xpconnect/tests/chrome/test_windowProxyDeadWrapper.html new file mode 100644 index 0000000000..7970c1ae70 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_windowProxyDeadWrapper.html @@ -0,0 +1,76 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1223372 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1223372</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://global/skin"/> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + +/** Test for Bug 1223372 **/ +const {TestUtils} = ChromeUtils.import("resource://testing-common/TestUtils.jsm"); + +async function go() { + SimpleTest.waitForExplicitFinish(); + await SpecialPowers.pushPrefEnv({"set": [["security.allow_eval_with_system_principal", + true]]}); + + var frame = $('subframe'); + frame.onload = null; + + var w = frame.contentWindow; + + w.eval("checkDead = function() { return Components.utils.isDeadWrapper(this); };"); + var checkDead = w.checkDead; + + w.eval("getObject = function() { return {}; }"); + var getObject = w.getObject; + + ok(!checkDead(), "WindowProxy shouldn't be dead yet"); + + // Load a content page in the chrome frame. + w.location = "https://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html"; + tryWindow(); + + function tryWindow() { + if (w.document.title != 'empty test page') { + info("Document not loaded yet - retrying"); + SimpleTest.executeSoon(tryWindow); + return; + } + + let winID = w.docShell.outerWindowID; + // Remove the frame. This will nuke the WindowProxy wrapper from our chrome + // document's global, so evaluating 'this' in it will return a dead wrapper + // once the window is destroyed. + frame.remove(); + + TestUtils.topicObserved("outer-window-nuked", (subject, data) => { + let id = subject.QueryInterface(Ci.nsISupportsPRUint64).data; + return id == winID; + }).then(() => { + ok(checkDead(), "Expected a dead object wrapper"); + + // Wrapping the Window should return a dead wrapper now. + var global = Cu.getGlobalForObject(getObject()); + ok(Cu.isDeadWrapper(global), + "Expected a dead wrapper when requesting the window's global"); + + SimpleTest.finish(); + }); + } +} + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1223372">Mozilla Bug 1223372</a> + +<iframe id="subframe" src="./file_empty.html" onload="go()"></iframe> + +</body> +</html> diff --git a/js/xpconnect/tests/chrome/test_wrappers.xhtml b/js/xpconnect/tests/chrome/test_wrappers.xhtml new file mode 100644 index 0000000000..73c808a9df --- /dev/null +++ b/js/xpconnect/tests/chrome/test_wrappers.xhtml @@ -0,0 +1,85 @@ +<?xml version="1.0"?> +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" + type="text/css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=500931 +--> +<window title="Mozilla Bug 500931" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=533596" + target="_blank">Mozilla Bug 533596</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"><![CDATA[ + + /** Test for Bug 533596 **/ + + function go() { + var win = $('ifr').contentWindow; + var utils = window.windowUtils; + is(utils.getClassName(window), "Proxy", "our window is wrapped correctly") + is(utils.getClassName(location), "Location", "chrome doesn't have location wrappers") + is(utils.getClassName(win), "Proxy", "win is an Proxy"); + is(utils.getClassName(win.location), "Proxy", "deep wrapping works"); + is(win.location.href, "https://example.org/tests/js/xpconnect/tests/mochitest/chrome_wrappers_helper.html", + "can still get strings out"); + + var unsafeWin = win.wrappedJSObject; + is(utils.getClassName(unsafeWin), "Proxy", "can get a Proxy"); + is(utils.getClassName(unsafeWin.location), "Proxy", "deep wrapping works"); + + Object.defineProperty(unsafeWin, "defprop1", { value: 1, writable: true, enumerable: true, configurable: true }); + /* TODO (bug 552854): the getter isn't visible in content. + function checkWrapper(val) { + ok(utils.getClassName(val) == "Proxy", "wrapped properly"); + } + Object.defineProperty(unsafeWin, "defprop2", { set: checkWrapper, enumerable: true, configurable: true }); + */ + unsafeWin.run_test(ok, win, unsafeWin); + + win.setTimeout(function() { + is(utils.getClassName(this), "Proxy", + "this is wrapped correctly"); + SimpleTest.finish(); + }, 0) + + var saw0 = false; + for (let i in $('ifr').contentDocument.getElementsByTagName('body')) { + if (i === "0") + saw0 = true; + } + ok(saw0, "properly enumerated the 0 value"); + + ok(win.XPathEvaluator.toString().includes("XPathEvaluator"), + "Can access content window.XPathEvaluator"); + + var nativeToString = + ("" + Math.sin).replace("sin", "EventTarget"); + var eventTargetToString = "" + win.EventTarget; + ok(eventTargetToString.indexOf(nativeToString) > -1, + "Stringifying a DOM interface object should return the same string as " + + "stringifying a native function. " + eventTargetToString + " " + nativeToString); + + is(win.XPathResult.NUMBER_TYPE, 1, "can access constants on constructors"); + is(typeof win.IDBKeyRange.bound, "function", "can access crazy IDBKeyRange static functions"); + + // Test getter/setter lookup on Xray wrappers. + ok(Object.prototype.__lookupGetter__.call(win.document, 'title'), 'found getter on document'); + ok(Object.prototype.__lookupGetter__.call(win.document, 'title'), 'found getter on document'); + } + + SimpleTest.waitForExplicitFinish(); + + ]]></script> + <iframe type="content" + src="https://example.org/tests/js/xpconnect/tests/mochitest/chrome_wrappers_helper.html" + onload="go()" + id="ifr"> + </iframe> +</window> diff --git a/js/xpconnect/tests/chrome/test_xrayLargeTypedArray.html b/js/xpconnect/tests/chrome/test_xrayLargeTypedArray.html new file mode 100644 index 0000000000..dcb0b87380 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_xrayLargeTypedArray.html @@ -0,0 +1,47 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1674777 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 1674777</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://global/skin"/> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + +/** Test for Bug 1674777 **/ + +function go() { + SimpleTest.waitForExplicitFinish(); + + let win = document.getElementById('ifr').contentWindow; + + const nbytes = 3 * 1024 * 1024 * 1024; // 3 GB. + let tarray = new win.Int8Array(nbytes); + ok(Cu.isXrayWrapper(tarray), "Should be Xray"); + is(tarray.length, nbytes, "Length should match"); + is(tarray.byteLength, nbytes, "byteLength should match"); + + // Expect OOM when getting all property names. + let ex; + try { + Object.getOwnPropertyNames(tarray); + } catch (e) { + ex = e; + } + is(ex, "out of memory", "Expected OOM"); + + SimpleTest.finish(); +} + + </script> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1674777">Mozilla Bug 1674777</a> + +<iframe id="ifr" onload="go();" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" /> + +</body> +</html> diff --git a/js/xpconnect/tests/chrome/test_xrayToJS.xhtml b/js/xpconnect/tests/chrome/test_xrayToJS.xhtml new file mode 100644 index 0000000000..fbfa67e61d --- /dev/null +++ b/js/xpconnect/tests/chrome/test_xrayToJS.xhtml @@ -0,0 +1,1191 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=933681 +--> +<window title="Mozilla Bug 933681" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=933681" + target="_blank">Mozilla Bug 933681</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + + /** Test for ES constructors on Xrayed globals. **/ + SimpleTest.waitForExplicitFinish(); + let global = Cu.getGlobalForObject.bind(Cu); + + function checkThrows(f, rgxp, msg) { + try { + f(); + ok(false, "Should have thrown: " + msg); + } catch (e) { + ok(true, "Threw as expected: " + msg); + ok(rgxp.test(e), "Message correct: " + e); + } + } + + var { AppConstants } = SpecialPowers.ChromeUtils.import( + "resource://gre/modules/AppConstants.jsm" + ); + var isNightlyBuild = AppConstants.NIGHTLY_BUILD; + var isReleaseOrBeta = AppConstants.RELEASE_OR_BETA; + + let typedArrayClasses = ['Uint8Array', 'Int8Array', 'Uint16Array', 'Int16Array', + 'Uint32Array', 'Int32Array', 'Float32Array', 'Float64Array', + 'Uint8ClampedArray']; + let errorObjectClasses = ['Error', 'InternalError', 'EvalError', 'RangeError', 'ReferenceError', + 'SyntaxError', 'TypeError', 'URIError', 'AggregateError']; + + // A simpleConstructors entry can either be the name of a constructor as a + // string, or an object containing the properties `name`, and `args`. + // In the former case, the constructor is invoked without any args; in the + // latter case, it is invoked with `args` as the arguments list. + let simpleConstructors = ['Object', 'Function', 'Array', 'Boolean', 'Date', 'Number', + 'String', 'RegExp', 'ArrayBuffer', 'WeakMap', 'WeakSet', 'Map', 'Set', + {name: 'Promise', args: [function(){}]}]; + + // All TypedArray constructors can be called with zero arguments. + simpleConstructors = simpleConstructors.concat(typedArrayClasses); + + // All Error constructors except AggregateError can be called with zero arguments. + simpleConstructors = simpleConstructors.concat(errorObjectClasses.filter(name => { + return name !== 'AggregateError'; + })); + + function go() { + window.iwin = document.getElementById('ifr').contentWindow; + /* global iwin */ + + // Test constructors that can be instantiated with zero arguments, or with + // a fixed set of arguments provided using `...rest`. + for (let c of simpleConstructors) { + var args = []; + if (typeof c === 'object') { + args = c.args; + c = c.name; + } + ok(iwin[c], "Constructors appear: " + c); + is(iwin[c], Cu.unwaiveXrays(iwin.wrappedJSObject[c]), + "we end up with the appropriate constructor: " + c); + is(Cu.unwaiveXrays(Cu.waiveXrays(new iwin[c](...args)).constructor), iwin[c], + "constructor property is set up right: " + c); + let expectedProto = Cu.isOpaqueWrapper(new iwin[c](...args)) ? + iwin.Object.prototype : iwin[c].prototype; + is(Object.getPrototypeOf(new iwin[c](...args)), expectedProto, + "prototype is correct: " + c); + is(global(new iwin[c](...args)), iwin, "Got the right global: " + c); + } + + // Test Object in more detail. + var num = new iwin.Object(4); + is(Cu.waiveXrays(num).valueOf(), 4, "primitive object construction works"); + is(global(num), iwin, "correct global for num"); + var obj = new iwin.Object(); + obj.foo = 2; + var withProto = Cu.unwaiveXrays(Cu.waiveXrays(iwin).Object.create(obj)); + is(global(withProto), iwin, "correct global for withProto"); + is(Cu.waiveXrays(withProto).foo, 2, "Inherits properly"); + + // Test Function. + var primitiveFun = new iwin.Function('return 2'); + is(global(primitiveFun), iwin, "function construction works"); + is(primitiveFun(), 2, "basic function works"); + var doSetFoo = new iwin.Function('arg', 'arg.foo = 2;'); + is(global(doSetFoo), iwin, "function with args works"); + try { + doSetFoo({}); + ok(false, "should have thrown while setting property on object"); + } catch (e) { + ok(!!/denied/.test(e), "Threw correctly: " + e); + } + var factoryFun = new iwin.Function('return {foo: 32}'); + is(global(factoryFun), iwin, "proper global for factoryFun"); + is(factoryFun().foo, 32, "factoryFun invokable"); + is(global(factoryFun()), iwin, "minted objects live in the content scope"); + testXray('Function', factoryFun, new iwin.Function(), ['length', 'name']); + var echoThis = new iwin.Function('return this;'); + echoThis.wrappedJSObject.bind = 42; + var boundEchoThis = echoThis.bind(document); + is(boundEchoThis(), document, "bind() works correctly over Xrays"); + is(global(boundEchoThis), window, "bound functions live in the caller's scope"); + ok(/return this/.test(echoThis.toSource()), 'toSource works: ' + echoThis.toSource()); + ok(/return this/.test(echoThis.toString()), 'toString works: ' + echoThis.toString()); + is(iwin.Function.prototype, Object.getPrototypeOf(echoThis), "Function.prototype works for standard classes"); + is(echoThis.prototype, undefined, "Function.prototype not visible for non standard constructors"); + iwin.eval('var foopyFunction = function namedFoopyFunction(a, b, c) {}'); + var foopyFunction = Cu.unwaiveXrays(Cu.waiveXrays(iwin).foopyFunction); + ok(Cu.isXrayWrapper(foopyFunction), "Should be Xrays"); + is(foopyFunction.name, "namedFoopyFunction", ".name works over Xrays"); + is(foopyFunction.length, 3, ".length works over Xrays"); + ok(Object.getOwnPropertyNames(foopyFunction).includes('length'), "Should list length"); + ok(Object.getOwnPropertyNames(foopyFunction).includes('name'), "Should list name"); + ok(!Object.getOwnPropertyNames(foopyFunction).includes('prototype'), "Should not list prototype"); + ok(Object.getOwnPropertyNames(iwin.Array).includes('prototype'), "Should list prototype for standard constructor"); + + // Test BoundFunction. + iwin.eval('var boundFoopyFunction = foopyFunction.bind(null, 1)'); + var boundFoopyFunction = Cu.unwaiveXrays(Cu.waiveXrays(iwin).boundFoopyFunction); + is(boundFoopyFunction.name, "bound namedFoopyFunction", "bound .name works over Xrays"); + is(boundFoopyFunction.length, 2, "bound .length works over Xrays"); + is(JSON.stringify(Object.getOwnPropertyNames(boundFoopyFunction).sort()), '["length","name"]', "Should list length and name"); + // Mutate .name, it's just a data property. + iwin.eval('Object.defineProperty(boundFoopyFunction, "name", {value: "foobar", configurable: true, writable: true});'); + is(boundFoopyFunction.name, "foobar", "mutated .name works over Xrays"); + iwin.eval('boundFoopyFunction.name = 123;'); + is(boundFoopyFunction.name, undefined, "only support string for .name"); + iwin.eval('delete boundFoopyFunction.name'); + is(boundFoopyFunction.name, undefined, "deleted .name works over Xrays"); + // Mutate .length. + iwin.eval('Object.defineProperty(boundFoopyFunction, "length", {value: 456, configurable: true, writable: true});'); + is(boundFoopyFunction.length, 456, "mutated .length works over Xrays"); + iwin.eval('boundFoopyFunction.length = "bar";'); + is(boundFoopyFunction.length, undefined, "only support number for .length"); + + // Test proxies. + var targetObject = new iwin.Object(); + targetObject.foo = 9; + var forwardingProxy = new iwin.Proxy(targetObject, new iwin.Object()); + is(global(forwardingProxy), iwin, "proxy global correct"); + is(Cu.waiveXrays(forwardingProxy).foo, 9, "forwards correctly"); + + // Test AggregateError. + { + // AggregateError throws when called without an iterable object as its first argument. + let args = [new iwin.Array()]; + + ok(iwin.AggregateError, "AggregateError constructor is present"); + is(iwin.AggregateError, Cu.unwaiveXrays(iwin.wrappedJSObject.AggregateError), + "we end up with the appropriate AggregateError constructor"); + is(Cu.unwaiveXrays(Cu.waiveXrays(new iwin.AggregateError(...args)).constructor), iwin.AggregateError, + "AggregateError constructor property is set up right"); + let expectedProto = Cu.isOpaqueWrapper(new iwin.AggregateError(...args)) ? + iwin.Object.prototype : iwin.AggregateError.prototype; + is(Object.getPrototypeOf(new iwin.AggregateError(...args)), expectedProto, + "AggregateError prototype is correct"); + is(global(new iwin.AggregateError(...args)), iwin, "Got the right global for AggregateError"); + } + + // Test eval. + var toEval = "({a: 2, b: {foo: 'bar'}, f: function() { return window; }})"; + is(global(iwin.eval(toEval)), iwin, "eval creates objects in the correct global"); + is(iwin.eval(toEval).b.foo, 'bar', "eval-ed object looks right"); + is(Cu.waiveXrays(iwin.eval(toEval)).f(), Cu.waiveXrays(iwin), "evaled function works right"); + + testDate(); + + testObject(); + + testArray(); + + testTypedArrays(); + + testErrorObjects(); + + testRegExp(); + + testPromise(); + + testArrayBuffer(); + + testMap(); + + testSet(); + + testWeakMap(); + + testWeakSet(); + + testProxy(); + + testDataView(); + + testNumber(); + + SimpleTest.finish(); + } + + // Maintain a static list of the properties that are available on each standard + // prototype, so that we make sure to audit any new ones to make sure they're + // Xray-safe. + // + // DO NOT CHANGE WTIHOUT REVIEW FROM AN XPCONNECT PEER. + var gPrototypeProperties = {}; + var gConstructorProperties = {}; + function constructorProps(arr) { + // Some props live on all constructors + return arr.concat(["prototype", "length", "name"]); + } + gPrototypeProperties.Date = + ["getTime", "getTimezoneOffset", "getYear", "getFullYear", "getUTCFullYear", + "getMonth", "getUTCMonth", "getDate", "getUTCDate", "getDay", "getUTCDay", + "getHours", "getUTCHours", "getMinutes", "getUTCMinutes", "getSeconds", + "getUTCSeconds", "getMilliseconds", "getUTCMilliseconds", "setTime", + "setYear", "setFullYear", "setUTCFullYear", "setMonth", "setUTCMonth", + "setDate", "setUTCDate", "setHours", "setUTCHours", "setMinutes", + "setUTCMinutes", "setSeconds", "setUTCSeconds", "setMilliseconds", + "setUTCMilliseconds", "toUTCString", "toLocaleString", + "toLocaleDateString", "toLocaleTimeString", "toDateString", "toTimeString", + "toISOString", "toJSON", "toSource", "toString", "valueOf", "constructor", + "toGMTString", Symbol.toPrimitive]; + gConstructorProperties.Date = constructorProps(["UTC", "parse", "now"]); + gPrototypeProperties.Object = + ["constructor", "toSource", "toString", "toLocaleString", "valueOf", + "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", + "__defineGetter__", "__defineSetter__", "__lookupGetter__", "__lookupSetter__", + "__proto__"]; + gConstructorProperties.Object = + constructorProps(["setPrototypeOf", "getOwnPropertyDescriptor", "getOwnPropertyDescriptors", + "keys", "is", "defineProperty", "defineProperties", "create", + "getOwnPropertyNames", "getOwnPropertySymbols", + "preventExtensions", "freeze", "fromEntries", "isFrozen", "seal", + "isSealed", "assign", "getPrototypeOf", "values", + "entries", "isExtensible", "hasOwn"]); + gPrototypeProperties.Array = + ["length", "toSource", "toString", "toLocaleString", "join", "reverse", "sort", "push", + "pop", "shift", "unshift", "splice", "concat", "slice", "lastIndexOf", "indexOf", + "includes", "forEach", "map", "reduce", "reduceRight", "filter", "some", "every", "find", + "findIndex", "copyWithin", "fill", Symbol.iterator, Symbol.unscopables, "entries", "keys", + "values", "constructor", "flat", "flatMap", "at", "findLast", "findLastIndex", + "toReversed", "toSorted", "toSpliced", "with"]; + gConstructorProperties.Array = + constructorProps(["isArray", "from", "fromAsync", "of", Symbol.species]); + for (let c of typedArrayClasses) { + gPrototypeProperties[c] = ["constructor", "BYTES_PER_ELEMENT"]; + gConstructorProperties[c] = constructorProps(["BYTES_PER_ELEMENT"]); + } + // There is no TypedArray constructor, looks like. + is(window.TypedArray, undefined, "If this ever changes, add to this test!"); + for (let c of errorObjectClasses) { + gPrototypeProperties[c] = ["constructor", "name", "message", "stack"]; + gConstructorProperties[c] = constructorProps([]); + } + // toString and toSource only live on the parent proto (Error.prototype). + gPrototypeProperties.Error.push('toString'); + gPrototypeProperties.Error.push('toSource'); + + gPrototypeProperties.Function = + ["constructor", "toSource", "toString", "apply", "call", "bind", + "length", "name", "arguments", "caller", Symbol.hasInstance]; + gConstructorProperties.Function = constructorProps([]) + + gPrototypeProperties.RegExp = + ["constructor", "toSource", "toString", "compile", "exec", "test", + Symbol.match, Symbol.matchAll, Symbol.replace, Symbol.search, Symbol.split, + "flags", "dotAll", "global", "hasIndices", "ignoreCase", "multiline", "source", "sticky", + "unicode"]; + gConstructorProperties.RegExp = + constructorProps(["input", "lastMatch", "lastParen", + "leftContext", "rightContext", "$1", "$2", "$3", "$4", + "$5", "$6", "$7", "$8", "$9", "$_", "$&", "$+", + "$`", "$'", Symbol.species]) + + gPrototypeProperties.Promise = + ["constructor", "catch", "then", "finally", Symbol.toStringTag]; + gConstructorProperties.Promise = + constructorProps(["resolve", "reject", "all", "allSettled", "any", "race", Symbol.species]); + + gPrototypeProperties.ArrayBuffer = + ["constructor", "byteLength", "slice", Symbol.toStringTag]; + gConstructorProperties.ArrayBuffer = + constructorProps(["isView", Symbol.species]); + + gPrototypeProperties.SharedArrayBuffer = ["constructor", "slice", "byteLength", Symbol.toStringTag]; + gConstructorProperties.SharedArrayBuffer = constructorProps([Symbol.species]); + + gPrototypeProperties.Map = + ["constructor", "size", Symbol.toStringTag, "get", "has", "set", "delete", + "keys", "values", "clear", "forEach", "entries", Symbol.iterator]; + gConstructorProperties.Map = + constructorProps([Symbol.species]); + + gPrototypeProperties.Set = + ["constructor", "size", Symbol.toStringTag, "has", "add", "delete", + "keys", "values", "clear", "forEach", "entries", Symbol.iterator]; + gConstructorProperties.Set = + constructorProps([Symbol.species]); + + gPrototypeProperties.WeakMap = + ["constructor", Symbol.toStringTag, "get", "has", "set", "delete"]; + gConstructorProperties.WeakMap = + constructorProps([]); + + gPrototypeProperties.WeakSet = + ["constructor", Symbol.toStringTag, "has", "add", "delete"]; + gConstructorProperties.WeakSet = + constructorProps([]); + + gPrototypeProperties.DataView = + ["constructor", "buffer", "byteLength", "byteOffset", Symbol.toStringTag, + "getInt8", "getUint8", "getInt16", "getUint16", + "getInt32", "getUint32", "getFloat32", "getFloat64", + "setInt8", "setUint8", "setInt16", "setUint16", + "setInt32", "setUint32", "setFloat32", "setFloat64", + "getBigInt64", "getBigUint64", "setBigInt64", "setBigUint64"] + gConstructorProperties.DataView = constructorProps([]); + + // Sort an array that may contain symbols as well as strings. + function sortProperties(arr) { + function sortKey(prop) { + return typeof prop + ":" + prop.toString(); + } + arr.sort((a, b) => sortKey(a) < sortKey(b) ? -1 : +1); + } + + // Sort all the lists so we don't need to mutate them later (or copy them + // again to sort them). + for (let c of Object.keys(gPrototypeProperties)) + sortProperties(gPrototypeProperties[c]); + for (let c of Object.keys(gConstructorProperties)) + sortProperties(gConstructorProperties[c]); + + function filterOut(array, props) { + return array.filter(p => !props.includes(p)); + } + + function isTypedArrayClass(classname) { + return typedArrayClasses.includes(classname); + } + + function propertyIsGetter(obj, name, classname) { + return !!Object.getOwnPropertyDescriptor(obj, name).get; + } + + function testProtoCallables(protoCallables, xray, xrayProto, localProto) { + for (let name of protoCallables) { + info("Running tests for property: " + name); + // Test both methods and getter properties. + function lookupCallable(obj) { + let desc = null; + do { + desc = Object.getOwnPropertyDescriptor(obj, name); + if (desc) { + break; + } + obj = Object.getPrototypeOf(obj); + } while (obj); + return desc ? (desc.get || desc.value) : undefined; + }; + ok(xrayProto.hasOwnProperty(name), `proto should have the property '${name}' as own`); + ok(!xray.hasOwnProperty(name), `instance should not have the property '${name}' as own`); + let method = lookupCallable(xrayProto); + is(typeof method, 'function', "Methods from Xrays are functions"); + is(global(method), window, "Methods from Xrays are local"); + ok(method instanceof Function, "instanceof works on methods from Xrays"); + is(lookupCallable(xrayProto), method, "Holder caching works properly"); + is(lookupCallable(xray), method, "Proto props resolve on the instance"); + let local = lookupCallable(localProto); + is(method.length, local.length, "Function.length identical"); + if (!method.length) { + is(method.call(xray) + "", local.call(xray) + "", + "Xray and local method results stringify identically"); + + // If invoking this method returns something non-Xrayable (opaque), the + // stringification is going to return [object Object]. + // This happens for set[@@iterator] and other Iterator objects. + let callable = lookupCallable(xray.wrappedJSObject); + if (!Cu.isOpaqueWrapper(method.call(xray)) && callable) { + is(method.call(xray) + "", + callable.call(xray.wrappedJSObject) + "", + "Xray and waived method results stringify identically"); + } + } + } + } + + function testCtorCallables(ctorCallables, xrayCtor, localCtor) { + for (let name of ctorCallables) { + // Don't try to test Function.prototype, since that is in fact a callable + // but doesn't really do the things we expect callables to do here + // (e.g. it's in the wrong global, since it gets Xrayed itself). + if (name == "prototype" && localCtor.name == "Function") { + continue; + } + info(`Running tests for property: ${localCtor.name}.${name}`); + // Test both methods and getter properties. + function lookupCallable(obj) { + let desc = null; + do { + desc = Object.getOwnPropertyDescriptor(obj, name); + obj = Object.getPrototypeOf(obj); + } while (!desc); + return desc.get || desc.value; + }; + + ok(xrayCtor.hasOwnProperty(name), "ctor should have the property as own"); + let method = lookupCallable(xrayCtor); + is(typeof method, 'function', "Methods from ctor Xrays are functions"); + is(global(method), window, "Methods from ctor Xrays are local"); + ok(method instanceof Function, + "instanceof works on methods from ctor Xrays"); + is(lookupCallable(xrayCtor), method, + "Holder caching works properly on ctors"); + let local = lookupCallable(localCtor); + is(method.length, local.length, + "Function.length identical for method from ctor"); + // Don't try to do the return-value check on Date.now(), since there is + // absolutely no reason it should return the same value each time. + // + // Also don't try to do the return-value check on Regexp.lastMatch and + // Regexp["$&"] (which are aliases), because they get state off the global + // they live in, as far as I can tell, so testing them over Xrays will be + // wrong: on the Xray they will actaully get the lastMatch of _our_ + // global, not the Xrayed one. + if (!method.length && + !(localCtor.name == "Date" && name == "now") && + !(localCtor.name == "RegExp" && (name == "lastMatch" || name == "$&"))) { + is(method.call(xrayCtor) + "", local.call(xrayCtor) + "", + "Xray and local method results stringify identically on constructors"); + is(method.call(xrayCtor) + "", + lookupCallable(xrayCtor.wrappedJSObject).call(xrayCtor.wrappedJSObject) + "", + "Xray and waived method results stringify identically"); + } + } + } + + function testXray(classname, xray, xray2, propsToSkip, ctorPropsToSkip = []) { + propsToSkip = propsToSkip || []; + let xrayProto = Object.getPrototypeOf(xray); + let localProto = window[classname].prototype; + let desiredProtoProps = Object.getOwnPropertyNames(localProto).sort(); + + is(desiredProtoProps.toSource(), + gPrototypeProperties[classname].filter(id => typeof id === "string").toSource(), + "A property on the " + classname + + " prototype has changed! You need a security audit from an XPConnect peer"); + is(Object.getOwnPropertySymbols(localProto).map(uneval).sort().toSource(), + gPrototypeProperties[classname].filter(id => typeof id !== "string").map(uneval).sort().toSource(), + "A symbol-keyed property on the " + classname + + " prototype has been changed! You need a security audit from an XPConnect peer"); + + let protoProps = filterOut(desiredProtoProps, propsToSkip); + let protoCallables = protoProps.filter(name => propertyIsGetter(localProto, name, classname) || + typeof localProto[name] == 'function' && + name != 'constructor'); + ok(!!protoCallables.length, "Need something to test"); + is(xrayProto, iwin[classname].prototype, "Xray proto is correct"); + is(xrayProto, xray.__proto__, "Proto accessors agree"); + var protoProto = classname == "Object" ? null : iwin.Object.prototype; + is(Object.getPrototypeOf(xrayProto), protoProto, "proto proto is correct"); + testProtoCallables(protoCallables, xray, xrayProto, localProto); + is(Object.getOwnPropertyNames(xrayProto).sort().toSource(), + protoProps.toSource(), "getOwnPropertyNames works"); + is(Object.getOwnPropertySymbols(xrayProto).map(uneval).sort().toSource(), + gPrototypeProperties[classname].filter(id => typeof id !== "string" && !propsToSkip.includes(id)) + .map(uneval).sort().toSource(), + "getOwnPropertySymbols works"); + + is(xrayProto.constructor, iwin[classname], "constructor property works"); + + xrayProto.expando = 42; + is(xray.expando, 42, "Xrayed instances see proto expandos"); + is(xray2.expando, 42, "Xrayed instances see proto expandos"); + + // Now test constructors + let localCtor = window[classname]; + let xrayCtor = xrayProto.constructor; + // We already checked that this is the same as iwin[classname] + + let desiredCtorProps = + Object.getOwnPropertyNames(localCtor).sort(); + is(desiredCtorProps.toSource(), + gConstructorProperties[classname].filter(id => typeof id === "string").toSource(), + "A property on the " + classname + + " constructor has changed! You need a security audit from an XPConnect peer"); + let desiredCtorSymbols = + Object.getOwnPropertySymbols(localCtor).map(uneval).sort() + is(desiredCtorSymbols.toSource(), + gConstructorProperties[classname].filter(id => typeof id !== "string").map(uneval).sort().toSource(), + "A symbol-keyed property on the " + classname + + " constructor has been changed! You need a security audit from an XPConnect peer"); + + let ctorProps = filterOut(desiredCtorProps, ctorPropsToSkip); + let ctorSymbols = filterOut(desiredCtorSymbols, ctorPropsToSkip.map(uneval)); + let ctorCallables = ctorProps.filter(name => propertyIsGetter(localCtor, name, classname) || + typeof localCtor[name] == 'function'); + testCtorCallables(ctorCallables, xrayCtor, localCtor); + is(Object.getOwnPropertyNames(xrayCtor).sort().toSource(), + ctorProps.toSource(), "getOwnPropertyNames works on Xrayed ctors"); + is(Object.getOwnPropertySymbols(xrayCtor).map(uneval).sort().toSource(), + ctorSymbols.toSource(), "getOwnPropertySymbols works on Xrayed ctors"); + } + + // We will need arraysEqual and testArrayIterators both in this global scope + // and in sandboxes. + function arraysEqual(arr1, arr2, reason) { + is(arr1.length, arr2.length, `${reason}; lengths should be equal`) + for (var i = 0; i < arr1.length; ++i) { + if (Array.isArray(arr2[i])) { + arraysEqual(arr1[i], arr2[i], `${reason}; item at index ${i}`); + } else { + is(arr1[i], arr2[i], `${reason}; item at index ${i} should be equal`); + } + } + } + + function testArrayIterators(arrayLike, equivalentArray, reason) { + arraysEqual([...arrayLike], equivalentArray, `${reason}; spread operator`); + arraysEqual([...arrayLike.entries()], [...equivalentArray.entries()], + `${reason}; entries`); + arraysEqual([...arrayLike.keys()], [...equivalentArray.keys()], + `${reason}; keys`); + if (arrayLike.values) { + arraysEqual([...arrayLike.values()], equivalentArray, + `${reason}; values`); + } + + var forEachCopy = []; + arrayLike.forEach(function(arg) { forEachCopy.push(arg); }); + arraysEqual(forEachCopy, equivalentArray, `${reason}; forEach copy`); + + var everyCopy = []; + arrayLike.every(function(arg) { everyCopy.push(arg); return true; }); + arraysEqual(everyCopy, equivalentArray, `${reason}; every() copy`); + + var filterCopy = []; + var filterResult = arrayLike.filter(function(arg) { + filterCopy.push(arg); + return true; + }); + arraysEqual(filterCopy, equivalentArray, `${reason}; filter copy`); + arraysEqual([...filterResult], equivalentArray, `${reason}; filter result`); + + var findCopy = []; + arrayLike.find(function(arg) { findCopy.push(arg); return false; }); + arraysEqual(findCopy, equivalentArray, `${reason}; find() copy`); + + var findIndexCopy = []; + arrayLike.findIndex(function(arg) { findIndexCopy.push(arg); return false; }); + arraysEqual(findIndexCopy, equivalentArray, `${reason}; findIndex() copy`); + + var mapCopy = []; + var mapResult = arrayLike.map(function(arg) { mapCopy.push(arg); return arg}); + arraysEqual(mapCopy, equivalentArray, `${reason}; map() copy`); + arraysEqual([...mapResult], equivalentArray, `${reason}; map() result`); + + var reduceCopy = []; + arrayLike.reduce(function(_, arg) { reduceCopy.push(arg); }, 0); + arraysEqual(reduceCopy, equivalentArray, `${reason}; reduce() copy`); + + var reduceRightCopy = []; + arrayLike.reduceRight(function(_, arg) { reduceRightCopy.unshift(arg); }, 0); + arraysEqual(reduceRightCopy, equivalentArray, `${reason}; reduceRight() copy`); + + var someCopy = []; + arrayLike.some(function(arg) { someCopy.push(arg); return false; }); + arraysEqual(someCopy, equivalentArray, `${reason}; some() copy`); + } + + function testDate() { + // toGMTString is handled oddly in the engine. We don't bother to support + // it over Xrays. + let propsToSkip = ['toGMTString']; + + testXray('Date', new iwin.Date(), new iwin.Date(), propsToSkip); + + // Test the self-hosted toLocaleString. + var d = new iwin.Date(); + isnot(d.toLocaleString, Cu.unwaiveXrays(d.wrappedJSObject.toLocaleString), "Different function identities"); + is(Cu.getGlobalForObject(d.toLocaleString), window, "Xray global is correct"); + is(Cu.getGlobalForObject(d.wrappedJSObject.toLocaleString), iwin, "Underlying global is correct"); + is(d.toLocaleString('de-DE'), d.wrappedJSObject.toLocaleString('de-DE'), "Results match"); + } + + var uniqueSymbol; + + function testObject() { + testXray('Object', Cu.unwaiveXrays(Cu.waiveXrays(iwin).Object.create(new iwin.Object())), + new iwin.Object(), []); + + // Construct an object full of tricky things. + let symbolProps = ''; + uniqueSymbol = iwin.eval('var uniqueSymbol = Symbol("uniqueSymbol"); uniqueSymbol'); + symbolProps = `, [uniqueSymbol]: 43, + [Symbol.for("registrySymbolProp")]: 44`; + var trickyObject = + iwin.eval(`(function() { + var o = new Object({ + primitiveProp: 42, objectProp: { foo: 2 }, + xoProp: top, hasOwnProperty: 10, + get getterProp() { return 2; }, + set setterProp(x) { }, + get getterSetterProp() { return 3; }, + set getterSetterProp(x) { }, + callableProp: function() { }, + nonXrayableProp: new Map()[Symbol.iterator]() + ${symbolProps} + }); + Object.defineProperty(o, "nonConfigurableGetterSetterProp", + { get: function() { return 5; }, set: function() {} }); + return o; + })()`); + testTrickyObject(trickyObject); + } + + function testArray() { + // The |length| property is generally very weird, especially with respect + // to its behavior on the prototype. Array.prototype is actually an Array + // instance, and therefore has a vestigial .length. But we don't want to + // show that over Xrays, and generally want .length to just appear as an + // |own| data property. So we add it to the ignore list here, and check it + // separately. + // + // |Symbol.unscopables| should in principle be exposed, but it is + // inconvenient (as it's a data property, unsupported by ClassSpec) and + // low value. + let propsToSkip = ['length', Symbol.unscopables]; + + testXray('Array', new iwin.Array(20), new iwin.Array(), propsToSkip); + + let symbolProps = ''; + uniqueSymbol = iwin.eval('var uniqueSymbol = Symbol("uniqueSymbol"); uniqueSymbol'); + symbolProps = `trickyArray[uniqueSymbol] = 43; + trickyArray[Symbol.for("registrySymbolProp")] = 44;`; + var trickyArray = + iwin.eval(`var trickyArray = []; + trickyArray.primitiveProp = 42; + trickyArray.objectProp = { foo: 2 }; + trickyArray.xoProp = top; + trickyArray.hasOwnProperty = 10; + Object.defineProperty(trickyArray, 'getterProp', { get: function() { return 2; }}); + Object.defineProperty(trickyArray, 'setterProp', { set: function(x) {}}); + Object.defineProperty(trickyArray, 'getterSetterProp', { get: function() { return 3; }, set: function(x) {}, configurable: true}); + Object.defineProperty(trickyArray, 'nonConfigurableGetterSetterProp', { get: function() { return 5; }, set: function(x) {}}); + trickyArray.callableProp = function() {}; + trickyArray.nonXrayableProp = new Map()[Symbol.iterator](); + ${symbolProps} + trickyArray;`); + + // Test indexed access. + trickyArray.wrappedJSObject[9] = "some indexed property"; + is(trickyArray[9], "some indexed property", "indexed properties work correctly over Xrays"); + is(trickyArray.length, 10, "Length works correctly over Xrays"); + checkThrows(function() { "use strict"; delete trickyArray.length; }, /config/, "Can't delete non-configurable 'length' property"); + delete trickyArray[9]; + is(trickyArray[9], undefined, "Delete works correctly over Xrays"); + is(trickyArray.wrappedJSObject[9], undefined, "Delete works correctly over Xrays (viewed via waiver)"); + is(trickyArray.length, 10, "length doesn't change"); + trickyArray[11] = "some other indexed property"; + is(trickyArray.length, 12, "length now changes"); + is(trickyArray.wrappedJSObject[11], "some other indexed property"); + trickyArray.length = 0; + is(trickyArray.length, 0, "Setting length works over Xray"); + is(trickyArray[11], undefined, "Setting length truncates over Xray"); + Object.defineProperty(trickyArray, 'length', { configurable: false, enumerable: false, writable: false, value: 0 }); + trickyArray[1] = "hi"; + is(trickyArray.length, 0, "Length remains non-writable"); + is(trickyArray[1], undefined, "Frozen length forbids new properties"); + is(trickyArray instanceof iwin.Array, true, "instanceof should work across xray wrappers."); + testTrickyObject(trickyArray); + + testArrayIterators(new iwin.Array(1, 1, 2, 3, 5), [1, 1, 2, 3, 5]); + } + + // Parts of this function are kind of specific to testing Object, but we factor + // it out so that we can re-use the trickyObject stuff on Arrays. + function testTrickyObject(trickyObject) { + + // Make sure it looks right under the hood. + is(trickyObject.wrappedJSObject.getterProp, 2, "Underlying object has getter"); + is(Cu.unwaiveXrays(trickyObject.wrappedJSObject.xoProp), top, "Underlying object has xo property"); + + // Test getOwnPropertyNames. + var expectedNames = ['objectProp', 'primitiveProp']; + if (trickyObject instanceof iwin.Array) + expectedNames.push('length'); + is(Object.getOwnPropertyNames(trickyObject).sort().toSource(), + expectedNames.sort().toSource(), "getOwnPropertyNames should be filtered correctly"); + var expectedSymbols = [Symbol.for("registrySymbolProp"), uniqueSymbol]; + is(Object.getOwnPropertySymbols(trickyObject).map(uneval).sort().toSource(), + expectedSymbols.map(uneval).sort().toSource(), + "getOwnPropertySymbols should be filtered correctly"); + + // Test that cloning uses the Xray view. + var cloned = Cu.cloneInto(trickyObject, this); + is(Object.getOwnPropertyNames(cloned).sort().toSource(), + expectedNames.sort().toSource(), "structured clone should use the Xray view"); + is(Object.getOwnPropertySymbols(cloned).map(uneval).sort().toSource(), + "[]", "structured cloning doesn't clone symbol-keyed properties yet"); + + // Test iteration and in-place modification. Beware of 'expando', which is the property + // we placed on the xray proto. + var propCount = 0; + for (let prop in trickyObject) { + if (prop == 'primitiveProp') + trickyObject[prop] = trickyObject[prop] - 10; + if (prop != 'expando') { + // eslint-disable-next-line no-self-assign + trickyObject[prop] = trickyObject[prop]; + } + ++propCount; + } + is(propCount, 3, "Should iterate the correct number of times"); + + // Test Object.keys. + is(Object.keys(trickyObject).sort().toSource(), + ['objectProp', 'primitiveProp'].toSource(), "Object.keys should be filtered correctly"); + + // Test getOwnPropertyDescriptor. + is(trickyObject.primitiveProp, 32, "primitive prop works"); + is(trickyObject.objectProp.foo, 2, "object prop works"); + is(typeof trickyObject.callableProp, 'undefined', "filtering works correctly"); + is(Object.getOwnPropertyDescriptor(trickyObject, 'primitiveProp').value, 32, "getOwnPropertyDescriptor works"); + is(Object.getOwnPropertyDescriptor(trickyObject, 'xoProp'), undefined, "filtering works with getOwnPropertyDescriptor"); + + // Test defineProperty. + + trickyObject.primitiveSetByXray = 'fourty two'; + is(trickyObject.primitiveSetByXray, 'fourty two', "Can set primitive correctly over Xray (ready via Xray)"); + is(trickyObject.wrappedJSObject.primitiveSetByXray, 'fourty two', "Can set primitive correctly over Xray (ready via Waiver)"); + + var newContentObject = iwin.eval('new Object({prop: 99, get getterProp() { return 2; }})'); + trickyObject.objectSetByXray = newContentObject; + is(trickyObject.objectSetByXray.prop, 99, "Can set object correctly over Xray (ready via Xray)"); + is(trickyObject.wrappedJSObject.objectSetByXray.prop, 99, "Can set object correctly over Xray (ready via Waiver)"); + checkThrows(function() { trickyObject.rejectedProp = {foo: 33}}, /cross-origin object/, + "Should reject privileged object property definition"); + + // Test JSON.stringify. + var jsonStr = JSON.stringify(newContentObject); + ok(/prop/.test(jsonStr), "JSON stringification should work: " + jsonStr); + + // Test deletion. + delete newContentObject.prop; + ok(!newContentObject.hasOwnProperty('prop'), "Deletion should work"); + ok(!newContentObject.wrappedJSObject.hasOwnProperty('prop'), "Deletion should forward"); + delete newContentObject.getterProp; + ok(newContentObject.wrappedJSObject.hasOwnProperty('getterProp'), "Deletion be no-op for filtered property"); + + // We should be able to overwrite an existing accessor prop and convert it + // to a value prop. + is(trickyObject.wrappedJSObject.getterSetterProp, 3, "Underlying object has getter"); + is(trickyObject.getterSetterProp, undefined, "Filtering properly over Xray"); + trickyObject.getterSetterProp = 'redefined'; + is(trickyObject.getterSetterProp, 'redefined', "Redefinition works"); + is(trickyObject.wrappedJSObject.getterSetterProp, 'redefined', "Redefinition forwards"); + + // We should NOT be able to overwrite an existing non-configurable accessor + // prop, though. + is(trickyObject.wrappedJSObject.nonConfigurableGetterSetterProp, 5, + "Underlying object has getter"); + is(trickyObject.nonConfigurableGetterSetterProp, undefined, + "Filtering properly over Xray here too"); + is((trickyObject.nonConfigurableGetterSetterProp = 'redefined'), 'redefined', + "Assigning to non-configurable prop should fail silently in non-strict mode"); + checkThrows(function() { + "use strict"; + trickyObject.nonConfigurableGetterSetterProp = 'redefined'; + }, /config/, "Should throw when redefining non-configurable prop in strict mode"); + is(trickyObject.nonConfigurableGetterSetterProp, undefined, + "Redefinition should have failed"); + is(trickyObject.wrappedJSObject.nonConfigurableGetterSetterProp, 5, + "Redefinition really should have failed"); + + checkThrows(function() { trickyObject.hasOwnProperty = 33; }, /shadow/, + "Should reject shadowing of pre-existing inherited properties over Xrays"); + + checkThrows(function() { Object.defineProperty(trickyObject, 'rejectedProp', { get() {}}); }, + /accessor property/, "Should reject accessor property definition"); + } + + function testTypedArrays() { + // We don't invoke testXray with %TypedArray%, because that function isn't + // set up to deal with "anonymous" dependent classes (that is, classes not + // visible as a global property, which %TypedArray% is not), and fixing it + // up is more trouble than it's worth. + + var typedArrayProto = Object.getPrototypeOf(Int8Array.prototype); + + var desiredInheritedProps = Object.getOwnPropertyNames(typedArrayProto).sort(); + var inheritedProps = + filterOut(desiredInheritedProps, ["BYTES_PER_ELEMENT", "constructor"]); + + var inheritedCallables = + inheritedProps.filter(name => (propertyIsGetter(typedArrayProto, name) || + typeof typedArrayProto[name] === "function") && + name !== "constructor"); + + for (let c of typedArrayClasses) { + var t = new iwin[c](10); + checkThrows(function() { t[2]; }, /performant/, "direct property-wise reading of typed arrays forbidden over Xrays"); + checkThrows(function() { t[2] = 3; }, /performant/, "direct property-wise writing of typed arrays forbidden over Xrays"); + var wesb = new Cu.Sandbox([iwin], {isWebExtensionContentScript: true}); + wesb.t = t; + wesb.eval('t[2] = 3'); + is(wesb.eval('t.wrappedJSObject[2]'), 3, "direct property-wise writing of typed arrays allowed for WebExtension content scripts"); + is(wesb.eval('t[2]'), 3, "direct property-wise reading and writing of typed arrays allowed for WebExtensions content scripts"); + + t.wrappedJSObject[2] = 3; + is(t.wrappedJSObject[2], 3, "accessing elements over waivers works"); + t.wrappedJSObject.expando = 'hi'; + is(t.wrappedJSObject.expando, 'hi', "access expandos over waivers works"); + is(Cu.cloneInto(t, window)[2], 3, "cloneInto works"); + is(Cu.cloneInto(t, window).expando, undefined, "cloneInto does not copy expandos"); + is(Object.getOwnPropertyNames(t).sort().toSource(), + '["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]', + "Only indexed properties visible over Xrays"); + Object.defineProperty(t.wrappedJSObject, 'length', {value: 42}); + is(t.wrappedJSObject.length, 42, "Set tricky expando") + is(t.length, 10, "Length accessor works over Xrays") + is(t.byteLength, t.length * window[c].prototype.BYTES_PER_ELEMENT, "byteLength accessor works over Xrays") + + // Can create TypedArray from content ArrayBuffer + var buffer = new iwin.ArrayBuffer(8); + new window[c](buffer); + + var xray = new iwin[c](0); + var xrayTypedArrayProto = Object.getPrototypeOf(Object.getPrototypeOf(xray)); + testProtoCallables(inheritedCallables, new iwin[c](0), xrayTypedArrayProto, typedArrayProto); + + // When testing iterators, make sure to do so from inside our web + // extension sandbox, since from chrome we can't poke their indices. Note + // that we have to actually recreate our functions that touch typed array + // indices inside the sandbox, not just export them, because otherwise + // they'll just run with our principal anyway. + // + // But we do want to export is(), since we want ours called. + wesb.eval(String(arraysEqual)); + wesb.eval(String(testArrayIterators)); + Cu.exportFunction(is, wesb, + { defineAs: "is" }); + wesb.eval('testArrayIterators(t, [0, 0, 3, 0, 0, 0, 0, 0, 0, 0])'); + } + } + + function testErrorObjects() { + // We only invoke testXray with Error, because that function isn't set up + // to deal with dependent classes and fixing it up is more trouble than + // it's worth. + testXray('Error', new iwin.Error('some error message'), new iwin.Error()); + + // Make sure that the dependent classes have their prototypes set up correctly. + for (let c of errorObjectClasses.filter(x => x != "Error")) { + var args = ['some message']; + if (c === 'AggregateError') { + // AggregateError's first argument is the list of aggregated errors. + args.unshift(new iwin.Array('error 1', 'error 2')); + } + var e = new iwin[c](...args); + is(Object.getPrototypeOf(e).name, c, "Prototype has correct name"); + is(Object.getPrototypeOf(Object.getPrototypeOf(e)), iwin.Error.prototype, "Dependent prototype set up correctly"); + is(e.name, c, "Exception name inherited correctly"); + + function testProperty(name, criterion, goodReplacement, faultyReplacement) { + ok(criterion(e[name]), name + " property is correct: " + e[name]); + e.wrappedJSObject[name] = goodReplacement; + is(e[name], goodReplacement, name + " property ok after replacement: " + goodReplacement); + e.wrappedJSObject[name] = faultyReplacement; + is(e[name], name == 'message' ? "" : undefined, name + " property skipped after suspicious replacement"); + } + testProperty('message', x => x == 'some message', 'some other message', 42); + testProperty('fileName', x => x == '', 'otherFilename.html', new iwin.Object()); + testProperty('columnNumber', x => x == 1, 99, 99.5); + testProperty('lineNumber', x => x == 0, 50, 'foo'); + + if (c === 'AggregateError') { + let {errors} = e; + is(errors.length, 2, "errors property has the correct length"); + is(errors[0], 'error 1', "errors[0] has the correct value"); + is(errors[1], 'error 2', "errors[1] has the correct value"); + + e.wrappedJSObject.errors = 42; + is(e.wrappedJSObject.errors, 42, "errors is a plain data property"); + is(e.errors, 42, "visible over Xrays"); + } + + // Note - an Exception newed via Xrays is going to have an empty stack given the + // current semantics and implementation. This tests the current behavior, but that + // may change in bug 1036527 or similar. + // + // Furthermore, xrays should always return an error's original stack, and + // not overwrite it. + var stack = e.stack; + ok(/^\s*$/.test(stack), "stack property should be correct"); + e.wrappedJSObject.stack = "not a stack"; + is(e.stack, stack, "Xrays should never get an overwritten stack property."); + + // Test the .cause property is correctly handled, too. + if (isNightlyBuild) { + let cause = 'error cause'; + let options = new iwin.Object(); + options.cause = cause; + args.push(options); + + let e = new iwin[c](...args); + is(e.cause, cause); + + e.wrappedJSObject.cause = 42; + is(e.wrappedJSObject.cause, 42, "cause is a plain data property"); + is(e.cause, 42, "visible over Xrays"); + } + } + } + + function testRegExp() { + // RegExp statics are very weird, and in particular RegExp has static + // properties that have to do with the last regexp execution in the global. + // Xraying those makes no sense, so we just skip constructor properties for + // RegExp xrays. + // RegExp[@@species] is affected by above skip, but we don't fix it until + // compelling use-case appears, as supporting RegExp[@@species] while + // skipping other static properties makes things complicated. + let ctorPropsToSkip = ["input", "lastMatch", "lastParen", + "leftContext", "rightContext", "$1", "$2", "$3", + "$4", "$5", "$6", "$7", "$8", "$9", "$_", "$&", + "$+", "$`", "$'", Symbol.species]; + testXray('RegExp', new iwin.RegExp('foo'), new iwin.RegExp(), [], + ctorPropsToSkip); + + // Test the self-hosted |flags| property, toString, and toSource. + for (var flags of ["", "g", "i", "m", "y", "gimy"]) { + var re = new iwin.RegExp("foo", flags); + is(re.flags, re.wrappedJSObject.flags, "Results match"); + + isnot(re.toString, Cu.unwaiveXrays(re.wrappedJSObject.toString), "Different function identities"); + is(Cu.getGlobalForObject(re.toString), window, "Xray global is correct"); + is(Cu.getGlobalForObject(re.wrappedJSObject.toString), iwin, "Underlying global is correct"); + is(re.toString(), re.wrappedJSObject.toString(), "Results match"); + + isnot(re.toSource, Cu.unwaiveXrays(re.wrappedJSObject.toSource), "Different function identities"); + is(Cu.getGlobalForObject(re.toSource), window, "Xray global is correct"); + if (re.wrappedJSObject.toSource) { + is(Cu.getGlobalForObject(re.wrappedJSObject.toSource), iwin, "Underlying global is correct"); + is(re.toSource(), re.wrappedJSObject.toSource(), "Results match"); + } + + // Test with modified flags accessors + iwin.eval(` +var props = ["global", "ignoreCase", "multiline", "sticky", "source", "unicode"]; +var origDescs = {}; +for (var prop of props) { + origDescs[prop] = Object.getOwnPropertyDescriptor(RegExp.prototype, prop); + Object.defineProperty(RegExp.prototype, prop, { + get: function() { + throw new Error("modified accessor is called"); + } + }); +} +`); + try { + is(re.flags, flags, "Unmodified flags accessors are called"); + is(re.toString(), "/foo/" + flags, "Unmodified flags and source accessors are called"); + is(re.toSource(), "/foo/" + flags, "Unmodified flags and source accessors are called"); + } finally { + iwin.eval(` +for (var prop of props) { + Object.defineProperty(RegExp.prototype, prop, origDescs[prop]); +} +`); + } + } + } + + // Note: this is a small set of basic tests. More in-depth tests are located + // in test_promise_xrays.html. + function testPromise() { + testXray('Promise', new iwin.Promise(function(){}), new iwin.Promise(function(){})); + + // Test catch and then. + var pr = new iwin.Promise(function(){}); + isnot(pr.catch, Cu.unwaiveXrays(pr.wrappedJSObject.catch), "Different function identities"); + is(Cu.getGlobalForObject(pr.catch), window, "Xray global is correct"); + is(Cu.getGlobalForObject(pr.wrappedJSObject.catch), iwin, "Underlying global is correct"); + + isnot(pr.then, Cu.unwaiveXrays(pr.wrappedJSObject.then), "Different function identities"); + is(Cu.getGlobalForObject(pr.then), window, "Xray global is correct"); + is(Cu.getGlobalForObject(pr.wrappedJSObject.then), iwin, "Underlying global is correct"); + } + + function testArrayBuffer() { + let constructors = ['ArrayBuffer']; + + for (const c of constructors) { + testXray(c, new iwin[c](0), new iwin[c](12)); + + var t = new iwin[c](12); + is(t.byteLength, 12, `${c} byteLength is correct`); + + is(t.slice(4).byteLength, 8, `${c} byteLength is correct after slicing`); + is(Cu.getGlobalForObject(t.slice(4)), iwin, "Slice results lives in the target compartment"); + is(Object.getPrototypeOf(t.slice(4)), iwin[c].prototype, "Slice results proto lives in target compartment") + + var i32Array = new Int32Array(t); + // i32Array is going to be created in the buffer's target compartment, + // but usually this is unobservable, because the proto is set to + // the current compartment's prototype. + // However Xrays ignore the object's proto and claim its proto is + // the default proto for that class in the relevant compartment, + // so see through this proto hack. + todo_is(Object.getPrototypeOf(i32Array), Int32Array.prototype, "Int32Array has correct proto"); + is(i32Array.length, 3, `Int32Array created from Xray ${c} has the correct length`); + is(i32Array.buffer, t, "Int32Array has the correct buffer that we passed in"); + + i32Array = new iwin.Int32Array(t); + is(Object.getPrototypeOf(i32Array), iwin.Int32Array.prototype, "Xray Int32Array has correct proto"); + is(i32Array.length, 3, `Xray Int32Array created from Xray ${c} has the correct length`); + is(i32Array.buffer, t, "Xray Int32Array has the correct buffer that we passed in"); + + t = (new iwin.Int32Array(2)).buffer; + is(t.byteLength, 8, `Can access ${c} returned by buffer property`); + } + } + + function testMap() { + testXray('Map', new iwin.Map(), new iwin.Map()); + + var t = iwin.eval(`new Map([[1, "a"], [null, "b"]])`); + is(t.size, 2, "Map size is correct"); + is(t.get(1), "a", "Key 1 has the correct value"); + is(t.get(null), "b", "Key null has the correct value"); + is(t.has(1), true, "Has Key 1"); + is(t.set(3, 5).get(3), 5, "Correctly sets key"); + is(t.delete(null), true, "Key null can be deleted"); + + let values = []; + t.forEach((value, key) => values.push(value)); + is(values.toString(), "a,5", "forEach enumerates values correctly"); + + t.clear(); + is(t.size, 0, "Map is empty after calling clear"); + } + + function testSet() { + testXray('Set', new iwin.Set(), new iwin.Set()); + + var t = iwin.eval(`new Set([1, null])`); + is(t.size, 2, "Set size is correct"); + is(t.has(1), true, "Contains 1"); + is(t.has(null), true, "Contains null"); + is(t.add(5).has(5), true, "Can add value to set"); + is(t.delete(null), true, "Value null can be deleted"); + + let values = []; + t.forEach(value => values.push(value)); + is(values.toString(), "1,5", "forEach enumerates values correctly"); + + t.clear(); + is(t.size, 0, "Set is empty after calling clear"); + } + + function testWeakMap() { + testXray('WeakMap', new iwin.WeakMap(), new iwin.WeakMap()); + + var key1 = iwin.eval(`var key1 = {}; key1`); + var key2 = iwin.eval(`var key2 = []; key2`); + var key3 = iwin.eval(`var key3 = /a/; key3`); + var key4 = {}; + var key5 = []; + var t = iwin.eval(`new WeakMap([[key1, "a"], [key2, "b"]])`); + is(t.get(key1), "a", "key1 has the correct value"); + is(t.get(key2), "b", "key2 has the correct value"); + is(t.has(key1), true, "Has key1"); + is(t.has(key3), false, "Doesn't have key3"); + is(t.has(key5), false, "Doesn't have key5"); + is(t.set(key4, 5).get(key4), 5, "Correctly sets key"); + is(t.get(key1), "a", "key1 has the correct value after modification"); + is(t.get(key2), "b", "key2 has the correct value after modification"); + is(t.delete(key1), true, "key1 can be deleted"); + is(t.delete(key2), true, "key2 can be deleted"); + is(t.delete(key3), false, "key3 cannot be deleted"); + is(t.delete(key4), true, "key4 can be deleted"); + is(t.delete(key5), false, "key5 cannot be deleted"); + } + + function testWeakSet() { + testXray('WeakSet', new iwin.WeakSet(), new iwin.WeakSet()); + + var key1 = iwin.eval(`var key1 = {}; key1`); + var key2 = iwin.eval(`var key2 = []; key2`); + var key3 = iwin.eval(`var key3 = /a/; key3`); + var key4 = {}; + var key5 = []; + var t = iwin.eval(`new WeakSet([key1, key2])`); + is(t.has(key1), true, "Has key1"); + is(t.has(key2), true, "Has key2"); + is(t.has(key3), false, "Doesn't have key3"); + is(t.has(key5), false, "Doesn't have key5"); + is(t.add(key4, 5).has(key4), true, "Can add value to set"); + is(t.delete(key1), true, "key1 can be deleted"); + is(t.delete(key2), true, "key2 can be deleted"); + is(t.delete(key3), false, "key3 cannot be deleted"); + is(t.delete(key4), true, "key4 can be deleted"); + is(t.delete(key5), false, "key5 cannot be deleted"); + } + + function testProxy() { + let ProxyCtor = iwin.Proxy; + is(Object.getOwnPropertyNames(ProxyCtor).sort().toSource(), + ["length", "name"].sort().toSource(), + "Xrayed Proxy constructor should not have any properties"); + is(ProxyCtor.prototype, undefined, "Proxy.prototype should not be set"); + // Proxy.revocable can safely be exposed, but it is not. + // Until it is supported, check that the property is not set. + is(ProxyCtor.revocable, undefined, "Proxy.reflect is not set"); + } + + function testDataView() { + testXray('DataView', new iwin.DataView(new iwin.ArrayBuffer(4)), + new iwin.DataView(new iwin.ArrayBuffer(8))); + + const versions = [() => iwin.eval(`new DataView(new ArrayBuffer(8))`), + () => new DataView(new iwin.ArrayBuffer(8))]; + + for (const constructor of versions) { + let t = constructor(); + is(t.byteLength, 8, `byteLength correct for "${constructor}"`); + is(t.byteOffset, 0, `byteOffset correct for "${constructor}"`); + is(t.buffer.byteLength, 8, `buffer works for "${constructor}"`); + + const get = ["getInt8", "getUint8", "getInt16", "getUint16", + "getInt32", "getUint32", "getFloat32", "getFloat64"]; + + const set = ["setInt8", "setUint8", "setInt16", "setUint16", + "setInt32", "setUint32", "setFloat32", "setFloat64"]; + + for (const f of get) { + let x = t[f](0); + is(x, 0, `${f} is 0 for "${constructor}"`); + is(typeof x, 'number', `typeof ${f} is number for "${constructor}"`); + } + + for (const f of ["getBigInt64", "getBigUint64"]) { + let x = t[f](0); + is(x, BigInt(0), `${f} is 0n for "${constructor}"`); + is(typeof x, 'bigint', `typeof ${f} is bigint for "${constructor}"`); + } + + for (let i = 0; i < set.length; i++) { + t[set[i]](0, 13); + is(t[get[i]](0), 13, `${get[i]}(0) afer ${set[i]}(0, 13) is 13 for "${constructor}"`); + } + + for (const k of ["BigInt64", "BigUint64"]) { + t["set" + k](0, BigInt(13)); + is(t["get" + k](0), BigInt(13), `get${k}(0) afer set${k}(0, 13n) is 13n for "${constructor}"`); + } + } + } + + function testNumber() { + // We don't actually support Xrays to Number yet. This is testing + // that case. If we add such support, we might have to start + // using a different non-Xrayed class here, if we can find one. + let xrayCtor = iwin.Number; + is(Object.getOwnPropertyNames(xrayCtor).sort().toSource(), + Object.getOwnPropertyNames(function() {}).sort().toSource(), + "We should not have any static properties on a non-Xrayable constructor"); + is(xrayCtor.noSuchProperty, undefined, + "Where did our noSuchProperty property come from?"); + } + + ]]> + </script> + <iframe id="ifr" onload="go();" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" /> +</window> diff --git a/js/xpconnect/tests/chrome/test_xrayic.xhtml b/js/xpconnect/tests/chrome/test_xrayic.xhtml new file mode 100644 index 0000000000..fd9ab8f7b3 --- /dev/null +++ b/js/xpconnect/tests/chrome/test_xrayic.xhtml @@ -0,0 +1,81 @@ +<?xml version="1.0"?> +<?xml-stylesheet type="text/css" href="chrome://global/skin"?> +<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1355109 +--> +<window title="Mozilla Bug 1355109" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> + + <!-- test results are displayed in the html:body --> + <body xmlns="http://www.w3.org/1999/xhtml"> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=758415" + target="_blank">Mozilla Bug 758415</a> + </body> + + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ + + SimpleTest.waitForExplicitFinish(); + + // Import our test JSM. We first strip the filename off + // the chrome url, then append the jsm filename. + var base = /.*\//.exec(window.location.href)[0]; + ChromeUtils.import(base + "file_expandosharing.jsm"); + + // Wait for all child frames to load. + var gLoadCount = 0; + function frameLoaded() { + if (++gLoadCount == window.frames.length) + go(); + } + + function go() { + testSandbox(1); + testSandbox(100); + testSandbox(1000); + SimpleTest.finish(); + } + + function testSandbox(iterations) { + // Create an expanded principal sandbox to get xrays with exclusive + // expandos. + var sandbox = new Cu.Sandbox(["https://test1.example.org", + "https://test2.example.org"]); + sandbox.iframeWindows = new sandbox.Array(); + for (let iframe of document.getElementsByTagName('iframe')) { + sandbox.iframeWindows.push(iframe.contentWindow); + } + Cu.evalInSandbox(testClassName.toSource(), sandbox); + Cu.evalInSandbox(testIC.toSource(), sandbox); + is(Cu.evalInSandbox("testIC(" + iterations + ");", sandbox), true, "sandbox test"); + } + + // This is in a separate function to provide a common source location for ICs. + function testClassName(obj, expected) { + var className = obj.className; + if (className != expected) + throw new Error("Got " + className + ", expected " + expected); + } + + function testIC(iterations) { + for (var i = 0; i < this.iframeWindows.length; i++) { + var win = this.iframeWindows[i]; + var spans = win.document.getElementsByTagName('span'); + for (var j = 0; j < spans.length; j++) { + var span = spans[j]; + for (var k = 0; k < iterations; k++) + testClassName(span, "iamaspan"); + Object.defineProperty(span, "className", { value: "what" }); + testClassName(span, "what"); + } + } + return true; + } + ]]> + </script> + <iframe id="inlineFrame1" onload="frameLoaded();" type="content" src="https://test1.example.org/tests/js/xpconnect/tests/mochitest/file_xrayic.html" /> + <iframe id="inlineFrame2" onload="frameLoaded();" type="content" src="https://test1.example.org/tests/js/xpconnect/tests/mochitest/file_xrayic.html" /> +</window> diff --git a/js/xpconnect/tests/chrome/utf8_subscript.js b/js/xpconnect/tests/chrome/utf8_subscript.js new file mode 100644 index 0000000000..6444273c9d --- /dev/null +++ b/js/xpconnect/tests/chrome/utf8_subscript.js @@ -0,0 +1,5 @@ +// -*- coding: utf-8; indent-tabs-mode: nil -*- +var str = "𝔘𝔫𝔦𝔠𝔬𝔡𝔢"; +function f() { + return 42; +} diff --git a/js/xpconnect/tests/chrome/worker_discardSystemSource.js b/js/xpconnect/tests/chrome/worker_discardSystemSource.js new file mode 100644 index 0000000000..5da32511fa --- /dev/null +++ b/js/xpconnect/tests/chrome/worker_discardSystemSource.js @@ -0,0 +1,6 @@ +function canary() { + // eslint-disable-next-line no-unused-vars + var someBitOfSource = 42; +} + +postMessage(canary.toString()); |