summaryrefslogtreecommitdiffstats
path: root/js/xpconnect/tests/chrome
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--js/xpconnect/tests/chrome/bug503926.xhtml30
-rw-r--r--js/xpconnect/tests/chrome/chrome.toml220
-rw-r--r--js/xpconnect/tests/chrome/file_bug1281071.html13
-rw-r--r--js/xpconnect/tests/chrome/file_bug1530146.html6
-rw-r--r--js/xpconnect/tests/chrome/file_bug1530146_inner.html4
-rw-r--r--js/xpconnect/tests/chrome/file_bug484459.html10
-rw-r--r--js/xpconnect/tests/chrome/file_bug618176.xhtml48
-rw-r--r--js/xpconnect/tests/chrome/file_bug996069.html11
-rw-r--r--js/xpconnect/tests/chrome/file_discardSystemSource.html19
-rw-r--r--js/xpconnect/tests/chrome/file_empty.html2
-rw-r--r--js/xpconnect/tests/chrome/file_evalInSandbox.html1
-rw-r--r--js/xpconnect/tests/chrome/file_expandosharing.jsm12
-rw-r--r--js/xpconnect/tests/chrome/moz.build12
-rw-r--r--js/xpconnect/tests/chrome/outoflinexulscript.js5
-rw-r--r--js/xpconnect/tests/chrome/subscript.js4
-rw-r--r--js/xpconnect/tests/chrome/test_APIExposer.xhtml48
-rw-r--r--js/xpconnect/tests/chrome/test_bug1041626.xhtml60
-rw-r--r--js/xpconnect/tests/chrome/test_bug1042436.xhtml54
-rw-r--r--js/xpconnect/tests/chrome/test_bug1065185.html64
-rw-r--r--js/xpconnect/tests/chrome/test_bug1074863.html31
-rw-r--r--js/xpconnect/tests/chrome/test_bug1092477.xhtml33
-rw-r--r--js/xpconnect/tests/chrome/test_bug1124898.html52
-rw-r--r--js/xpconnect/tests/chrome/test_bug1126911.html40
-rw-r--r--js/xpconnect/tests/chrome/test_bug1281071.xhtml32
-rw-r--r--js/xpconnect/tests/chrome/test_bug1390159.xhtml44
-rw-r--r--js/xpconnect/tests/chrome/test_bug1430164.html31
-rw-r--r--js/xpconnect/tests/chrome/test_bug1516237.html48
-rw-r--r--js/xpconnect/tests/chrome/test_bug1530146.html58
-rw-r--r--js/xpconnect/tests/chrome/test_bug361111.xhtml33
-rw-r--r--js/xpconnect/tests/chrome/test_bug448587.xhtml35
-rw-r--r--js/xpconnect/tests/chrome/test_bug484459.xhtml37
-rw-r--r--js/xpconnect/tests/chrome/test_bug500931.xhtml40
-rw-r--r--js/xpconnect/tests/chrome/test_bug503926.xhtml58
-rw-r--r--js/xpconnect/tests/chrome/test_bug533596.xhtml58
-rw-r--r--js/xpconnect/tests/chrome/test_bug571849.xhtml44
-rw-r--r--js/xpconnect/tests/chrome/test_bug610390.xhtml32
-rw-r--r--js/xpconnect/tests/chrome/test_bug614757.xhtml33
-rw-r--r--js/xpconnect/tests/chrome/test_bug616992.xhtml30
-rw-r--r--js/xpconnect/tests/chrome/test_bug618176.xhtml30
-rw-r--r--js/xpconnect/tests/chrome/test_bug654370.xhtml27
-rw-r--r--js/xpconnect/tests/chrome/test_bug658560.xhtml38
-rw-r--r--js/xpconnect/tests/chrome/test_bug658909.xhtml92
-rw-r--r--js/xpconnect/tests/chrome/test_bug664689.xhtml28
-rw-r--r--js/xpconnect/tests/chrome/test_bug679861.xhtml38
-rw-r--r--js/xpconnect/tests/chrome/test_bug706301.xhtml52
-rw-r--r--js/xpconnect/tests/chrome/test_bug720619.xhtml46
-rw-r--r--js/xpconnect/tests/chrome/test_bug726949.xhtml41
-rw-r--r--js/xpconnect/tests/chrome/test_bug732665.xhtml92
-rw-r--r--js/xpconnect/tests/chrome/test_bug732665_meta.js34
-rw-r--r--js/xpconnect/tests/chrome/test_bug738244.xhtml58
-rw-r--r--js/xpconnect/tests/chrome/test_bug743843.xhtml39
-rw-r--r--js/xpconnect/tests/chrome/test_bug760076.xhtml49
-rw-r--r--js/xpconnect/tests/chrome/test_bug760131.html48
-rw-r--r--js/xpconnect/tests/chrome/test_bug763343.xhtml35
-rw-r--r--js/xpconnect/tests/chrome/test_bug771429.xhtml66
-rw-r--r--js/xpconnect/tests/chrome/test_bug773962.xhtml88
-rw-r--r--js/xpconnect/tests/chrome/test_bug792280.xhtml43
-rw-r--r--js/xpconnect/tests/chrome/test_bug793433.xhtml44
-rw-r--r--js/xpconnect/tests/chrome/test_bug795275.xhtml80
-rw-r--r--js/xpconnect/tests/chrome/test_bug799348.xhtml47
-rw-r--r--js/xpconnect/tests/chrome/test_bug801241.xhtml48
-rw-r--r--js/xpconnect/tests/chrome/test_bug812415.xhtml90
-rw-r--r--js/xpconnect/tests/chrome/test_bug853283.xhtml40
-rw-r--r--js/xpconnect/tests/chrome/test_bug853571.xhtml62
-rw-r--r--js/xpconnect/tests/chrome/test_bug858101.xhtml55
-rw-r--r--js/xpconnect/tests/chrome/test_bug860494.xhtml57
-rw-r--r--js/xpconnect/tests/chrome/test_bug865948.xhtml35
-rw-r--r--js/xpconnect/tests/chrome/test_bug866823.xhtml49
-rw-r--r--js/xpconnect/tests/chrome/test_bug895340.xhtml50
-rw-r--r--js/xpconnect/tests/chrome/test_bug932906.xhtml69
-rw-r--r--js/xpconnect/tests/chrome/test_bug996069.xhtml52
-rw-r--r--js/xpconnect/tests/chrome/test_chrometoSource.xhtml70
-rw-r--r--js/xpconnect/tests/chrome/test_cloneInto.xhtml194
-rw-r--r--js/xpconnect/tests/chrome/test_cows.xhtml207
-rw-r--r--js/xpconnect/tests/chrome/test_discardSystemSource.xhtml81
-rw-r--r--js/xpconnect/tests/chrome/test_documentdomain.xhtml100
-rw-r--r--js/xpconnect/tests/chrome/test_doublewrappedcompartments.xhtml41
-rw-r--r--js/xpconnect/tests/chrome/test_envChain_event_handler.html137
-rw-r--r--js/xpconnect/tests/chrome/test_evalInSandbox.xhtml205
-rw-r--r--js/xpconnect/tests/chrome/test_evalInWindow.xhtml71
-rw-r--r--js/xpconnect/tests/chrome/test_exnstack.xhtml68
-rw-r--r--js/xpconnect/tests/chrome/test_expandosharing.xhtml147
-rw-r--r--js/xpconnect/tests/chrome/test_exposeInDerived.xhtml45
-rw-r--r--js/xpconnect/tests/chrome/test_inlineScripts.html53
-rw-r--r--js/xpconnect/tests/chrome/test_localstorage_with_nsEp.xhtml37
-rw-r--r--js/xpconnect/tests/chrome/test_matches.xhtml49
-rw-r--r--js/xpconnect/tests/chrome/test_nodelists.xhtml49
-rw-r--r--js/xpconnect/tests/chrome/test_nsScriptErrorWithStack.html59
-rw-r--r--js/xpconnect/tests/chrome/test_onGarbageCollection.html48
-rw-r--r--js/xpconnect/tests/chrome/test_precisegc.xhtml26
-rw-r--r--js/xpconnect/tests/chrome/test_private_field_cows.xhtml131
-rw-r--r--js/xpconnect/tests/chrome/test_sandboxImport.xhtml37
-rw-r--r--js/xpconnect/tests/chrome/test_scriptSettings.xhtml127
-rw-r--r--js/xpconnect/tests/chrome/test_scripterror.html87
-rw-r--r--js/xpconnect/tests/chrome/test_secureContexts.html58
-rw-r--r--js/xpconnect/tests/chrome/test_sharedChromeCompartment.html63
-rw-r--r--js/xpconnect/tests/chrome/test_weakmap_keys_preserved.xhtml33
-rw-r--r--js/xpconnect/tests/chrome/test_weakmap_keys_preserved2.xhtml80
-rw-r--r--js/xpconnect/tests/chrome/test_weakref.xhtml32
-rw-r--r--js/xpconnect/tests/chrome/test_windowProxyDeadWrapper.html78
-rw-r--r--js/xpconnect/tests/chrome/test_wrappers.xhtml85
-rw-r--r--js/xpconnect/tests/chrome/test_xrayLargeTypedArray.html47
-rw-r--r--js/xpconnect/tests/chrome/test_xrayToJS.xhtml1200
-rw-r--r--js/xpconnect/tests/chrome/test_xrayic.xhtml81
-rw-r--r--js/xpconnect/tests/chrome/utf8_subscript.js5
-rw-r--r--js/xpconnect/tests/chrome/worker_discardSystemSource.js6
106 files changed, 6951 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.toml b/js/xpconnect/tests/chrome/chrome.toml
new file mode 100644
index 0000000000..6aec4b549b
--- /dev/null
+++ b/js/xpconnect/tests/chrome/chrome.toml
@@ -0,0 +1,220 @@
+[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"]
+
+["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_bug1530146.html"]
+support-files = [
+ "file_bug1530146.html",
+ "file_bug1530146_inner.html",
+]
+
+["test_chrometoSource.xhtml"]
+
+["test_cloneInto.xhtml"]
+
+["test_cows.xhtml"]
+
+["test_discardSystemSource.xhtml"]
+
+["test_documentdomain.xhtml"]
+
+["test_doublewrappedcompartments.xhtml"]
+
+["test_envChain_event_handler.html"]
+
+["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_private_field_cows.xhtml"]
+
+["test_sandboxImport.xhtml"]
+
+["test_scriptSettings.xhtml"]
+
+["test_scripterror.html"]
+
+["test_secureContexts.html"]
+
+["test_sharedChromeCompartment.html"]
+
+["test_weakmap_keys_preserved.xhtml"]
+
+["test_weakmap_keys_preserved2.xhtml"]
+
+["test_weakref.xhtml"]
+
+["test_windowProxyDeadWrapper.html"]
+
+["test_wrappers.xhtml"]
+
+["test_xrayLargeTypedArray.html"]
+skip-if = ["bits == 32"] # Large ArrayBuffers not supported on 32-bit.
+
+["test_xrayToJS.xhtml"]
+
+["test_xrayic.xhtml"]
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..51548541b7
--- /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.toml"]
+
+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..5c640c2052
--- /dev/null
+++ b/js/xpconnect/tests/chrome/test_bug1516237.html
@@ -0,0 +1,48 @@
+<!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 **/
+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,&lt;script&gt;var x=3&lt;/script&gt;"
+ 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..6710a59289
--- /dev/null
+++ b/js/xpconnect/tests/chrome/test_chrometoSource.xhtml
@@ -0,0 +1,70 @@
+<?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.importESModule(
+ "resource://gre/modules/NetUtil.sys.mjs"
+);
+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..3c41c0bfdc
--- /dev/null
+++ b/js/xpconnect/tests/chrome/test_scriptSettings.xhtml
@@ -0,0 +1,127 @@
+<?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() {
+ 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 = Promise.withResolvers();
+ 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 = Promise.withResolvers();
+ 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 = Promise.withResolvers();
+ 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 = Promise.withResolvers();
+ 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 = Promise.withResolvers();
+ 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 = Promise.withResolvers();
+ 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 = Promise.withResolvers();
+ 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..a6f0ac95be
--- /dev/null
+++ b/js/xpconnect/tests/chrome/test_windowProxyDeadWrapper.html
@@ -0,0 +1,78 @@
+<!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.importESModule(
+ "resource://testing-common/TestUtils.sys.mjs"
+);
+
+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..cc009a2d55
--- /dev/null
+++ b/js/xpconnect/tests/chrome/test_xrayToJS.xhtml
@@ -0,0 +1,1200 @@
+<?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.importESModule(
+ "resource://gre/modules/AppConstants.sys.mjs"
+ );
+ 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 = {};
+ // Properties which cannot be invoked if callable without potentially
+ // rendering the object useless.
+ var gStatefulProperties = {};
+ 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", "groupBy"]);
+ 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", "unicodeSets"];
+ 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",
+ "withResolvers", Symbol.species]);
+
+ gPrototypeProperties.ArrayBuffer =
+ ["constructor", "byteLength", "detached", "slice", Symbol.toStringTag, "transfer", "transferToFixedLength"];
+ gConstructorProperties.ArrayBuffer =
+ constructorProps(["isView", Symbol.species]);
+ gStatefulProperties.ArrayBuffer = ["transfer", "transferToFixedLength"]
+
+ gPrototypeProperties.SharedArrayBuffer = ["constructor", "slice", "byteLength", "detached", Symbol.toStringTag, "transfer", "transferToFixedLength"];
+ gConstructorProperties.SharedArrayBuffer = constructorProps([Symbol.species]);
+ gStatefulProperties.SharedArrayBuffer = ["transfer", "transferToFixedLength"]
+
+ gPrototypeProperties.Map =
+ ["constructor", "size", Symbol.toStringTag, "get", "has", "set", "delete",
+ "keys", "values", "clear", "forEach", "entries", Symbol.iterator];
+ gConstructorProperties.Map =
+ constructorProps(["groupBy", 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, callablesExcluded) {
+ // Handle undefined callablesExcluded.
+ let dontCall = callablesExcluded ?? [];
+ 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 && !dontCall.includes(name)) {
+ 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');
+ let callablesExcluded = gStatefulProperties[classname];
+ 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, callablesExcluded);
+ 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());