test_import_devtools_loader.js (5898B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 const { AppConstants } = ChromeUtils.importESModule( 5 "resource://gre/modules/AppConstants.sys.mjs" 6 ); 7 const { addDebuggerToGlobal } = ChromeUtils.importESModule( 8 "resource://gre/modules/jsdebugger.sys.mjs" 9 ); 10 addDebuggerToGlobal(this); 11 12 const ESM_URL = "resource://test/es6module_devtoolsLoader.sys.mjs"; 13 14 // Toggle the following pref to enable Cu.getModuleImportStack() 15 if (AppConstants.NIGHTLY_BUILD) { 16 Services.prefs.setBoolPref("browser.startup.record", true); 17 registerCleanupFunction(() => { 18 Services.prefs.clearUserPref("browser.startup.record"); 19 }); 20 } 21 22 add_task(async function testDevToolsModuleLoader() { 23 const dbg = new Debugger(); 24 25 const sharedGlobal = Cu.getGlobalForObject(Services); 26 const sharedPrincipal = Cu.getObjectPrincipal(sharedGlobal); 27 28 info("Test importing in the regular shared loader"); 29 const ns = ChromeUtils.importESModule(ESM_URL); 30 Assert.equal(ns.x, 0); 31 ns.increment(); 32 Assert.equal(ns.x, 1); 33 const nsGlobal = Cu.getGlobalForObject(ns); 34 const nsPrincipal = Cu.getObjectPrincipal(nsGlobal); 35 Assert.equal(nsGlobal, sharedGlobal, "Without any parameter, importESModule load in the shared system global"); 36 Assert.equal(nsPrincipal, sharedPrincipal); 37 Assert.ok(nsPrincipal.isSystemPrincipal); 38 info("Global of ESM loaded in the shared loader can be inspected by the Debugger"); 39 dbg.addDebuggee(nsGlobal); 40 Assert.ok(true, "The global is accepted by the Debugger API"); 41 42 const ns1 = ChromeUtils.importESModule(ESM_URL, { global: "shared" }); 43 Assert.equal(ns1, ns, "Passing global: 'shared' from the shared system global is equivalent to regular importESModule"); 44 45 info("Test importing in the devtools loader"); 46 const ns2 = ChromeUtils.importESModule(ESM_URL, { global: "devtools" }); 47 Assert.equal(ns2.x, 0, "We get a new module instance with a new incremented number"); 48 Assert.notEqual(ns2, ns, "We imported a new instance of the module"); 49 Assert.notEqual(ns2.importedObject, ns.importedObject, "The two module instances expose distinct objects"); 50 Assert.equal(ns2.importESModuleDevTools, ns2.importedObject, "When using global: 'devtools' from a devtools global, we keep loading in the same loader"); 51 Assert.equal(ns2.importESModuleCurrent, ns2.importedObject, "When using global: 'current' from a devtools global, we keep loading in the same loader"); 52 Assert.equal(ns2.importESModuleContextual, ns2.importedObject, "When using global: 'contextual' from a devtools global, we keep loading in the same loader"); 53 Assert.ok(ns2.importESModuleNoOptionFailed1, "global option is required in DevTools global"); 54 Assert.ok(ns2.importESModuleNoOptionFailed2, "global option is required in DevTools global"); 55 Assert.equal(ns2.importESModuleShared, ns.importedObject, "When passing global: 'shared', we load in the shared global, even from a devtools global"); 56 57 Assert.equal(ns2.importLazyDevTools(), ns2.importedObject, "When using global: 'devtools' from a devtools global, we keep loading in the same loader"); 58 Assert.equal(ns2.importLazyCurrent(), ns2.importedObject, "When using global: 'current' from a devtools global, we keep loading in the same loader"); 59 Assert.equal(ns2.importLazyContextual(), ns2.importedObject, "When using global: 'contextual' from a devtools global, we keep loading in the same loader"); 60 Assert.ok(ns2.importLazyNoOptionFailed1, "global option is required in DevTools global"); 61 Assert.ok(ns2.importLazyNoOptionFailed2, "global option is required in DevTools global"); 62 Assert.equal(ns2.importLazyShared(), ns.importedObject, "When passing global: 'shared', we load in the shared global, even from a devtools global"); 63 64 info("When using the devtools loader, we load in a distinct global, but the same compartment"); 65 const ns2Global = Cu.getGlobalForObject(ns2); 66 const ns2Principal = Cu.getObjectPrincipal(ns2Global); 67 Assert.notEqual(ns2Global, sharedGlobal, "The module is loaded in a distinct global"); 68 Assert.equal(ns2Principal, sharedPrincipal, "The principal is still the shared system principal"); 69 Assert.equal(Cu.getGlobalForObject(ns2.importedObject), ns2Global, "Nested dependencies are also loaded in the same devtools global"); 70 Assert.throws(() => dbg.addDebuggee(ns2Global), /TypeError: passing non-debuggable global to addDebuggee/, 71 "Global os ESM loaded in the devtools loader can't be inspected by the Debugee"); 72 73 info("Re-import the same module in the devtools loader"); 74 const ns3 = ChromeUtils.importESModule(ESM_URL, { global: "devtools" }); 75 Assert.equal(ns3, ns2, "We import the exact same module"); 76 Assert.equal(ns3.importedObject, ns2.importedObject, "The two module expose the same objects"); 77 78 info("Import a module only from the devtools loader"); 79 const ns4 = ChromeUtils.importESModule("resource://test/es6module_devtoolsLoader_only.js", { global: "devtools" }); 80 const ns4Global = Cu.getGlobalForObject(ns4); 81 Assert.equal(ns4Global, ns2Global, "The module is loaded in the same devtools global"); 82 83 // getModuleImportStack only works on nightly builds 84 if (AppConstants.NIGHTLY_BUILD) { 85 info("Assert the behavior of getModuleImportStack on modules loaded in the devtools loader"); 86 Assert.ok(Cu.getModuleImportStack(ESM_URL).includes("testDevToolsModuleLoader")); 87 Assert.ok(Cu.getModuleImportStack("resource://test/es6module_devtoolsLoader.js").includes("testDevToolsModuleLoader")); 88 Assert.ok(Cu.getModuleImportStack("resource://test/es6module_devtoolsLoader.js").includes(ESM_URL)); 89 // Previous import stack were for module loaded via the shared loader. 90 // Let's also assert that we get stack traces for modules loaded via the devtools loader. 91 Assert.ok(Cu.getModuleImportStack("resource://test/es6module_devtoolsLoader_only.js").includes("testDevToolsModuleLoader")); 92 } 93 });