Backed out changeset 713114c0331a (bug 1938707) by developer request CLOSED TREE
[gecko.git] / js / xpconnect / tests / unit / test_import_es6_modules.js
blob30b4edab9fa5ac16ea1821ca961fa912c379ac73
1 /* Any copyright is dedicated to the Public Domain.
2  * http://creativecommons.org/publicdomain/zero/1.0/ */
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);
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);
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);
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   });
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   });
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   });
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   });
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   });
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   });
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);
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");
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   });
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);
118   ns2 = await ns.doImport();
119   Assert.equal(ns2.y, 20);
121   // Dynamic import for statically imported module.
122   Assert.equal(ns.callGetCounter(), 1);
123   ns.callSetCounter(5);
124   Assert.equal(ns.callGetCounter(), 5);
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);
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   });
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   });
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   });
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   });
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   });
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   });
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   }
210   Assert.ok(threw, "Error should be thrown");
212   checkException(exception, expected, importLine, importColumn);
214   return exception;
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   }