this repo has no description

Merge pull request #135 from gBasil/async-esm-entrypoints

Add async ESM support to browser entrypoint files

authored by notnite.com and committed by

GitHub c6a63da9 4076482d

+37 -13
+36 -12
packages/core/src/extension/loader.ts
··· 17 17 18 18 const logger = new Logger("core/extension/loader"); 19 19 20 - function loadExtWeb(ext: DetectedExtension) { 20 + function evalIIFE(id: string, source: string): ExtensionWebExports { 21 + const fn = new Function("require", "module", "exports", source); 22 + 23 + const module = { id, exports: {} }; 24 + fn.apply(window, [ 25 + () => { 26 + logger.warn("Attempted to require() from web"); 27 + }, 28 + module, 29 + module.exports 30 + ]); 31 + 32 + return module.exports; 33 + } 34 + 35 + async function evalEsm(source: string): Promise<ExtensionWebExports> { 36 + // Data URLs (`data:`) don't seem to work under the CSP, but object URLs do 37 + const url = URL.createObjectURL(new Blob([source], { type: "text/javascript" })); 38 + 39 + const module = await import(url); 40 + 41 + URL.revokeObjectURL(url); 42 + 43 + return module; 44 + } 45 + 46 + async function loadExtWeb(ext: DetectedExtension) { 21 47 if (ext.scripts.web != null) { 22 48 const source = ext.scripts.web + `\n//# sourceURL=${ext.id}/web.js`; 23 - const fn = new Function("require", "module", "exports", source); 24 49 25 - const module = { id: ext.id, exports: {} }; 26 - fn.apply(window, [ 27 - () => { 28 - logger.warn("Attempted to require() from web"); 29 - }, 30 - module, 31 - module.exports 32 - ]); 50 + let exports: ExtensionWebExports; 51 + 52 + try { 53 + exports = evalIIFE(ext.id, source); 54 + } catch { 55 + logger.trace(`Failed to load IIFE for extension ${ext.id}, trying ESM loading`); 56 + exports = await evalEsm(source); 57 + } 33 58 34 - const exports: ExtensionWebExports = module.exports; 35 59 if (exports.patches != null) { 36 60 let idx = 0; 37 61 for (const patch of exports.patches) { ··· 80 104 async function loadExt(ext: DetectedExtension) { 81 105 webTarget: { 82 106 try { 83 - loadExtWeb(ext); 107 + await loadExtWeb(ext); 84 108 } catch (e) { 85 109 logger.error(`Failed to load extension "${ext.id}"`, e); 86 110 }
+1 -1
tsconfig.json
··· 1 1 { 2 2 "compilerOptions": { 3 3 "target": "es2022", 4 - "module": "es6", 4 + "module": "es2020", 5 5 "esModuleInterop": true, 6 6 "forceConsistentCasingInFileNames": true, 7 7 "strict": true,