3 const { AddonTestUtils } = ChromeUtils.importESModule(
4 "resource://testing-common/AddonTestUtils.sys.mjs"
7 AddonTestUtils.init(this);
9 add_task(async function() {
10 let scriptUrl = Services.io.newFileURI(do_get_file("file_simple_script.js")).spec;
13 let script1 = await ChromeUtils.compileScript(scriptUrl, {hasReturnValue: true});
14 let script2 = await ChromeUtils.compileScript(scriptUrl, {hasReturnValue: false});
16 equal(script1.url, scriptUrl, "Script URL is correct")
17 equal(script2.url, scriptUrl, "Script URL is correct")
19 equal(script1.hasReturnValue, true, "Script hasReturnValue property is correct")
20 equal(script2.hasReturnValue, false, "Script hasReturnValue property is correct")
23 // Test return-value version.
25 let sandbox1 = Cu.Sandbox("http://example.com");
26 let sandbox2 = Cu.Sandbox("http://example.org");
28 let obj = script1.executeInGlobal(sandbox1);
29 equal(Cu.getObjectPrincipal(obj).origin, "http://example.com", "Return value origin is correct");
30 equal(obj.foo, "\u00ae", "Return value has the correct charset");
32 obj = script1.executeInGlobal(sandbox2);
33 equal(Cu.getObjectPrincipal(obj).origin, "http://example.org", "Return value origin is correct");
34 equal(obj.foo, "\u00ae", "Return value has the correct charset");
37 // Test no-return-value version.
40 equal(sandbox1.bar, null);
42 obj = script2.executeInGlobal(sandbox1);
43 equal(obj, undefined, "No-return script has no return value");
45 equal(Cu.getObjectPrincipal(sandbox1.bar).origin, "http://example.com", "Object value origin is correct");
46 equal(sandbox1.bar.foo, "\u00ae", "Object value has the correct charset");
50 equal(sandbox2.bar, null);
52 obj = script2.executeInGlobal(sandbox2);
53 equal(obj, undefined, "No-return script has no return value");
55 equal(Cu.getObjectPrincipal(sandbox2.bar).origin, "http://example.org", "Object value origin is correct");
56 equal(sandbox2.bar.foo, "\u00ae", "Object value has the correct charset");
59 add_task(async function test_syntaxError() {
60 // Generate an artificially large script to force off-main-thread
62 let scriptUrl = `data:,${";".repeat(1024 * 1024)}(`;
65 ChromeUtils.compileScript(scriptUrl),
68 // Generate a small script to force main thread compilation.
69 scriptUrl = `data:,;(`;
72 ChromeUtils.compileScript(scriptUrl),
76 add_task(async function test_Error_filename() {
77 // This function will be serialized as a data:-URL and called.
78 function getMyError() {
79 let err = new Error();
81 fileName: err.fileName,
82 stackFirstLine: err.stack.split("\n")[0],
85 const scriptUrl = `data:,(${encodeURIComponent(getMyError)})()`;
86 const dummyFilename = "dummy filename";
87 let script1 = await ChromeUtils.compileScript(scriptUrl, { hasReturnValue: true });
88 let script2 = await ChromeUtils.compileScript(scriptUrl, { hasReturnValue: true, filename: dummyFilename });
90 equal(script1.url, scriptUrl, "Script URL is correct");
91 equal(script2.url, "dummy filename", "Script URL overridden");
93 let sandbox = Cu.Sandbox("http://example.com");
94 let err1 = script1.executeInGlobal(sandbox);
95 equal(err1.fileName, scriptUrl, "fileName is original script URL");
96 equal(err1.stackFirstLine, `getMyError@${scriptUrl}:2:15`, "Stack has original URL");
98 let err2 = script2.executeInGlobal(sandbox);
99 equal(err2.fileName, dummyFilename, "fileName is overridden filename");
100 equal(err2.stackFirstLine, `getMyError@${dummyFilename}:2:15`, "Stack has overridden URL");
103 add_task(async function test_invalid_url() {
104 // In this test we want a URL that doesn't resolve to a valid file.
105 // Moreover, the name is chosen such that it does not trigger the
106 // CheckForBrokenChromeURL check.
107 await Assert.rejects(
108 ChromeUtils.compileScript("resource:///invalid.ftl"),
109 /^Unable to load script: resource:\/\/\/invalid\.ftl$/
112 await Assert.rejects(
113 ChromeUtils.compileScript("resource:///invalid.ftl", { filename: "bye bye" }),
114 /^Unable to load script: bye bye$/
119 * Assert that executeInGlobal throws a special exception when the content script throws.
120 * And the content script exception is notified to the console.
122 add_task(async function test_exceptions_in_webconsole() {
123 const scriptUrl = `data:,throw new Error("foo")`;
124 const script = await ChromeUtils.compileScript(scriptUrl);
125 const sandbox = Cu.Sandbox("http://example.com");
127 Assert.throws(() => script.executeInGlobal(sandbox),
129 "Without reportException set to true, executeInGlobal throws an exception");
131 info("With reportException, executeInGlobal doesn't throw, but notifies the console");
132 const { messages } = await AddonTestUtils.promiseConsoleOutput(() => {
133 script.executeInGlobal(sandbox, { reportExceptions: true });
136 info("Wait for the console message related to the content script exception");
137 equal(messages.length, 1, "Got one console message");
138 messages[0].QueryInterface(Ci.nsIScriptError);
139 equal(messages[0].errorMessage, "Error: foo", "We are notified about the plain content script exception via the console");
140 ok(messages[0].stack, "The message has a stack");