ModuleLoader.mjs (1889B)
1 /** 2 * Any copyright is dedicated to the Public Domain. 3 * http://creativecommons.org/publicdomain/zero/1.0/ 4 */ 5 6 // This file expectes the SpecialPowers to be available in the scope 7 // it is loaded into. 8 /* global SpecialPowers */ 9 10 export function ModuleLoader(base, depth, proto) { 11 const modules = {}; 12 13 const principal = SpecialPowers.wrap(document).nodePrincipal; 14 15 const sharedGlobalSandbox = SpecialPowers.Cu.Sandbox(principal, { 16 invisibleToDebugger: true, 17 sandboxName: "FS Module Loader", 18 sandboxPrototype: proto, 19 wantComponents: false, 20 wantGlobalProperties: [], 21 wantXrays: false, 22 }); 23 24 const require = async function (id) { 25 if (modules[id]) { 26 return modules[id].exported_symbols; 27 } 28 29 const url = new URL(depth + id, base); 30 31 const module = Object.create(null, { 32 exported_symbols: { 33 configurable: false, 34 enumerable: true, 35 value: Object.create(null), 36 writable: true, 37 }, 38 }); 39 40 modules[id] = module; 41 42 const properties = { 43 require_module: require, 44 exported_symbols: module.exported_symbols, 45 }; 46 47 // Create a new object in this sandbox, that will be used as the "scope" 48 // object for this particular module. 49 const pseudoSandbox = SpecialPowers.Cu.createObjectIn(sharedGlobalSandbox, { 50 defineAs: "tempGlobalScope", 51 }); 52 Object.assign(pseudoSandbox, properties); 53 54 const request = new XMLHttpRequest(); 55 request.open("GET", url, false); // `false` makes the request synchronous 56 request.send(null); 57 const code = request.responseText; 58 59 SpecialPowers.Cu.evalInSandbox( 60 `with (tempGlobalScope) { ${code} }`, 61 sharedGlobalSandbox 62 ); 63 64 return module.exported_symbols; 65 }; 66 67 const returnObj = { 68 require: { 69 enumerable: true, 70 value: require, 71 }, 72 }; 73 74 return Object.create(null, returnObj); 75 }