test_import_global_current.js (22481B)
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/. */ 4 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); 13 14 Cu.evalInSandbox(` 15 globalThis["loaded"] = []; 16 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", { 17 global: "current", 18 }); 19 `, sb); 20 21 Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb), 0); 22 Cu.evalInSandbox(`ns.incCounter();`, sb); 23 Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb), 1); 24 25 Assert.equal(Cu.evalInSandbox(`globalThis["loaded"].join(",")`, sb), "2,1"); 26 }); 27 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 }; 38 39 const sb = new Cu.Sandbox(systemPrincipal, sandboxOpts); 40 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 }); 54 55 add_task(async function testWindow() { 56 const win1 = createChromeWindow(); 57 58 win1.eval(` 59 globalThis["loaded"] = []; 60 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", { 61 global: "current", 62 }); 63 `); 64 65 Assert.equal(win1.eval(`ns.getCounter();`), 0); 66 win1.eval(`ns.incCounter();`); 67 Assert.equal(win1.eval(`ns.getCounter();`), 1); 68 69 Assert.equal(win1.eval(`globalThis["loaded"].join(",")`), "2,1"); 70 }); 71 72 add_task(async function testReImport() { 73 // Re-importing the same module should return the same thing. 74 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); 82 83 Cu.evalInSandbox(` 84 globalThis["loaded"] = []; 85 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", { 86 global: "current", 87 }); 88 `, sb); 89 90 Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb), 0); 91 Cu.evalInSandbox(`ns.incCounter();`, sb); 92 Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb), 1); 93 94 Assert.equal(Cu.evalInSandbox(`globalThis["loaded"].join(",")`, sb), "2,1"); 95 96 Cu.evalInSandbox(` 97 var ns2 = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", { 98 global: "current", 99 }); 100 `, sb); 101 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); 107 108 // The top-level script shouldn't be executed twice. 109 Assert.equal(Cu.evalInSandbox(`globalThis["loaded"].join(",")`, sb), "2,1"); 110 }); 111 112 add_task(async function testNotFound() { 113 // Importing non-existent file should throw error. 114 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); 122 123 let caught = false; 124 try { 125 Cu.evalInSandbox(` 126 ChromeUtils.importESModule("resource://test/not_found.mjs", { 127 global: "current", 128 }); 129 `, sb); 130 } catch (e) { 131 caught = true; 132 Assert.stringMatches(e.message, /Failed to load/); 133 } 134 Assert.ok(caught); 135 }); 136 137 add_task(async function testParseError() { 138 // Parse error should be thrown. 139 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); 147 148 let caught = false; 149 try { 150 Cu.evalInSandbox(` 151 ChromeUtils.importESModule("resource://test/es6module_parse_error.js", { 152 global: "current", 153 }); 154 `, sb); 155 } catch (e) { 156 caught = true; 157 Assert.stringMatches(e.message, /unexpected token/); 158 } 159 Assert.ok(caught); 160 }); 161 162 add_task(async function testParseErrorInImport() { 163 // Parse error in imported module should be thrown. 164 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); 172 173 let caught = false; 174 try { 175 Cu.evalInSandbox(` 176 ChromeUtils.importESModule("resource://test/es6module_parse_error_in_import.js", { 177 global: "current", 178 }); 179 `, sb); 180 } catch (e) { 181 caught = true; 182 Assert.stringMatches(e.message, /unexpected token/); 183 } 184 Assert.ok(caught); 185 }); 186 187 add_task(async function testImportError() { 188 // Error for nested import should be thrown. 189 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); 197 198 let caught = false; 199 try { 200 Cu.evalInSandbox(` 201 ChromeUtils.importESModule("resource://test/es6module_import_error.js", { 202 global: "current", 203 }); 204 `, sb); 205 } catch (e) { 206 caught = true; 207 Assert.stringMatches(e.message, /doesn't provide an export named/); 208 } 209 Assert.ok(caught); 210 }); 211 212 add_task(async function testExecutionError() { 213 // Error while execution the top-level script should be thrown. 214 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); 222 223 let caught = false; 224 try { 225 Cu.evalInSandbox(` 226 ChromeUtils.importESModule("resource://test/es6module_throws.js", { 227 global: "current", 228 }); 229 `, sb); 230 } catch (e) { 231 caught = true; 232 Assert.stringMatches(e.message, /foobar/); 233 } 234 Assert.ok(caught); 235 236 // Re-import should throw the same error. 237 238 caught = false; 239 try { 240 Cu.evalInSandbox(` 241 ChromeUtils.importESModule("resource://test/es6module_throws.js", { 242 global: "current", 243 }); 244 `, sb); 245 } catch (e) { 246 caught = true; 247 Assert.stringMatches(e.message, /foobar/); 248 } 249 Assert.ok(caught); 250 }); 251 252 add_task(async function testImportNestShared() { 253 // Importing system ESM should work. 254 255 const win1 = createChromeWindow(); 256 257 const result = win1.eval(` 258 const { func1 } = ChromeUtils.importESModule("resource://test/non_shared_nest_import_shared_1.mjs", { 259 global: "current", 260 }); 261 func1(); 262 `); 263 264 Assert.equal(result, 27); 265 }); 266 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. 270 271 const win1 = createChromeWindow(); 272 273 const result = win1.eval(` 274 const { func } = ChromeUtils.importESModule("resource://test/non_shared_nest_import_non_shared_1.mjs", { 275 global: "current", 276 }); 277 func(); 278 `); 279 Assert.equal(result, 10); 280 }); 281 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. 285 286 const win1 = createChromeWindow(); 287 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); 295 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", 301 }); 302 `); 303 } catch (e) { 304 caught = true; 305 Assert.stringMatches(e.message, /cannot be used for different global/); 306 } 307 Assert.ok(caught); 308 }); 309 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. 313 314 const win1 = createChromeWindow(); 315 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); 323 324 const result = win1.eval(` 325 const { func3 } = ChromeUtils.importESModule("resource://test/non_shared_nest_import_non_shared_3.mjs", { 326 global: "current", 327 }); 328 329 // Nested import happens here. 330 func3(); 331 `); 332 Assert.equal(result, 22); 333 }); 334 335 add_task(async function testIsolationWithSandbox() { 336 // Modules should be isolated for each sandbox. 337 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); 347 348 // Verify modules in 2 sandboxes are isolated. 349 350 Cu.evalInSandbox(` 351 globalThis["loaded"] = []; 352 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", { 353 global: "current", 354 }); 355 `, sb1); 356 Cu.evalInSandbox(` 357 globalThis["loaded"] = []; 358 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", { 359 global: "current", 360 }); 361 `, sb2); 362 363 Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb1), 0); 364 Cu.evalInSandbox(`ns.incCounter();`, sb1); 365 Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb1), 1); 366 367 Assert.equal(Cu.evalInSandbox(`globalThis["loaded"].join(",")`, sb1), "2,1"); 368 369 Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb2), 0); 370 Cu.evalInSandbox(`ns.incCounter();`, sb2); 371 Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb2), 1); 372 373 Assert.equal(Cu.evalInSandbox(`globalThis["loaded"].join(",")`, sb2), "2,1"); 374 375 // Verify importing after any modification to different global doesn't affect. 376 377 const ns3 = Cu.evalInSandbox(` 378 globalThis["loaded"] = []; 379 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", { 380 global: "current", 381 }); 382 `, sb3); 383 384 Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb3), 0); 385 Cu.evalInSandbox(`ns.incCounter();`, sb3); 386 Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb3), 1); 387 388 Assert.equal(Cu.evalInSandbox(`globalThis["loaded"].join(",")`, sb3), "2,1"); 389 390 // Verify yet another modification are still isolated. 391 392 Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb1), 1); 393 Cu.evalInSandbox(`ns.incCounter();`, sb1); 394 Assert.equal(Cu.evalInSandbox(`ns.getCounter();`, sb1), 2); 395 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); 400 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); 406 407 // Verify the module's `globalThis` points the target global. 408 409 Cu.evalInSandbox(`ns.putCounter();`, sb1); 410 Cu.evalInSandbox(`ns.putCounter();`, sb2); 411 Cu.evalInSandbox(`ns.putCounter();`, sb3); 412 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); 419 }); 420 421 add_task(async function testIsolationWithWindow() { 422 // Modules should be isolated for each window. 423 424 const win1 = createChromeWindow(); 425 const win2 = createChromeWindow(); 426 const win3 = createChromeWindow(); 427 428 // Verify modules in 2 sandboxes are isolated. 429 430 win1.eval(` 431 globalThis["loaded"] = []; 432 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", { 433 global: "current", 434 }); 435 `); 436 win2.eval(` 437 globalThis["loaded"] = []; 438 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", { 439 global: "current", 440 }); 441 `); 442 443 Assert.equal(win1.eval(`ns.getCounter();`), 0); 444 win1.eval(`ns.incCounter();`); 445 Assert.equal(win1.eval(`ns.getCounter();`), 1); 446 447 Assert.equal(win1.eval(`globalThis["loaded"].join(",")`), "2,1"); 448 449 Assert.equal(win2.eval(`ns.getCounter();`), 0); 450 win2.eval(`ns.incCounter();`); 451 Assert.equal(win2.eval(`ns.getCounter();`), 1); 452 453 Assert.equal(win2.eval(`globalThis["loaded"].join(",")`), "2,1"); 454 455 // Verify importing after any modification to different global doesn't affect. 456 457 const ns3 = win3.eval(` 458 globalThis["loaded"] = []; 459 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", { 460 global: "current", 461 }); 462 `); 463 464 Assert.equal(win3.eval(`ns.getCounter();`), 0); 465 win3.eval(`ns.incCounter();`); 466 Assert.equal(win3.eval(`ns.getCounter();`), 1); 467 468 Assert.equal(win3.eval(`globalThis["loaded"].join(",")`), "2,1"); 469 470 // Verify yet another modification are still isolated. 471 472 Assert.equal(win1.eval(`ns.getCounter();`), 1); 473 win1.eval(`ns.incCounter();`); 474 Assert.equal(win1.eval(`ns.getCounter();`), 2); 475 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); 480 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); 486 487 // Verify the module's `globalThis` points the target global. 488 489 win1.eval(`ns.putCounter();`); 490 win2.eval(`ns.putCounter();`); 491 win3.eval(`ns.putCounter();`); 492 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); 499 }); 500 501 add_task(async function testSyncImportBeforeAsyncImportTopLevel() { 502 const window = createChromeWindow(); 503 504 window.eval(` 505 globalThis["loaded"] = []; 506 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", { 507 global: "current", 508 }); 509 `); 510 511 Assert.equal(window.eval(`ns.getCounter();`), 0); 512 window.eval(`ns.incCounter();`); 513 Assert.equal(window.eval(`ns.getCounter();`), 1); 514 515 Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1"); 516 517 window.eval(` 518 var ns2 = null; 519 const nsPromise = import("resource://test/non_shared_1.mjs"); 520 nsPromise.then(v => { ns2 = v; }); 521 `); 522 523 Services.tm.spinEventLoopUntil( 524 "Wait until dynamic import finishes", 525 () => window.eval(`ns2 !== null`) 526 ); 527 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); 532 533 Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1"); 534 }); 535 536 add_task(async function testSyncImportBeforeAsyncImportDependency() { 537 const window = createChromeWindow(); 538 539 window.eval(` 540 globalThis["loaded"] = []; 541 var ns = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", { 542 global: "current", 543 }); 544 `); 545 546 Assert.equal(window.eval(`ns.getCounter();`), 0); 547 window.eval(`ns.incCounter();`); 548 Assert.equal(window.eval(`ns.getCounter();`), 1); 549 550 Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1"); 551 552 window.eval(` 553 var ns2 = null; 554 const nsPromise = import("resource://test/import_non_shared_1.mjs"); 555 nsPromise.then(v => { ns2 = v; }); 556 `); 557 558 Services.tm.spinEventLoopUntil( 559 "Wait until dynamic import finishes", 560 () => window.eval(`ns2 !== null`) 561 ); 562 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); 567 568 Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1"); 569 }); 570 571 add_task(async function testSyncImportAfterAsyncImportTopLevel() { 572 const window = createChromeWindow(); 573 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; }); 579 `); 580 581 Services.tm.spinEventLoopUntil( 582 "Wait until dynamic import finishes", 583 () => window.eval(`ns !== null`) 584 ); 585 586 Assert.equal(window.eval(`ns.getCounter();`), 0); 587 window.eval(`ns.incCounter();`); 588 Assert.equal(window.eval(`ns.getCounter();`), 1); 589 590 Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1"); 591 592 window.eval(` 593 var ns2 = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", { 594 global: "current", 595 }); 596 `); 597 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); 602 603 Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1"); 604 }); 605 606 add_task(async function testSyncImportAfterAsyncImportDependency() { 607 const window = createChromeWindow(); 608 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; }); 614 `); 615 616 Services.tm.spinEventLoopUntil( 617 "Wait until dynamic import finishes", 618 () => window.eval(`ns !== null`) 619 ); 620 621 Assert.equal(window.eval(`ns.getCounter();`), 0); 622 window.eval(`ns.incCounter();`); 623 Assert.equal(window.eval(`ns.getCounter();`), 1); 624 625 Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1"); 626 627 window.eval(` 628 var ns2 = ChromeUtils.importESModule("resource://test/import_non_shared_1.mjs", { 629 global: "current", 630 }); 631 `); 632 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); 637 638 Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1"); 639 }); 640 641 add_task(async function testSyncImportWhileAsyncImportTopLevel() { 642 const window = createChromeWindow(); 643 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; }); 649 `); 650 651 window.eval(` 652 var ns2 = ChromeUtils.importESModule("resource://test/non_shared_1.mjs", { 653 global: "current", 654 }); 655 `); 656 657 Assert.equal(window.eval(`ns2.getCounter();`), 0); 658 window.eval(`ns2.incCounter();`); 659 Assert.equal(window.eval(`ns2.getCounter();`), 1); 660 661 Services.tm.spinEventLoopUntil( 662 "Wait until dynamic import finishes", 663 () => window.eval(`ns !== null`) 664 ); 665 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); 670 671 Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1"); 672 }); 673 674 add_task(async function testSyncImportWhileAsyncImportDependency() { 675 const window = createChromeWindow(); 676 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; }); 682 `); 683 684 window.eval(` 685 var ns2 = ChromeUtils.importESModule("resource://test/import_non_shared_1.mjs", { 686 global: "current", 687 }); 688 `); 689 690 Assert.equal(window.eval(`ns2.getCounter();`), 0); 691 window.eval(`ns2.incCounter();`); 692 Assert.equal(window.eval(`ns2.getCounter();`), 1); 693 694 Services.tm.spinEventLoopUntil( 695 "Wait until dynamic import finishes", 696 () => window.eval(`ns !== null`) 697 ); 698 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); 703 704 Assert.equal(window.eval(`globalThis["loaded"].join(",")`), "2,1"); 705 }); 706 707 add_task(async function testSyncImportBeforeAsyncImportTLA() { 708 // Top-level-await is not supported by sync import. 709 710 const window = createChromeWindow(); 711 712 let caught = false; 713 714 try { 715 window.eval(` 716 ChromeUtils.importESModule("resource://test/es6module_top_level_await.js", { 717 global: "current", 718 }); 719 `); 720 } catch (e) { 721 caught = true; 722 Assert.stringMatches(e.message, /top level await is not supported/); 723 } 724 Assert.ok(caught); 725 726 window.eval(` 727 var ns2 = null; 728 const nsPromise = import("resource://test/es6module_top_level_await.js"); 729 nsPromise.then(v => { ns2 = v; }); 730 `); 731 732 Services.tm.spinEventLoopUntil( 733 "Wait until dynamic import finishes", 734 () => window.eval(`ns2 !== null`) 735 ); 736 737 Assert.equal(window.eval(`ns2.foo();`), 10); 738 }); 739 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. 743 744 const window = createChromeWindow(); 745 746 window.eval(` 747 var ns2 = null; 748 const nsPromise = import("resource://test/es6module_top_level_await.js"); 749 nsPromise.then(v => { ns2 = v; }); 750 `); 751 752 Services.tm.spinEventLoopUntil( 753 "Wait until dynamic import finishes", 754 () => window.eval(`ns2 !== null`) 755 ); 756 757 Assert.equal(window.eval(`ns2.foo();`), 10); 758 759 window.eval(` 760 var ns = ChromeUtils.importESModule("resource://test/es6module_top_level_await.js", { 761 global: "current", 762 }); 763 `); 764 765 Assert.equal(window.eval(`ns.foo();`), 10); 766 Assert.equal(window.eval(`ns2.foo == ns.foo;`), true); 767 }); 768 769 // TODO: Bug 1973663: Enable xpcshell test testSyncImportWhileAsyncImportTLA 770 /* 771 add_task(async function testSyncImportWhileAsyncImportTLA() { 772 // Top-level-await is not supported by sync import, but if the module is 773 // already fetching, ChromeUtils.importESModule waits for it and, the 774 // async-imported module namespace is returned. 775 776 const window = createChromeWindow(); 777 778 window.eval(` 779 var ns2 = null; 780 const nsPromise = import("resource://test/es6module_top_level_await.js"); 781 nsPromise.then(v => { ns2 = v; }); 782 `); 783 784 window.eval(` 785 var ns = ChromeUtils.importESModule("resource://test/es6module_top_level_await.js", { 786 global: "current", 787 }); 788 `); 789 790 Services.tm.spinEventLoopUntil( 791 "Wait until dynamic import finishes", 792 () => window.eval(`ns2 !== null`) 793 ); 794 795 Assert.equal(window.eval(`ns2.foo();`), 10); 796 Assert.equal(window.eval(`ns.foo();`), 10); 797 Assert.equal(window.eval(`ns2.foo == ns.foo;`), true); 798 }); 799 */