Backed out changeset 713114c0331a (bug 1938707) by developer request CLOSED TREE
[gecko.git] / js / xpconnect / tests / unit / test_import_global_current.js
blob59037512f3bfda2397455a1833ac8649a2712d2e
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 add_task(async function testSandbox() {
6   const uri = "http://example.com/";
7   const window = createContentWindow(uri);
8   const sandboxOpts = {
9     sandboxPrototype: window,
10     wantGlobalProperties: ["ChromeUtils"],
11   };
12   const sb = new Cu.Sandbox(uri, sandboxOpts);
14   Cu.evalInSandbox(`
15 globalThis["loaded"] = [];
16 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", {
17   global: "current",
18 });
19 `, sb);
21   Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb), 0);
22   Cu.evalInSandbox(`ns.incCounter();`, sb);
23   Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb), 1);
25   Assert.equal(Cu.evalInSandbox(`globalThis["loaded"].join(",")`, sb), "2,1");
26 });
28 add_task(async function testNoWindowSandbox() {
29   // Sandbox without window doesn't have ScriptLoader, and Sandbox's
30   // ModuleLoader cannot be created.
31   const systemPrincipal = Components.Constructor(
32     "@mozilla.org/systemprincipal;1",
33     "nsIPrincipal"
34   )();
35   const sandboxOpts = {
36     wantGlobalProperties: ["ChromeUtils"],
37   };
39   const sb = new Cu.Sandbox(systemPrincipal, sandboxOpts);
41   let caught = false;
42   try {
43   Cu.evalInSandbox(`
44 ChromeUtils.importESModule("resource://test/non_shared_1.mjs", {
45   global: "current",
46 });
47 `, sb);
48   } catch (e) {
49     caught = true;
50     Assert.stringMatches(e.message, /No ModuleLoader found/);
51   }
52   Assert.ok(caught);
53 });
55 add_task(async function testWindow() {
56   const win1 = createChromeWindow();
58   win1.eval(`
59 globalThis["loaded"] = [];
60 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", {
61   global: "current",
62 });
63 `);
65   Assert.equal(win1.eval(`ns.getCounter();`), 0);
66   win1.eval(`ns.incCounter();`);
67   Assert.equal(win1.eval(`ns.getCounter();`), 1);
69   Assert.equal(win1.eval(`globalThis["loaded"].join(",")`), "2,1");
70 });
72 add_task(async function testReImport() {
73   // Re-importing the same module should return the same thing.
75   const uri = "http://example.com/";
76   const window = createContentWindow(uri);
77   const sandboxOpts = {
78     sandboxPrototype: window,
79     wantGlobalProperties: ["ChromeUtils"],
80   };
81   const sb = new Cu.Sandbox(uri, sandboxOpts);
83   Cu.evalInSandbox(`
84 globalThis["loaded"] = [];
85 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", {
86   global: "current",
87 });
88 `, sb);
90   Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb), 0);
91   Cu.evalInSandbox(`ns.incCounter();`, sb);
92   Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb), 1);
94   Assert.equal(Cu.evalInSandbox(`globalThis["loaded"].join(",")`, sb), "2,1");
96   Cu.evalInSandbox(`
97 var ns2 = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", {
98   global: "current",
99 });
100 `, sb);
102   // The counter should be shared, and also not reset.
103   Assert.equal(Cu.evalInSandbox(`ns2.getCounter();`, sb), 1);
104   Cu.evalInSandbox(`ns2.incCounter();`, sb);
105   Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb), 2);
106   Assert.equal(Cu.evalInSandbox(`ns2.getCounter();`, sb), 2);
108   // The top-level script shouldn't be executed twice.
109   Assert.equal(Cu.evalInSandbox(`globalThis["loaded"].join(",")`, sb), "2,1");
112 add_task(async function testNotFound() {
113   // Importing non-existent file should throw error.
115   const uri = "http://example.com/";
116   const window = createContentWindow(uri);
117   const sandboxOpts = {
118     sandboxPrototype: window,
119     wantGlobalProperties: ["ChromeUtils"],
120   };
121   const sb = new Cu.Sandbox(uri, sandboxOpts);
123   let caught = false;
124   try {
125   Cu.evalInSandbox(`
126 ChromeUtils.importESModule("resource://test/not_found.mjs", {
127   global: "current",
129 `, sb);
130   } catch (e) {
131     caught = true;
132     Assert.stringMatches(e.message, /Failed to load/);
133   }
134   Assert.ok(caught);
137 add_task(async function testParseError() {
138   // Parse error should be thrown.
140   const uri = "http://example.com/";
141   const window = createContentWindow(uri);
142   const sandboxOpts = {
143     sandboxPrototype: window,
144     wantGlobalProperties: ["ChromeUtils"],
145   };
146   const sb = new Cu.Sandbox(uri, sandboxOpts);
148   let caught = false;
149   try {
150   Cu.evalInSandbox(`
151 ChromeUtils.importESModule("resource://test/es6module_parse_error.js", {
152   global: "current",
154 `, sb);
155   } catch (e) {
156     caught = true;
157     Assert.stringMatches(e.message, /unexpected token/);
158   }
159   Assert.ok(caught);
162 add_task(async function testParseErrorInImport() {
163   // Parse error in imported module should be thrown.
165   const uri = "http://example.com/";
166   const window = createContentWindow(uri);
167   const sandboxOpts = {
168     sandboxPrototype: window,
169     wantGlobalProperties: ["ChromeUtils"],
170   };
171   const sb = new Cu.Sandbox(uri, sandboxOpts);
173   let caught = false;
174   try {
175   Cu.evalInSandbox(`
176 ChromeUtils.importESModule("resource://test/es6module_parse_error_in_import.js", {
177   global: "current",
179 `, sb);
180   } catch (e) {
181     caught = true;
182     Assert.stringMatches(e.message, /unexpected token/);
183   }
184   Assert.ok(caught);
187 add_task(async function testImportError() {
188   // Error for nested import should be thrown.
190   const uri = "http://example.com/";
191   const window = createContentWindow(uri);
192   const sandboxOpts = {
193     sandboxPrototype: window,
194     wantGlobalProperties: ["ChromeUtils"],
195   };
196   const sb = new Cu.Sandbox(uri, sandboxOpts);
198   let caught = false;
199   try {
200   Cu.evalInSandbox(`
201 ChromeUtils.importESModule("resource://test/es6module_import_error.js", {
202   global: "current",
204 `, sb);
205   } catch (e) {
206     caught = true;
207     Assert.stringMatches(e.message, /doesn't provide an export named/);
208   }
209   Assert.ok(caught);
212 add_task(async function testExecutionError() {
213   // Error while execution the top-level script should be thrown.
215   const uri = "http://example.com/";
216   const window = createContentWindow(uri);
217   const sandboxOpts = {
218     sandboxPrototype: window,
219     wantGlobalProperties: ["ChromeUtils"],
220   };
221   const sb = new Cu.Sandbox(uri, sandboxOpts);
223   let caught = false;
224   try {
225   Cu.evalInSandbox(`
226 ChromeUtils.importESModule("resource://test/es6module_throws.js", {
227   global: "current",
229 `, sb);
230   } catch (e) {
231     caught = true;
232     Assert.stringMatches(e.message, /foobar/);
233   }
234   Assert.ok(caught);
236   // Re-import should throw the same error.
238   caught = false;
239   try {
240   Cu.evalInSandbox(`
241 ChromeUtils.importESModule("resource://test/es6module_throws.js", {
242   global: "current",
244 `, sb);
245   } catch (e) {
246     caught = true;
247     Assert.stringMatches(e.message, /foobar/);
248   }
249   Assert.ok(caught);
252 add_task(async function testImportNestShared() {
253   // Importing system ESM should work.
255   const win1 = createChromeWindow();
257   const result = win1.eval(`
258 const { func1 } = ChromeUtils.importESModule("resource://test/non_shared_nest_import_shared_1.mjs", {
259   global: "current",
261 func1();
264   Assert.equal(result, 27);
267 add_task(async function testImportNestNonSharedSame() {
268   // For the same global, nested import for non-shared global is allowed while
269   // executing top-level script.
271   const win1 = createChromeWindow();
273   const result = win1.eval(`
274 const { func } = ChromeUtils.importESModule("resource://test/non_shared_nest_import_non_shared_1.mjs", {
275   global: "current",
277 func();
279   Assert.equal(result, 10);
282 add_task(async function testImportNestNonSharedDifferent() {
283   // For the different globals, nested import for non-shared global isn't
284   // allowed while executing top-level script.
286   const win1 = createChromeWindow();
288   const uri = "http://example.com/";
289   const window = createContentWindow(uri);
290   const sandboxOpts = {
291     sandboxPrototype: window,
292     wantGlobalProperties: ["ChromeUtils"],
293   };
294   win1.sb = new Cu.Sandbox(uri, sandboxOpts);
296   let caught = false;
297   try {
298   win1.eval(`
299 ChromeUtils.importESModule("resource://test/non_shared_nest_import_non_shared_2.mjs", {
300   global: "current",
303   } catch (e) {
304     caught = true;
305     Assert.stringMatches(e.message, /cannot be used for different global/);
306   }
307   Assert.ok(caught);
310 add_task(async function testImportNestNonSharedAfterImport() {
311   // Nested import for non-shared global is allowed after the import, both for
312   // the same and different globals.
314   const win1 = createChromeWindow();
316   const uri = "http://example.com/";
317   const window = createContentWindow(uri);
318   const sandboxOpts = {
319     sandboxPrototype: window,
320     wantGlobalProperties: ["ChromeUtils"],
321   };
322   win1.sb = new Cu.Sandbox(uri, sandboxOpts);
324   const result = win1.eval(`
325 const { func3 } = ChromeUtils.importESModule("resource://test/non_shared_nest_import_non_shared_3.mjs", {
326   global: "current",
329 // Nested import happens here.
330 func3();
332   Assert.equal(result, 22);
335 add_task(async function testIsolationWithSandbox() {
336   // Modules should be isolated for each sandbox.
338   const uri = "http://example.com/";
339   const window = createContentWindow(uri);
340   const sandboxOpts = {
341     sandboxPrototype: window,
342     wantGlobalProperties: ["ChromeUtils"],
343   };
344   const sb1 = new Cu.Sandbox(uri, sandboxOpts);
345   const sb2 = new Cu.Sandbox(uri, sandboxOpts);
346   const sb3 = new Cu.Sandbox(uri, sandboxOpts);
348   // Verify modules in 2 sandboxes are isolated.
350   Cu.evalInSandbox(`
351 globalThis["loaded"] = [];
352 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", {
353   global: "current",
355 `, sb1);
356   Cu.evalInSandbox(`
357 globalThis["loaded"] = [];
358 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", {
359   global: "current",
361 `, sb2);
363   Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb1), 0);
364   Cu.evalInSandbox(`ns.incCounter();`, sb1);
365   Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb1), 1);
367   Assert.equal(Cu.evalInSandbox(`globalThis["loaded"].join(",")`, sb1), "2,1");
369   Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb2), 0);
370   Cu.evalInSandbox(`ns.incCounter();`, sb2);
371   Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb2), 1);
373   Assert.equal(Cu.evalInSandbox(`globalThis["loaded"].join(",")`, sb2), "2,1");
375   // Verify importing after any modification to different global doesn't affect.
377   const ns3 = Cu.evalInSandbox(`
378 globalThis["loaded"] = [];
379 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", {
380   global: "current",
382 `, sb3);
384   Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb3), 0);
385   Cu.evalInSandbox(`ns.incCounter();`, sb3);
386   Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb3), 1);
388   Assert.equal(Cu.evalInSandbox(`globalThis["loaded"].join(",")`, sb3), "2,1");
390   // Verify yet another modification are still isolated.
392   Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb1), 1);
393   Cu.evalInSandbox(`ns.incCounter();`, sb1);
394   Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb1), 2);
396   Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb2), 1);
397   Cu.evalInSandbox(`ns.incCounter();`, sb2);
398   Cu.evalInSandbox(`ns.incCounter();`, sb2);
399   Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb2), 3);
401   Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb3), 1);
402   Cu.evalInSandbox(`ns.incCounter();`, sb3);
403   Cu.evalInSandbox(`ns.incCounter();`, sb3);
404   Cu.evalInSandbox(`ns.incCounter();`, sb3);
405   Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb3), 4);
407   // Verify the module's `globalThis` points the target global.
409   Cu.evalInSandbox(`ns.putCounter();`, sb1);
410   Cu.evalInSandbox(`ns.putCounter();`, sb2);
411   Cu.evalInSandbox(`ns.putCounter();`, sb3);
413   const counter1 = Cu.evalInSandbox(`globalThis["counter"]`, sb1);
414   Assert.equal(counter1, 2);
415   const counter2 = Cu.evalInSandbox(`globalThis["counter"]`, sb2);
416   Assert.equal(counter2, 3);
417   const counter3 = Cu.evalInSandbox(`globalThis["counter"]`, sb3);
418   Assert.equal(counter3, 4);
421 add_task(async function testIsolationWithWindow() {
422   // Modules should be isolated for each window.
424   const win1 = createChromeWindow();
425   const win2 = createChromeWindow();
426   const win3 = createChromeWindow();
428   // Verify modules in 2 sandboxes are isolated.
430   win1.eval(`
431 globalThis["loaded"] = [];
432 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", {
433   global: "current",
436   win2.eval(`
437 globalThis["loaded"] = [];
438 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", {
439   global: "current",
443   Assert.equal(win1.eval(`ns.getCounter();`), 0);
444   win1.eval(`ns.incCounter();`);
445   Assert.equal(win1.eval(`ns.getCounter();`), 1);
447   Assert.equal(win1.eval(`globalThis["loaded"].join(",")`), "2,1");
449   Assert.equal(win2.eval(`ns.getCounter();`), 0);
450   win2.eval(`ns.incCounter();`);
451   Assert.equal(win2.eval(`ns.getCounter();`), 1);
453   Assert.equal(win2.eval(`globalThis["loaded"].join(",")`), "2,1");
455   // Verify importing after any modification to different global doesn't affect.
457   const ns3 = win3.eval(`
458 globalThis["loaded"] = [];
459 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", {
460   global: "current",
464   Assert.equal(win3.eval(`ns.getCounter();`), 0);
465   win3.eval(`ns.incCounter();`);
466   Assert.equal(win3.eval(`ns.getCounter();`), 1);
468   Assert.equal(win3.eval(`globalThis["loaded"].join(",")`), "2,1");
470   // Verify yet another modification are still isolated.
472   Assert.equal(win1.eval(`ns.getCounter();`), 1);
473   win1.eval(`ns.incCounter();`);
474   Assert.equal(win1.eval(`ns.getCounter();`), 2);
476   Assert.equal(win2.eval(`ns.getCounter();`), 1);
477   win2.eval(`ns.incCounter();`);
478   win2.eval(`ns.incCounter();`);
479   Assert.equal(win2.eval(`ns.getCounter();`), 3);
481   Assert.equal(win3.eval(`ns.getCounter();`), 1);
482   win3.eval(`ns.incCounter();`);
483   win3.eval(`ns.incCounter();`);
484   win3.eval(`ns.incCounter();`);
485   Assert.equal(win3.eval(`ns.getCounter();`), 4);
487   // Verify the module's `globalThis` points the target global.
489   win1.eval(`ns.putCounter();`);
490   win2.eval(`ns.putCounter();`);
491   win3.eval(`ns.putCounter();`);
493   const counter1 = win1.eval(`globalThis["counter"]`);
494   Assert.equal(counter1, 2);
495   const counter2 = win2.eval(`globalThis["counter"]`);
496   Assert.equal(counter2, 3);
497   const counter3 = win3.eval(`globalThis["counter"]`);
498   Assert.equal(counter3, 4);
501 add_task(async function testSyncImportBeforeAsyncImportTopLevel() {
502   const window = createChromeWindow();
504   window.eval(`
505 globalThis["loaded"] = [];
506 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", {
507   global: "current",
511   Assert.equal(window.eval(`ns.getCounter();`), 0);
512   window.eval(`ns.incCounter();`);
513   Assert.equal(window.eval(`ns.getCounter();`), 1);
515   Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1");
517   window.eval(`
518 var ns2 = null;
519 const nsPromise = import("resource://test/non_shared_1.mjs");
520 nsPromise.then(v => { ns2 = v; });
523   Services.tm.spinEventLoopUntil(
524     "Wait until dynamic import finishes",
525     () => window.eval(`ns2 !== null`)
526   );
528   Assert.equal(window.eval(`ns2.getCounter();`), 1);
529   window.eval(`ns2.incCounter();`);
530   Assert.equal(window.eval(`ns2.getCounter();`), 2);
531   Assert.equal(window.eval(`ns.getCounter();`), 2);
533   Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1");
536 add_task(async function testSyncImportBeforeAsyncImportDependency() {
537   const window = createChromeWindow();
539   window.eval(`
540 globalThis["loaded"] = [];
541 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", {
542   global: "current",
546   Assert.equal(window.eval(`ns.getCounter();`), 0);
547   window.eval(`ns.incCounter();`);
548   Assert.equal(window.eval(`ns.getCounter();`), 1);
550   Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1");
552   window.eval(`
553 var ns2 = null;
554 const nsPromise = import("resource://test/import_non_shared_1.mjs");
555 nsPromise.then(v => { ns2 = v; });
558   Services.tm.spinEventLoopUntil(
559     "Wait until dynamic import finishes",
560     () => window.eval(`ns2 !== null`)
561   );
563   Assert.equal(window.eval(`ns2.getCounter();`), 1);
564   window.eval(`ns2.incCounter();`);
565   Assert.equal(window.eval(`ns2.getCounter();`), 2);
566   Assert.equal(window.eval(`ns.getCounter();`), 2);
568   Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1");
571 add_task(async function testSyncImportAfterAsyncImportTopLevel() {
572   const window = createChromeWindow();
574   window.eval(`
575 var ns = null;
576 globalThis["loaded"] = [];
577 const nsPromise = import("resource://test/non_shared_1.mjs");
578 nsPromise.then(v => { ns = v; });
581   Services.tm.spinEventLoopUntil(
582     "Wait until dynamic import finishes",
583     () => window.eval(`ns !== null`)
584   );
586   Assert.equal(window.eval(`ns.getCounter();`), 0);
587   window.eval(`ns.incCounter();`);
588   Assert.equal(window.eval(`ns.getCounter();`), 1);
590   Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1");
592   window.eval(`
593 var ns2 = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", {
594   global: "current",
598   Assert.equal(window.eval(`ns2.getCounter();`), 1);
599   window.eval(`ns2.incCounter();`);
600   Assert.equal(window.eval(`ns2.getCounter();`), 2);
601   Assert.equal(window.eval(`ns.getCounter();`), 2);
603   Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1");
606 add_task(async function testSyncImportAfterAsyncImportDependency() {
607   const window = createChromeWindow();
609   window.eval(`
610 var ns = null;
611 globalThis["loaded"] = [];
612 const nsPromise = import("resource://test/non_shared_1.mjs");
613 nsPromise.then(v => { ns = v; });
616   Services.tm.spinEventLoopUntil(
617     "Wait until dynamic import finishes",
618     () => window.eval(`ns !== null`)
619   );
621   Assert.equal(window.eval(`ns.getCounter();`), 0);
622   window.eval(`ns.incCounter();`);
623   Assert.equal(window.eval(`ns.getCounter();`), 1);
625   Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1");
627   window.eval(`
628 var ns2 = ChromeUtils.importESModule("resource://test/import_non_shared_1.mjs", {
629   global: "current",
633   Assert.equal(window.eval(`ns2.getCounter();`), 1);
634   window.eval(`ns2.incCounter();`);
635   Assert.equal(window.eval(`ns2.getCounter();`), 2);
636   Assert.equal(window.eval(`ns.getCounter();`), 2);
638   Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1");
641 add_task(async function testSyncImportWhileAsyncImportTopLevel() {
642   const window = createChromeWindow();
644   window.eval(`
645 var ns = null;
646 globalThis["loaded"] = [];
647 const nsPromise = import("resource://test/non_shared_1.mjs");
648 nsPromise.then(v => { ns = v; });
651   window.eval(`
652 var ns2 = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", {
653   global: "current",
657   Assert.equal(window.eval(`ns2.getCounter();`), 0);
658   window.eval(`ns2.incCounter();`);
659   Assert.equal(window.eval(`ns2.getCounter();`), 1);
661   Services.tm.spinEventLoopUntil(
662     "Wait until dynamic import finishes",
663     () => window.eval(`ns !== null`)
664   );
666   Assert.equal(window.eval(`ns.getCounter();`), 1);
667   window.eval(`ns.incCounter();`);
668   Assert.equal(window.eval(`ns.getCounter();`), 2);
669   Assert.equal(window.eval(`ns2.getCounter();`), 2);
671   Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1");
674 add_task(async function testSyncImportWhileAsyncImportDependency() {
675   const window = createChromeWindow();
677   window.eval(`
678 var ns = null;
679 globalThis["loaded"] = [];
680 const nsPromise = import("resource://test/non_shared_1.mjs");
681 nsPromise.then(v => { ns = v; });
684   window.eval(`
685 var ns2 = ChromeUtils.importESModule("resource://test/import_non_shared_1.mjs", {
686   global: "current",
690   Assert.equal(window.eval(`ns2.getCounter();`), 0);
691   window.eval(`ns2.incCounter();`);
692   Assert.equal(window.eval(`ns2.getCounter();`), 1);
694   Services.tm.spinEventLoopUntil(
695     "Wait until dynamic import finishes",
696     () => window.eval(`ns !== null`)
697   );
699   Assert.equal(window.eval(`ns.getCounter();`), 1);
700   window.eval(`ns.incCounter();`);
701   Assert.equal(window.eval(`ns.getCounter();`), 2);
702   Assert.equal(window.eval(`ns2.getCounter();`), 2);
704   Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1");
707 add_task(async function testSyncImportBeforeAsyncImportTLA() {
708   // Top-level-await is not supported by sync import.
710   const window = createChromeWindow();
712   let caught = false;
714   try {
715     window.eval(`
716 ChromeUtils.importESModule("resource://test/es6module_top_level_await.js", {
717   global: "current",
720   } catch (e) {
721     caught = true;
722     Assert.stringMatches(e.message, /top level await is not supported/);
723   }
724   Assert.ok(caught);
726   window.eval(`
727 var ns2 = null;
728 const nsPromise = import("resource://test/es6module_top_level_await.js");
729 nsPromise.then(v => { ns2 = v; });
732   Services.tm.spinEventLoopUntil(
733     "Wait until dynamic import finishes",
734     () => window.eval(`ns2 !== null`)
735   );
737   Assert.equal(window.eval(`ns2.foo();`), 10);
740 add_task(async function testSyncImportAfterAsyncImportTLA() {
741   // Top-level-await is not supported by sync import, but if the module is
742   // already imported, the existing module namespace is returned.
744   const window = createChromeWindow();
746   window.eval(`
747 var ns2 = null;
748 const nsPromise = import("resource://test/es6module_top_level_await.js");
749 nsPromise.then(v => { ns2 = v; });
752   Services.tm.spinEventLoopUntil(
753     "Wait until dynamic import finishes",
754     () => window.eval(`ns2 !== null`)
755   );
757   Assert.equal(window.eval(`ns2.foo();`), 10);
759   window.eval(`
760 var ns = ChromeUtils.importESModule("resource://test/es6module_top_level_await.js", {
761   global: "current",
765   Assert.equal(window.eval(`ns.foo();`), 10);
766   Assert.equal(window.eval(`ns2.foo == ns.foo;`), true);
769 add_task(async function testSyncImportWhileAsyncImportTLA() {
770   // Top-level-await is not supported by sync import, but if the module is
771   // already fetching, ChromeUtils.importESModule waits for it and, the
772   // async-imported module namespace is returned.
774   const window = createChromeWindow();
776   window.eval(`
777 var ns2 = null;
778 const nsPromise = import("resource://test/es6module_top_level_await.js");
779 nsPromise.then(v => { ns2 = v; });
782   window.eval(`
783 var ns = ChromeUtils.importESModule("resource://test/es6module_top_level_await.js", {
784   global: "current",
788   Services.tm.spinEventLoopUntil(
789     "Wait until dynamic import finishes",
790     () => window.eval(`ns2 !== null`)
791   );
793   Assert.equal(window.eval(`ns2.foo();`), 10);
794   Assert.equal(window.eval(`ns.foo();`), 10);
795   Assert.equal(window.eval(`ns2.foo == ns.foo;`), true);