test_compileScript.js (5317B)
1 "use strict"; 2 3 const { AddonTestUtils } = ChromeUtils.importESModule( 4 "resource://testing-common/AddonTestUtils.sys.mjs" 5 ); 6 7 AddonTestUtils.init(this); 8 9 add_task(async function() { 10 let scriptUrl = Services.io.newFileURI(do_get_file("file_simple_script.js")).spec; 11 12 13 let script1 = await ChromeUtils.compileScript(scriptUrl, {hasReturnValue: true}); 14 let script2 = await ChromeUtils.compileScript(scriptUrl, {hasReturnValue: false}); 15 16 equal(script1.url, scriptUrl, "Script URL is correct") 17 equal(script2.url, scriptUrl, "Script URL is correct") 18 19 equal(script1.hasReturnValue, true, "Script hasReturnValue property is correct") 20 equal(script2.hasReturnValue, false, "Script hasReturnValue property is correct") 21 22 23 // Test return-value version. 24 25 let sandbox1 = Cu.Sandbox("http://example.com"); 26 let sandbox2 = Cu.Sandbox("http://example.org"); 27 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"); 31 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"); 35 36 37 // Test no-return-value version. 38 39 sandbox1.bar = null; 40 equal(sandbox1.bar, null); 41 42 obj = script2.executeInGlobal(sandbox1); 43 equal(obj, undefined, "No-return script has no return value"); 44 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"); 47 48 49 sandbox2.bar = null; 50 equal(sandbox2.bar, null); 51 52 obj = script2.executeInGlobal(sandbox2); 53 equal(obj, undefined, "No-return script has no return value"); 54 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"); 57 }); 58 59 add_task(async function test_syntaxError() { 60 // Generate an artificially large script to force off-main-thread 61 // compilation. 62 let scriptUrl = `data:,${";".repeat(1024 * 1024)}(`; 63 64 await Assert.rejects( 65 ChromeUtils.compileScript(scriptUrl), 66 SyntaxError); 67 68 // Generate a small script to force main thread compilation. 69 scriptUrl = `data:,;(`; 70 71 await Assert.rejects( 72 ChromeUtils.compileScript(scriptUrl), 73 SyntaxError); 74 }); 75 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(); 80 return { 81 fileName: err.fileName, 82 stackFirstLine: err.stack.split("\n")[0], 83 }; 84 } 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 }); 89 90 equal(script1.url, scriptUrl, "Script URL is correct"); 91 equal(script2.url, "dummy filename", "Script URL overridden"); 92 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"); 97 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"); 101 }); 102 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$/ 110 ); 111 112 await Assert.rejects( 113 ChromeUtils.compileScript("resource:///invalid.ftl", { filename: "bye bye" }), 114 /^Unable to load script: bye bye$/ 115 ); 116 }); 117 118 /** 119 * Assert that executeInGlobal throws a special exception when the content script throws. 120 * And the content script exception is notified to the console. 121 */ 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"); 126 127 Assert.throws(() => script.executeInGlobal(sandbox), 128 /Error: foo/, 129 "Without reportException set to true, executeInGlobal throws an exception"); 130 131 info("With reportException, executeInGlobal doesn't throw, but notifies the console"); 132 const { messages } = await AddonTestUtils.promiseConsoleOutput(() => { 133 script.executeInGlobal(sandbox, { reportExceptions: true }); 134 }); 135 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"); 141 });