test_import_es6_modules.js (7853B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 add_task(async function() { 5 // Test basic import. 6 let ns = ChromeUtils.importESModule("resource://test/es6module.js"); 7 Assert.equal(ns.loadCount, 1); 8 Assert.equal(ns.value, 2); 9 10 // Test re-import of the same module. 11 let ns2 = ChromeUtils.importESModule("resource://test/es6module.js"); 12 Assert.equal(ns.loadCount, 1); 13 Assert.equal(ns, ns2); 14 15 // Test imports with absolute and relative URIs return the same thing. 16 let ns3 = ChromeUtils.importESModule("resource://test/es6module_absolute.js"); 17 let ns4 = ChromeUtils.importESModule("resource://test/es6module_absolute2.js"); 18 Assert.ok(ns3.absoluteX === ns3.relativeX); 19 Assert.ok(ns3.absoluteX === ns4.x); 20 21 // Test load failure. 22 testFailure("resource://test/es6module_not_found.js", { 23 type: "Error", 24 message: "Failed to load resource://test/es6module_not_found.js", 25 fileName: "test_import_es6_modules.js", 26 stack: "testFailure", 27 lineNumber: "*", 28 columnNumber: "*", 29 result: Cr.NS_ERROR_FILE_NOT_FOUND, 30 }); 31 32 // Test load failure in import. 33 testFailure("resource://test/es6module_missing_import.js", { 34 type: "Error", 35 message: "Failed to load resource://test/es6module_not_found2.js", 36 fileName: "test_import_es6_modules.js", 37 stack: "testFailure", 38 lineNumber: "*", 39 columnNumber: "*", 40 result: Cr.NS_ERROR_FILE_NOT_FOUND, 41 }); 42 43 // Test parse error. 44 testFailure("resource://test/es6module_parse_error.js", { 45 type: "SyntaxError", 46 fileName: "resource://test/es6module_parse_error.js", 47 stack: "testFailure", 48 lineNumber: 1, 49 columnNumber: 6, 50 }); 51 52 // Test parse error in import. 53 testFailure("resource://test/es6module_parse_error_in_import.js", { 54 type: "SyntaxError", 55 fileName: "resource://test/es6module_parse_error.js", 56 stack: "testFailure", 57 lineNumber: 1, 58 columnNumber: 6, 59 }); 60 61 // Test import error. 62 testFailure("resource://test/es6module_import_error.js", { 63 type: "SyntaxError", 64 fileName: "resource://test/es6module_import_error.js", 65 lineNumber: 1, 66 columnNumber: 10, 67 }); 68 69 // Test execution failure. 70 let exception1 = testFailure("resource://test/es6module_throws.js", { 71 type: "Error", 72 message: "foobar", 73 stack: "throwFunction", 74 fileName: "resource://test/es6module_throws.js", 75 lineNumber: 2, 76 columnNumber: 9, 77 }); 78 79 // Test re-import throws the same exception. 80 let exception2 = testFailure("resource://test/es6module_throws.js", { 81 type: "Error", 82 message: "foobar", 83 stack: "throwFunction", 84 fileName: "resource://test/es6module_throws.js", 85 lineNumber: 2, 86 columnNumber: 9, 87 }); 88 Assert.ok(exception1 === exception2); 89 90 // Test loading cyclic module graph. 91 ns = ChromeUtils.importESModule("resource://test/es6module_cycle_a.js"); 92 Assert.ok(ns.loaded); 93 Assert.equal(ns.getValueFromB(), "b"); 94 ns = ChromeUtils.importESModule("resource://test/es6module_cycle_b.js"); 95 Assert.ok(ns.loaded); 96 Assert.equal(ns.getValueFromC(), "c"); 97 ns = ChromeUtils.importESModule("resource://test/es6module_cycle_c.js"); 98 Assert.ok(ns.loaded); 99 Assert.equal(ns.getValueFromA(), "a"); 100 101 // Test top-level await is not supported. 102 testFailure("resource://test/es6module_top_level_await.js", { 103 type: "SyntaxError", 104 message: "not supported", 105 stack: "testFailure", 106 fileName: "resource://test/es6module_top_level_await.js", 107 lineNumber: 1, 108 columnNumber: 1, 109 }); 110 }); 111 112 add_task(async function testDynamicImport() { 113 // Dynamic import while and after evaluating top-level script. 114 let ns = ChromeUtils.importESModule("resource://test/es6module_dynamic_import.js"); 115 let ns2 = await ns.result; 116 Assert.equal(ns2.x, 10); 117 118 ns2 = await ns.doImport(); 119 Assert.equal(ns2.y, 20); 120 121 // Dynamic import for statically imported module. 122 Assert.equal(ns.callGetCounter(), 1); 123 ns.callSetCounter(5); 124 Assert.equal(ns.callGetCounter(), 5); 125 126 const { getCounter, setCounter } = await ns.doImportStatic(); 127 Assert.equal(getCounter(), 5); 128 setCounter(8); 129 Assert.equal(getCounter(), 8); 130 Assert.equal(ns.callGetCounter(), 8); 131 132 // Dynamic import for missing file. 133 ns = ChromeUtils.importESModule("resource://test/es6module_dynamic_import_missing.js"); 134 let e = await ns.result; 135 checkException(e, { 136 type: "TypeError", 137 message: "error loading dynamically imported", 138 fileName: "resource://test/es6module_dynamic_import_missing.js", 139 lineNumber: 5, 140 columnNumber: 1, 141 }); 142 143 e = await ns.doImport(); 144 checkException(e, { 145 type: "TypeError", 146 message: "error loading dynamically imported", 147 fileName: "resource://test/es6module_dynamic_import_missing.js", 148 lineNumber: 11, 149 columnNumber: 5, 150 }); 151 152 // Syntax error in dynamic import. 153 ns = ChromeUtils.importESModule("resource://test/es6module_dynamic_import_syntax_error.js"); 154 e = await ns.result; 155 checkException(e, { 156 type: "SyntaxError", 157 message: "unexpected token", 158 fileName: "resource://test/es6module_dynamic_import_syntax_error2.js", 159 lineNumber: 1, 160 columnNumber: 3, 161 }); 162 163 e = await ns.doImport(); 164 checkException(e, { 165 type: "SyntaxError", 166 message: "unexpected token", 167 fileName: "resource://test/es6module_dynamic_import_syntax_error3.js", 168 lineNumber: 1, 169 columnNumber: 4, 170 }); 171 172 // Runtime error in dynamic import. 173 ns = ChromeUtils.importESModule("resource://test/es6module_dynamic_import_runtime_error.js"); 174 e = await ns.result; 175 checkException(e, { 176 type: "ReferenceError", 177 message: "foo is not defined", 178 fileName: "resource://test/es6module_dynamic_import_runtime_error2.js", 179 lineNumber: 2, 180 columnNumber: 1, 181 }); 182 183 e = await ns.doImport(); 184 checkException(e, { 185 type: "ReferenceError", 186 message: "bar is not defined", 187 fileName: "resource://test/es6module_dynamic_import_runtime_error3.js", 188 lineNumber: 2, 189 columnNumber: 1, 190 }); 191 }); 192 193 function testFailure(url, expected) { 194 let threw = false; 195 let exception; 196 let importLine, importColumn; 197 try { 198 // Get the line/column for ChromeUtils.importESModule. 199 // lineNumber/columnNumber value with "*" in `expected` points the 200 // line/column. 201 let e = new Error(); 202 importLine = e.lineNumber + 3; 203 importColumn = 17; 204 ChromeUtils.importESModule(url); 205 } catch (e) { 206 threw = true; 207 exception = e; 208 } 209 210 Assert.ok(threw, "Error should be thrown"); 211 212 checkException(exception, expected, importLine, importColumn); 213 214 return exception; 215 } 216 217 function checkException(exception, expected, importLine, importColumn) { 218 if ("type" in expected) { 219 Assert.equal(exception.constructor.name, expected.type, "error type"); 220 } 221 if ("message" in expected) { 222 Assert.ok(exception.message.includes(expected.message), 223 `Message "${exception.message}" should contain "${expected.message}"`); 224 } 225 if ("stack" in expected) { 226 Assert.ok(exception.stack.includes(expected.stack), 227 `Stack "${exception.stack}" should contain "${expected.stack}"`); 228 } 229 if ("fileName" in expected) { 230 Assert.ok(exception.fileName.includes(expected.fileName), 231 `fileName "${exception.fileName}" should contain "${expected.fileName}"`); 232 } 233 if ("lineNumber" in expected) { 234 let expectedLine = expected.lineNumber; 235 if (expectedLine === "*") { 236 expectedLine = importLine; 237 } 238 Assert.equal(exception.lineNumber, expectedLine, "lineNumber"); 239 } 240 if ("columnNumber" in expected) { 241 let expectedColumn = expected.columnNumber; 242 if (expectedColumn === "*") { 243 expectedColumn = importColumn; 244 } 245 Assert.equal(exception.columnNumber, expectedColumn, "columnNumber"); 246 } 247 if ("result" in expected) { 248 Assert.equal(exception.result, expected.result, "result"); 249 } 250 }