es-module-shims 1.5.5 → 1.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -2
- package/dist/es-module-shims.js +96 -69
- package/dist/es-module-shims.wasm.js +106 -71
- package/index.d.ts +24 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ Because we are still using the native module loader the edge cases work out comp
|
|
|
29
29
|
Include ES Module Shims with a `async` attribute on the script, then include an import map and module scripts normally:
|
|
30
30
|
|
|
31
31
|
```html
|
|
32
|
-
<script async src="https://ga.jspm.io/npm:es-module-shims@1.5.
|
|
32
|
+
<script async src="https://ga.jspm.io/npm:es-module-shims@1.5.8/dist/es-module-shims.js"></script>
|
|
33
33
|
|
|
34
34
|
<!-- https://generator.jspm.io/#U2NhYGBkDM0rySzJSU1hKEpNTC5xMLTQM9Az0C1K1jMAAKFS5w0gAA -->
|
|
35
35
|
<script type="importmap">
|
|
@@ -292,11 +292,22 @@ While in polyfill mode the same restrictions apply that multiple import maps, im
|
|
|
292
292
|
To make it easy to keep track of import map state, es-module-shims provides a `importShim.getImportMap` utility function, available only in shim mode.
|
|
293
293
|
|
|
294
294
|
```js
|
|
295
|
-
const importMap = importShim.getImportMap()
|
|
295
|
+
const importMap = importShim.getImportMap();
|
|
296
296
|
|
|
297
297
|
// importMap will be an object in the same shape as the json in a importmap script
|
|
298
298
|
```
|
|
299
299
|
|
|
300
|
+
#### Setting current import map state
|
|
301
|
+
To make it easy to set the import map state, es-module-shims provides a `importShim.addImportMap` utility function, available only in shim mode.
|
|
302
|
+
|
|
303
|
+
```js
|
|
304
|
+
// importMap will be an object in the same shape as the json in a importmap script
|
|
305
|
+
const importMap = { imports: {/*...*/}, scopes: {/*...*/} };
|
|
306
|
+
|
|
307
|
+
importShim.addImportMap(importMap);
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
|
|
300
311
|
### Dynamic Import
|
|
301
312
|
|
|
302
313
|
> Stability: Stable browser standard
|
|
@@ -423,6 +434,34 @@ var resolvedUrl = import.meta.resolve('dep', 'https://site.com/another/scope');
|
|
|
423
434
|
|
|
424
435
|
Node.js also implements a similar API, although it's in the process of shifting to a synchronous resolver.
|
|
425
436
|
|
|
437
|
+
### Module Workers
|
|
438
|
+
ES Module Shims can be used in module workers in browsers that provide dynamic import in worker environments, which at the moment are Chrome(80+), Edge(80+), Safari(15+).
|
|
439
|
+
|
|
440
|
+
An example of ES Module Shims usage in web workers is provided below:
|
|
441
|
+
```js
|
|
442
|
+
/**
|
|
443
|
+
*
|
|
444
|
+
* @param {string} aURL a string representing the URL of the module script the worker will execute.
|
|
445
|
+
* @returns {string} The string representing the URL of the script the worker will execute.
|
|
446
|
+
*/
|
|
447
|
+
function getWorkerScriptURL(aURL) {
|
|
448
|
+
// baseURL, esModuleShimsURL are considered to be known in advance
|
|
449
|
+
// esModuleShimsURL - must point to the non-CSP build of ES Module Shims,
|
|
450
|
+
// namely the `es-module-shim.wasm.js` output: es-module-shims/dist/es-module-shims.wasm.js
|
|
451
|
+
|
|
452
|
+
return URL.createObjectURL(new Blob(
|
|
453
|
+
[
|
|
454
|
+
`importScripts('${new URL(esModuleShimsURL, baseURL).href}');
|
|
455
|
+
importShim.addImportMap(${JSON.stringify(importShim.getImportMap())});
|
|
456
|
+
importShim('${new URL(aURL, baseURL).href}').catch(e => setTimeout(() => { throw e; }))`
|
|
457
|
+
],
|
|
458
|
+
{ type: 'application/javascript' }))
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
const worker = new Worker(getWorkerScriptURL('myEsModule.js'));
|
|
462
|
+
```
|
|
463
|
+
> For now, in web workers must be used the non-CSP build of ES Module Shims, namely the `es-module-shim.wasm.js` output: es-module-shims/dist/es-module-shims.wasm.js.
|
|
464
|
+
|
|
426
465
|
## Init Options
|
|
427
466
|
|
|
428
467
|
Provide a `esmsInitOptions` on the global scope before `es-module-shims` is loaded to configure various aspects of the module loading process:
|
package/dist/es-module-shims.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
/* ES Module Shims 1.5.
|
|
1
|
+
/* ES Module Shims 1.5.8 */
|
|
2
2
|
(function () {
|
|
3
3
|
|
|
4
|
+
const hasWindow = typeof window !== 'undefined';
|
|
5
|
+
const hasDocument = typeof document !== 'undefined';
|
|
6
|
+
|
|
4
7
|
const noop = () => {};
|
|
5
8
|
|
|
6
|
-
const optionsScript = document.querySelector('script[type=esms-options]');
|
|
9
|
+
const optionsScript = hasDocument ? document.querySelector('script[type=esms-options]') : undefined;
|
|
7
10
|
|
|
8
11
|
const esmsInitOptions = optionsScript ? JSON.parse(optionsScript.innerHTML) : {};
|
|
9
12
|
Object.assign(esmsInitOptions, self.esmsInitOptions || {});
|
|
10
13
|
|
|
11
|
-
let shimMode = !!esmsInitOptions.shimMode;
|
|
14
|
+
let shimMode = hasDocument ? !!esmsInitOptions.shimMode : true;
|
|
12
15
|
|
|
13
16
|
const importHook = globalHook(shimMode && esmsInitOptions.onimport);
|
|
14
17
|
const resolveHook = globalHook(shimMode && esmsInitOptions.resolve);
|
|
@@ -17,11 +20,10 @@
|
|
|
17
20
|
|
|
18
21
|
const skip = esmsInitOptions.skip ? new RegExp(esmsInitOptions.skip) : null;
|
|
19
22
|
|
|
20
|
-
let nonce = esmsInitOptions.nonce;
|
|
21
|
-
|
|
22
23
|
const mapOverrides = esmsInitOptions.mapOverrides;
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
let nonce = esmsInitOptions.nonce;
|
|
26
|
+
if (!nonce && hasDocument) {
|
|
25
27
|
const nonceElement = document.querySelector('script[nonce]');
|
|
26
28
|
if (nonceElement)
|
|
27
29
|
nonce = nonceElement.nonce || nonceElement.getAttribute('nonce');
|
|
@@ -48,7 +50,11 @@
|
|
|
48
50
|
|
|
49
51
|
const edge = !navigator.userAgentData && !!navigator.userAgent.match(/Edge\/\d+\.\d+/);
|
|
50
52
|
|
|
51
|
-
const baseUrl =
|
|
53
|
+
const baseUrl = hasDocument
|
|
54
|
+
? document.baseURI
|
|
55
|
+
: `${location.protocol}//${location.host}${location.pathname.includes('/')
|
|
56
|
+
? location.pathname.slice(0, location.pathname.lastIndexOf('/') + 1)
|
|
57
|
+
: location.pathname}`;
|
|
52
58
|
|
|
53
59
|
function createBlob (source, type = 'text/javascript') {
|
|
54
60
|
return URL.createObjectURL(new Blob([source], { type }));
|
|
@@ -56,7 +62,7 @@
|
|
|
56
62
|
|
|
57
63
|
const eoop = err => setTimeout(() => { throw err });
|
|
58
64
|
|
|
59
|
-
const throwError = err => { (
|
|
65
|
+
const throwError = err => { (self.reportError || hasWindow && window.safari && console.error || eoop)(err), void onerror(err); };
|
|
60
66
|
|
|
61
67
|
function fromParent (parent) {
|
|
62
68
|
return parent ? ` imported from ${parent}` : '';
|
|
@@ -273,33 +279,43 @@
|
|
|
273
279
|
let supportsJsonAssertions = false;
|
|
274
280
|
let supportsCssAssertions = false;
|
|
275
281
|
|
|
276
|
-
let
|
|
277
|
-
let
|
|
278
|
-
|
|
282
|
+
let supportsImportMaps = hasDocument && HTMLScriptElement.supports ? HTMLScriptElement.supports('importmap') : false;
|
|
283
|
+
let supportsImportMeta = supportsImportMaps;
|
|
279
284
|
let supportsDynamicImport = false;
|
|
280
285
|
|
|
281
|
-
const featureDetectionPromise = Promise.resolve(supportsDynamicImportCheck).then(_supportsDynamicImport => {
|
|
286
|
+
const featureDetectionPromise = Promise.resolve(supportsImportMaps || supportsDynamicImportCheck).then(_supportsDynamicImport => {
|
|
282
287
|
if (!_supportsDynamicImport)
|
|
283
288
|
return;
|
|
284
289
|
supportsDynamicImport = true;
|
|
285
290
|
|
|
286
291
|
return Promise.all([
|
|
287
|
-
dynamicImport(createBlob('import.meta')).then(() => supportsImportMeta = true, noop),
|
|
288
|
-
cssModulesEnabled && dynamicImport(createBlob(
|
|
289
|
-
jsonModulesEnabled && dynamicImport(createBlob(
|
|
290
|
-
|
|
291
|
-
self._$s = v => {
|
|
292
|
-
document.head.removeChild(iframe);
|
|
293
|
-
if (v) supportsImportMaps = true;
|
|
294
|
-
delete self._$s;
|
|
295
|
-
resolve();
|
|
296
|
-
};
|
|
292
|
+
supportsImportMaps || dynamicImport(createBlob('import.meta')).then(() => supportsImportMeta = true, noop),
|
|
293
|
+
cssModulesEnabled && dynamicImport(createBlob(`import"${createBlob('', 'text/css')}"assert{type:"css"}`)).then(() => supportsCssAssertions = true, noop),
|
|
294
|
+
jsonModulesEnabled && dynamicImport(createBlob(`import"${createBlob('{}', 'text/json')}"assert{type:"json"}`)).then(() => supportsJsonAssertions = true, noop),
|
|
295
|
+
supportsImportMaps || hasDocument && (HTMLScriptElement.supports || new Promise(resolve => {
|
|
297
296
|
const iframe = document.createElement('iframe');
|
|
298
297
|
iframe.style.display = 'none';
|
|
299
298
|
iframe.setAttribute('nonce', nonce);
|
|
300
|
-
|
|
299
|
+
// setting src to a blob URL results in a navigation event in webviews
|
|
300
|
+
// setting srcdoc is not supported in React native webviews on iOS
|
|
301
|
+
// therefore, we need to first feature detect srcdoc support
|
|
302
|
+
iframe.srcdoc = `<!doctype html><script nonce="${nonce}"><${''}/script>`;
|
|
301
303
|
document.head.appendChild(iframe);
|
|
302
|
-
|
|
304
|
+
iframe.onload = () => {
|
|
305
|
+
self._$s = v => {
|
|
306
|
+
document.head.removeChild(iframe);
|
|
307
|
+
supportsImportMaps = v;
|
|
308
|
+
delete self._$s;
|
|
309
|
+
resolve();
|
|
310
|
+
};
|
|
311
|
+
const supportsSrcDoc = iframe.contentDocument.head.childNodes.length > 0;
|
|
312
|
+
const importMapTest = `<!doctype html><script type=importmap nonce="${nonce}">{"imports":{"x":"${createBlob('')}"}<${''}/script><script nonce="${nonce}">import('x').catch(() => {}).then(v=>parent._$s(!!v))<${''}/script>`;
|
|
313
|
+
if (supportsSrcDoc)
|
|
314
|
+
iframe.srcdoc = importMapTest;
|
|
315
|
+
else
|
|
316
|
+
iframe.contentDocument.write(importMapTest);
|
|
317
|
+
};
|
|
318
|
+
}))
|
|
303
319
|
]);
|
|
304
320
|
});
|
|
305
321
|
|
|
@@ -336,7 +352,9 @@
|
|
|
336
352
|
await initPromise;
|
|
337
353
|
if (importHook) await importHook(id, typeof args[1] !== 'string' ? args[1] : {}, parentUrl);
|
|
338
354
|
if (acceptingImportMaps || shimMode || !baselinePassthrough) {
|
|
339
|
-
|
|
355
|
+
if (hasDocument)
|
|
356
|
+
processImportMaps();
|
|
357
|
+
|
|
340
358
|
if (!shimMode)
|
|
341
359
|
acceptingImportMaps = false;
|
|
342
360
|
}
|
|
@@ -366,6 +384,10 @@
|
|
|
366
384
|
|
|
367
385
|
importShim.resolve = resolveSync;
|
|
368
386
|
importShim.getImportMap = () => JSON.parse(JSON.stringify(importMap));
|
|
387
|
+
importShim.addImportMap = importMapIn => {
|
|
388
|
+
if (!shimMode) throw new Error('Unsupported in polyfill mode.');
|
|
389
|
+
importMap = resolveAndComposeImportMap(importMapIn, baseUrl, importMap);
|
|
390
|
+
};
|
|
369
391
|
|
|
370
392
|
const registry = importShim._r = {};
|
|
371
393
|
|
|
@@ -404,44 +426,47 @@
|
|
|
404
426
|
}
|
|
405
427
|
}
|
|
406
428
|
baselinePassthrough = esmsInitOptions.polyfillEnable !== true && supportsDynamicImport && supportsImportMeta && supportsImportMaps && (!jsonModulesEnabled || supportsJsonAssertions) && (!cssModulesEnabled || supportsCssAssertions) && !importMapSrcOrLazy && !false;
|
|
407
|
-
if (
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
for (const
|
|
416
|
-
if (
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
429
|
+
if (hasDocument) {
|
|
430
|
+
if (!supportsImportMaps) {
|
|
431
|
+
const supports = HTMLScriptElement.supports || (type => type === 'classic' || type === 'module');
|
|
432
|
+
HTMLScriptElement.supports = type => type === 'importmap' || supports(type);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
if (shimMode || !baselinePassthrough) {
|
|
436
|
+
new MutationObserver(mutations => {
|
|
437
|
+
for (const mutation of mutations) {
|
|
438
|
+
if (mutation.type !== 'childList') continue;
|
|
439
|
+
for (const node of mutation.addedNodes) {
|
|
440
|
+
if (node.tagName === 'SCRIPT') {
|
|
441
|
+
if (node.type === (shimMode ? 'module-shim' : 'module'))
|
|
442
|
+
processScript(node);
|
|
443
|
+
if (node.type === (shimMode ? 'importmap-shim' : 'importmap'))
|
|
444
|
+
processImportMap(node);
|
|
445
|
+
}
|
|
446
|
+
else if (node.tagName === 'LINK' && node.rel === (shimMode ? 'modulepreload-shim' : 'modulepreload'))
|
|
447
|
+
processPreload(node);
|
|
421
448
|
}
|
|
422
|
-
else if (node.tagName === 'LINK' && node.rel === (shimMode ? 'modulepreload-shim' : 'modulepreload'))
|
|
423
|
-
processPreload(node);
|
|
424
449
|
}
|
|
450
|
+
}).observe(document, {childList: true, subtree: true});
|
|
451
|
+
processImportMaps();
|
|
452
|
+
processScriptsAndPreloads();
|
|
453
|
+
if (document.readyState === 'complete') {
|
|
454
|
+
readyStateCompleteCheck();
|
|
425
455
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
await initPromise;
|
|
435
|
-
processImportMaps();
|
|
436
|
-
if (document.readyState === 'complete') {
|
|
437
|
-
readyStateCompleteCheck();
|
|
438
|
-
document.removeEventListener('readystatechange', readyListener);
|
|
456
|
+
else {
|
|
457
|
+
async function readyListener() {
|
|
458
|
+
await initPromise;
|
|
459
|
+
processImportMaps();
|
|
460
|
+
if (document.readyState === 'complete') {
|
|
461
|
+
readyStateCompleteCheck();
|
|
462
|
+
document.removeEventListener('readystatechange', readyListener);
|
|
463
|
+
}
|
|
439
464
|
}
|
|
465
|
+
document.addEventListener('readystatechange', readyListener);
|
|
440
466
|
}
|
|
441
|
-
document.addEventListener('readystatechange', readyListener);
|
|
442
467
|
}
|
|
443
|
-
return undefined;
|
|
444
468
|
}
|
|
469
|
+
return undefined;
|
|
445
470
|
});
|
|
446
471
|
let importMapPromise = initPromise;
|
|
447
472
|
let firstPolyfillLoad = true;
|
|
@@ -521,7 +546,7 @@
|
|
|
521
546
|
const source = load.S;
|
|
522
547
|
|
|
523
548
|
// edge doesnt execute sibling in order, so we fix this up by ensuring all previous executions are explicit dependencies
|
|
524
|
-
let resolvedSource = edge && lastLoad ? `import '${lastLoad}';` : '';
|
|
549
|
+
let resolvedSource = edge && lastLoad ? `import '${lastLoad}';` : '';
|
|
525
550
|
|
|
526
551
|
if (!imports.length) {
|
|
527
552
|
resolvedSource += source;
|
|
@@ -562,7 +587,7 @@
|
|
|
562
587
|
resolvedSource += `/*${source.slice(start - 1, statementEnd)}*/${urlJsString(blobUrl)}`;
|
|
563
588
|
|
|
564
589
|
// circular shell execution
|
|
565
|
-
if (!cycleShell && depLoad.s) {
|
|
590
|
+
if (!cycleShell && depLoad.s) {
|
|
566
591
|
resolvedSource += `;import*as m$_${depIndex} from'${depLoad.b}';import{u$_ as u$_${depIndex}}from'${depLoad.s}';u$_${depIndex}(m$_${depIndex})`;
|
|
567
592
|
depLoad.s = undefined;
|
|
568
593
|
}
|
|
@@ -649,8 +674,8 @@
|
|
|
649
674
|
return { r: res.url, s: `export default ${await res.text()}`, t: 'json' };
|
|
650
675
|
else if (cssContentType.test(contentType)) {
|
|
651
676
|
return { r: res.url, s: `var s=new CSSStyleSheet();s.replaceSync(${
|
|
652
|
-
|
|
653
|
-
|
|
677
|
+
JSON.stringify((await res.text()).replace(cssUrlRegEx, (_match, quotes = '', relUrl1, relUrl2) => `url(${quotes}${resolveUrl(relUrl1 || relUrl2, url)}${quotes})`))
|
|
678
|
+
});export default s;`, t: 'css' };
|
|
654
679
|
}
|
|
655
680
|
else
|
|
656
681
|
throw Error(`Unsupported Content-Type "${contentType}" loading ${url}${fromParent(parent)}. Modules must be served with a valid MIME type like application/javascript.`);
|
|
@@ -720,7 +745,7 @@
|
|
|
720
745
|
load.L = load.f.then(async () => {
|
|
721
746
|
let childFetchOpts = fetchOpts;
|
|
722
747
|
load.d = (await Promise.all(load.a[0].map(async ({ n, d }) => {
|
|
723
|
-
if (d >= 0 && !supportsDynamicImport || d === 2 && !supportsImportMeta)
|
|
748
|
+
if (d >= 0 && !supportsDynamicImport || d === -2 && !supportsImportMeta)
|
|
724
749
|
load.n = true;
|
|
725
750
|
if (d !== -1 || !n) return;
|
|
726
751
|
const { r, b } = await resolve(n, load.r || load.u);
|
|
@@ -771,14 +796,16 @@
|
|
|
771
796
|
document.dispatchEvent(new Event('DOMContentLoaded'));
|
|
772
797
|
}
|
|
773
798
|
// this should always trigger because we assume es-module-shims is itself a domcontentloaded requirement
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
799
|
+
if (hasDocument) {
|
|
800
|
+
document.addEventListener('DOMContentLoaded', async () => {
|
|
801
|
+
await initPromise;
|
|
802
|
+
domContentLoadedCheck();
|
|
803
|
+
if (shimMode || !baselinePassthrough) {
|
|
804
|
+
processImportMaps();
|
|
805
|
+
processScriptsAndPreloads();
|
|
806
|
+
}
|
|
807
|
+
});
|
|
808
|
+
}
|
|
782
809
|
|
|
783
810
|
let readyStateCompleteCnt = 1;
|
|
784
811
|
function readyStateCompleteCheck () {
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
/* ES Module Shims Wasm 1.5.
|
|
1
|
+
/* ES Module Shims Wasm 1.5.8 */
|
|
2
2
|
(function () {
|
|
3
3
|
|
|
4
|
+
const hasWindow = typeof window !== 'undefined';
|
|
5
|
+
const hasDocument = typeof document !== 'undefined';
|
|
6
|
+
|
|
4
7
|
const noop = () => {};
|
|
5
8
|
|
|
6
|
-
const optionsScript = document.querySelector('script[type=esms-options]');
|
|
9
|
+
const optionsScript = hasDocument ? document.querySelector('script[type=esms-options]') : undefined;
|
|
7
10
|
|
|
8
11
|
const esmsInitOptions = optionsScript ? JSON.parse(optionsScript.innerHTML) : {};
|
|
9
12
|
Object.assign(esmsInitOptions, self.esmsInitOptions || {});
|
|
10
13
|
|
|
11
|
-
let shimMode = !!esmsInitOptions.shimMode;
|
|
14
|
+
let shimMode = hasDocument ? !!esmsInitOptions.shimMode : true;
|
|
12
15
|
|
|
13
16
|
const importHook = globalHook(shimMode && esmsInitOptions.onimport);
|
|
14
17
|
const resolveHook = globalHook(shimMode && esmsInitOptions.resolve);
|
|
@@ -17,11 +20,10 @@
|
|
|
17
20
|
|
|
18
21
|
const skip = esmsInitOptions.skip ? new RegExp(esmsInitOptions.skip) : null;
|
|
19
22
|
|
|
20
|
-
let nonce = esmsInitOptions.nonce;
|
|
21
|
-
|
|
22
23
|
const mapOverrides = esmsInitOptions.mapOverrides;
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
let nonce = esmsInitOptions.nonce;
|
|
26
|
+
if (!nonce && hasDocument) {
|
|
25
27
|
const nonceElement = document.querySelector('script[nonce]');
|
|
26
28
|
if (nonceElement)
|
|
27
29
|
nonce = nonceElement.nonce || nonceElement.getAttribute('nonce');
|
|
@@ -48,7 +50,11 @@
|
|
|
48
50
|
|
|
49
51
|
const edge = !navigator.userAgentData && !!navigator.userAgent.match(/Edge\/\d+\.\d+/);
|
|
50
52
|
|
|
51
|
-
const baseUrl =
|
|
53
|
+
const baseUrl = hasDocument
|
|
54
|
+
? document.baseURI
|
|
55
|
+
: `${location.protocol}//${location.host}${location.pathname.includes('/')
|
|
56
|
+
? location.pathname.slice(0, location.pathname.lastIndexOf('/') + 1)
|
|
57
|
+
: location.pathname}`;
|
|
52
58
|
|
|
53
59
|
function createBlob (source, type = 'text/javascript') {
|
|
54
60
|
return URL.createObjectURL(new Blob([source], { type }));
|
|
@@ -56,7 +62,7 @@
|
|
|
56
62
|
|
|
57
63
|
const eoop = err => setTimeout(() => { throw err });
|
|
58
64
|
|
|
59
|
-
const throwError = err => { (
|
|
65
|
+
const throwError = err => { (self.reportError || hasWindow && window.safari && console.error || eoop)(err), void onerror(err); };
|
|
60
66
|
|
|
61
67
|
function fromParent (parent) {
|
|
62
68
|
return parent ? ` imported from ${parent}` : '';
|
|
@@ -234,6 +240,15 @@
|
|
|
234
240
|
|
|
235
241
|
let supportsDynamicImportCheck = false;
|
|
236
242
|
|
|
243
|
+
// first check basic eval support
|
|
244
|
+
try {
|
|
245
|
+
eval('');
|
|
246
|
+
}
|
|
247
|
+
catch (e) {
|
|
248
|
+
throw new Error(`The ES Module Shims Wasm build will not work without eval support. Either use the alternative CSP-compatible build or make sure to add both the "unsafe-eval" and "unsafe-wasm-eval" CSP policies.`);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// polyfill dynamic import if not supported
|
|
237
252
|
let dynamicImport;
|
|
238
253
|
try {
|
|
239
254
|
dynamicImport = (0, eval)('u=>import(u)');
|
|
@@ -241,7 +256,7 @@
|
|
|
241
256
|
}
|
|
242
257
|
catch (e) {}
|
|
243
258
|
|
|
244
|
-
if (!supportsDynamicImportCheck) {
|
|
259
|
+
if (hasDocument && !supportsDynamicImportCheck) {
|
|
245
260
|
let err;
|
|
246
261
|
window.addEventListener('error', _err => err = _err);
|
|
247
262
|
dynamicImport = (url, { errUrl = url }) => {
|
|
@@ -249,7 +264,6 @@
|
|
|
249
264
|
const src = createBlob(`import*as m from'${url}';self._esmsi=m;`);
|
|
250
265
|
const s = Object.assign(document.createElement('script'), { type: 'module', src });
|
|
251
266
|
s.setAttribute('noshim', '');
|
|
252
|
-
s.setAttribute('nonce', nonce);
|
|
253
267
|
document.head.appendChild(s);
|
|
254
268
|
return new Promise((resolve, reject) => {
|
|
255
269
|
s.addEventListener('load', () => {
|
|
@@ -271,33 +285,43 @@
|
|
|
271
285
|
let supportsJsonAssertions = false;
|
|
272
286
|
let supportsCssAssertions = false;
|
|
273
287
|
|
|
274
|
-
let
|
|
275
|
-
let
|
|
276
|
-
|
|
288
|
+
let supportsImportMaps = hasDocument && HTMLScriptElement.supports ? HTMLScriptElement.supports('importmap') : false;
|
|
289
|
+
let supportsImportMeta = supportsImportMaps;
|
|
277
290
|
let supportsDynamicImport = false;
|
|
278
291
|
|
|
279
|
-
const featureDetectionPromise = Promise.resolve(supportsDynamicImportCheck).then(_supportsDynamicImport => {
|
|
292
|
+
const featureDetectionPromise = Promise.resolve(supportsImportMaps || supportsDynamicImportCheck).then(_supportsDynamicImport => {
|
|
280
293
|
if (!_supportsDynamicImport)
|
|
281
294
|
return;
|
|
282
295
|
supportsDynamicImport = true;
|
|
283
296
|
|
|
284
297
|
return Promise.all([
|
|
285
|
-
dynamicImport(createBlob('import.meta')).then(() => supportsImportMeta = true, noop),
|
|
286
|
-
cssModulesEnabled && dynamicImport(createBlob(
|
|
287
|
-
jsonModulesEnabled && dynamicImport(createBlob(
|
|
288
|
-
|
|
289
|
-
self._$s = v => {
|
|
290
|
-
document.head.removeChild(iframe);
|
|
291
|
-
if (v) supportsImportMaps = true;
|
|
292
|
-
delete self._$s;
|
|
293
|
-
resolve();
|
|
294
|
-
};
|
|
298
|
+
supportsImportMaps || dynamicImport(createBlob('import.meta')).then(() => supportsImportMeta = true, noop),
|
|
299
|
+
cssModulesEnabled && dynamicImport(createBlob(`import"${createBlob('', 'text/css')}"assert{type:"css"}`)).then(() => supportsCssAssertions = true, noop),
|
|
300
|
+
jsonModulesEnabled && dynamicImport(createBlob(`import"${createBlob('{}', 'text/json')}"assert{type:"json"}`)).then(() => supportsJsonAssertions = true, noop),
|
|
301
|
+
supportsImportMaps || hasDocument && (HTMLScriptElement.supports || new Promise(resolve => {
|
|
295
302
|
const iframe = document.createElement('iframe');
|
|
296
303
|
iframe.style.display = 'none';
|
|
297
304
|
iframe.setAttribute('nonce', nonce);
|
|
298
|
-
|
|
305
|
+
// setting src to a blob URL results in a navigation event in webviews
|
|
306
|
+
// setting srcdoc is not supported in React native webviews on iOS
|
|
307
|
+
// therefore, we need to first feature detect srcdoc support
|
|
308
|
+
iframe.srcdoc = `<!doctype html><script nonce="${nonce}"><${''}/script>`;
|
|
299
309
|
document.head.appendChild(iframe);
|
|
300
|
-
|
|
310
|
+
iframe.onload = () => {
|
|
311
|
+
self._$s = v => {
|
|
312
|
+
document.head.removeChild(iframe);
|
|
313
|
+
supportsImportMaps = v;
|
|
314
|
+
delete self._$s;
|
|
315
|
+
resolve();
|
|
316
|
+
};
|
|
317
|
+
const supportsSrcDoc = iframe.contentDocument.head.childNodes.length > 0;
|
|
318
|
+
const importMapTest = `<!doctype html><script type=importmap nonce="${nonce}">{"imports":{"x":"${createBlob('')}"}<${''}/script><script nonce="${nonce}">import('x').catch(() => {}).then(v=>parent._$s(!!v))<${''}/script>`;
|
|
319
|
+
if (supportsSrcDoc)
|
|
320
|
+
iframe.srcdoc = importMapTest;
|
|
321
|
+
else
|
|
322
|
+
iframe.contentDocument.write(importMapTest);
|
|
323
|
+
};
|
|
324
|
+
}))
|
|
301
325
|
]);
|
|
302
326
|
});
|
|
303
327
|
|
|
@@ -334,7 +358,9 @@
|
|
|
334
358
|
await initPromise;
|
|
335
359
|
if (importHook) await importHook(id, typeof args[1] !== 'string' ? args[1] : {}, parentUrl);
|
|
336
360
|
if (acceptingImportMaps || shimMode || !baselinePassthrough) {
|
|
337
|
-
|
|
361
|
+
if (hasDocument)
|
|
362
|
+
processImportMaps();
|
|
363
|
+
|
|
338
364
|
if (!shimMode)
|
|
339
365
|
acceptingImportMaps = false;
|
|
340
366
|
}
|
|
@@ -364,6 +390,10 @@
|
|
|
364
390
|
|
|
365
391
|
importShim.resolve = resolveSync;
|
|
366
392
|
importShim.getImportMap = () => JSON.parse(JSON.stringify(importMap));
|
|
393
|
+
importShim.addImportMap = importMapIn => {
|
|
394
|
+
if (!shimMode) throw new Error('Unsupported in polyfill mode.');
|
|
395
|
+
importMap = resolveAndComposeImportMap(importMapIn, baseUrl, importMap);
|
|
396
|
+
};
|
|
367
397
|
|
|
368
398
|
const registry = importShim._r = {};
|
|
369
399
|
|
|
@@ -402,44 +432,47 @@
|
|
|
402
432
|
}
|
|
403
433
|
}
|
|
404
434
|
baselinePassthrough = esmsInitOptions.polyfillEnable !== true && supportsDynamicImport && supportsImportMeta && supportsImportMaps && (!jsonModulesEnabled || supportsJsonAssertions) && (!cssModulesEnabled || supportsCssAssertions) && !importMapSrcOrLazy && !false;
|
|
405
|
-
if (
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
for (const
|
|
414
|
-
if (
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
435
|
+
if (hasDocument) {
|
|
436
|
+
if (!supportsImportMaps) {
|
|
437
|
+
const supports = HTMLScriptElement.supports || (type => type === 'classic' || type === 'module');
|
|
438
|
+
HTMLScriptElement.supports = type => type === 'importmap' || supports(type);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
if (shimMode || !baselinePassthrough) {
|
|
442
|
+
new MutationObserver(mutations => {
|
|
443
|
+
for (const mutation of mutations) {
|
|
444
|
+
if (mutation.type !== 'childList') continue;
|
|
445
|
+
for (const node of mutation.addedNodes) {
|
|
446
|
+
if (node.tagName === 'SCRIPT') {
|
|
447
|
+
if (node.type === (shimMode ? 'module-shim' : 'module'))
|
|
448
|
+
processScript(node);
|
|
449
|
+
if (node.type === (shimMode ? 'importmap-shim' : 'importmap'))
|
|
450
|
+
processImportMap(node);
|
|
451
|
+
}
|
|
452
|
+
else if (node.tagName === 'LINK' && node.rel === (shimMode ? 'modulepreload-shim' : 'modulepreload'))
|
|
453
|
+
processPreload(node);
|
|
419
454
|
}
|
|
420
|
-
else if (node.tagName === 'LINK' && node.rel === (shimMode ? 'modulepreload-shim' : 'modulepreload'))
|
|
421
|
-
processPreload(node);
|
|
422
455
|
}
|
|
456
|
+
}).observe(document, {childList: true, subtree: true});
|
|
457
|
+
processImportMaps();
|
|
458
|
+
processScriptsAndPreloads();
|
|
459
|
+
if (document.readyState === 'complete') {
|
|
460
|
+
readyStateCompleteCheck();
|
|
423
461
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
await initPromise;
|
|
433
|
-
processImportMaps();
|
|
434
|
-
if (document.readyState === 'complete') {
|
|
435
|
-
readyStateCompleteCheck();
|
|
436
|
-
document.removeEventListener('readystatechange', readyListener);
|
|
462
|
+
else {
|
|
463
|
+
async function readyListener() {
|
|
464
|
+
await initPromise;
|
|
465
|
+
processImportMaps();
|
|
466
|
+
if (document.readyState === 'complete') {
|
|
467
|
+
readyStateCompleteCheck();
|
|
468
|
+
document.removeEventListener('readystatechange', readyListener);
|
|
469
|
+
}
|
|
437
470
|
}
|
|
471
|
+
document.addEventListener('readystatechange', readyListener);
|
|
438
472
|
}
|
|
439
|
-
document.addEventListener('readystatechange', readyListener);
|
|
440
473
|
}
|
|
441
|
-
return init;
|
|
442
474
|
}
|
|
475
|
+
return init;
|
|
443
476
|
});
|
|
444
477
|
let importMapPromise = initPromise;
|
|
445
478
|
let firstPolyfillLoad = true;
|
|
@@ -519,7 +552,7 @@
|
|
|
519
552
|
const source = load.S;
|
|
520
553
|
|
|
521
554
|
// edge doesnt execute sibling in order, so we fix this up by ensuring all previous executions are explicit dependencies
|
|
522
|
-
let resolvedSource = edge && lastLoad ? `import '${lastLoad}';` : '';
|
|
555
|
+
let resolvedSource = edge && lastLoad ? `import '${lastLoad}';` : '';
|
|
523
556
|
|
|
524
557
|
if (!imports.length) {
|
|
525
558
|
resolvedSource += source;
|
|
@@ -560,7 +593,7 @@
|
|
|
560
593
|
resolvedSource += `/*${source.slice(start - 1, statementEnd)}*/${urlJsString(blobUrl)}`;
|
|
561
594
|
|
|
562
595
|
// circular shell execution
|
|
563
|
-
if (!cycleShell && depLoad.s) {
|
|
596
|
+
if (!cycleShell && depLoad.s) {
|
|
564
597
|
resolvedSource += `;import*as m$_${depIndex} from'${depLoad.b}';import{u$_ as u$_${depIndex}}from'${depLoad.s}';u$_${depIndex}(m$_${depIndex})`;
|
|
565
598
|
depLoad.s = undefined;
|
|
566
599
|
}
|
|
@@ -647,8 +680,8 @@
|
|
|
647
680
|
return { r: res.url, s: `export default ${await res.text()}`, t: 'json' };
|
|
648
681
|
else if (cssContentType.test(contentType)) {
|
|
649
682
|
return { r: res.url, s: `var s=new CSSStyleSheet();s.replaceSync(${
|
|
650
|
-
|
|
651
|
-
|
|
683
|
+
JSON.stringify((await res.text()).replace(cssUrlRegEx, (_match, quotes = '', relUrl1, relUrl2) => `url(${quotes}${resolveUrl(relUrl1 || relUrl2, url)}${quotes})`))
|
|
684
|
+
});export default s;`, t: 'css' };
|
|
652
685
|
}
|
|
653
686
|
else
|
|
654
687
|
throw Error(`Unsupported Content-Type "${contentType}" loading ${url}${fromParent(parent)}. Modules must be served with a valid MIME type like application/javascript.`);
|
|
@@ -718,7 +751,7 @@
|
|
|
718
751
|
load.L = load.f.then(async () => {
|
|
719
752
|
let childFetchOpts = fetchOpts;
|
|
720
753
|
load.d = (await Promise.all(load.a[0].map(async ({ n, d }) => {
|
|
721
|
-
if (d >= 0 && !supportsDynamicImport || d === 2 && !supportsImportMeta)
|
|
754
|
+
if (d >= 0 && !supportsDynamicImport || d === -2 && !supportsImportMeta)
|
|
722
755
|
load.n = true;
|
|
723
756
|
if (d !== -1 || !n) return;
|
|
724
757
|
const { r, b } = await resolve(n, load.r || load.u);
|
|
@@ -769,14 +802,16 @@
|
|
|
769
802
|
document.dispatchEvent(new Event('DOMContentLoaded'));
|
|
770
803
|
}
|
|
771
804
|
// this should always trigger because we assume es-module-shims is itself a domcontentloaded requirement
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
805
|
+
if (hasDocument) {
|
|
806
|
+
document.addEventListener('DOMContentLoaded', async () => {
|
|
807
|
+
await initPromise;
|
|
808
|
+
domContentLoadedCheck();
|
|
809
|
+
if (shimMode || !baselinePassthrough) {
|
|
810
|
+
processImportMaps();
|
|
811
|
+
processScriptsAndPreloads();
|
|
812
|
+
}
|
|
813
|
+
});
|
|
814
|
+
}
|
|
780
815
|
|
|
781
816
|
let readyStateCompleteCnt = 1;
|
|
782
817
|
function readyStateCompleteCheck () {
|
package/index.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ interface ESMSInitOptions {
|
|
|
18
18
|
/**
|
|
19
19
|
* Disable retriggering of document readystate
|
|
20
20
|
*/
|
|
21
|
-
noLoadEventRetriggers: true
|
|
21
|
+
noLoadEventRetriggers: true;
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* #### Skip Processing Stability
|
|
@@ -45,24 +45,28 @@ interface ESMSInitOptions {
|
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
47
|
* #### Error hook
|
|
48
|
-
*
|
|
48
|
+
*
|
|
49
49
|
* Register a callback for any ES Module Shims module errors.
|
|
50
|
-
*
|
|
50
|
+
*
|
|
51
51
|
*/
|
|
52
52
|
onerror: (e: any) => any;
|
|
53
53
|
|
|
54
54
|
/**
|
|
55
55
|
* #### Resolve Hook
|
|
56
|
-
*
|
|
56
|
+
*
|
|
57
57
|
* Only supported in Shim Mode.
|
|
58
|
-
*
|
|
58
|
+
*
|
|
59
59
|
* Provide a custom resolver function.
|
|
60
60
|
*/
|
|
61
|
-
resolve: (
|
|
61
|
+
resolve: (
|
|
62
|
+
id: string,
|
|
63
|
+
parentUrl: string,
|
|
64
|
+
resolve: (id: string, parentUrl: string) => string
|
|
65
|
+
) => string | Promise<string>;
|
|
62
66
|
|
|
63
67
|
/**
|
|
64
68
|
* #### Fetch Hook
|
|
65
|
-
*
|
|
69
|
+
*
|
|
66
70
|
* Only supported in Shim Mode.
|
|
67
71
|
*
|
|
68
72
|
* > Stability: Non-spec feature
|
|
@@ -126,14 +130,19 @@ interface ESMSInitOptions {
|
|
|
126
130
|
|
|
127
131
|
/**
|
|
128
132
|
* #### Revoke Blob URLs
|
|
129
|
-
*
|
|
133
|
+
*
|
|
130
134
|
* Set to *true* to cleanup blob URLs from memory after execution.
|
|
131
135
|
* Can cost some compute time for large loads.
|
|
132
|
-
*
|
|
136
|
+
*
|
|
133
137
|
*/
|
|
134
138
|
revokeBlobURLs: boolean;
|
|
135
139
|
}
|
|
136
140
|
|
|
141
|
+
interface ImportMap {
|
|
142
|
+
imports: Record<string, string>;
|
|
143
|
+
scopes: Record<string, Record<string, string>>;
|
|
144
|
+
}
|
|
145
|
+
|
|
137
146
|
/**
|
|
138
147
|
* Dynamic import(...) within any modules loaded will be rewritten as
|
|
139
148
|
* importShim(...) automatically providing full support for all es-module-shims
|
|
@@ -151,6 +160,12 @@ declare function importShim<Default, Exports extends object>(
|
|
|
151
160
|
parentUrl?: string
|
|
152
161
|
): Promise<{ default: Default } & Exports>;
|
|
153
162
|
|
|
163
|
+
declare namespace importShim {
|
|
164
|
+
const resolve: (id: string, parentURL?: string) => string;
|
|
165
|
+
const addImportMap: (importMap: Partial<ImportMap>) => void;
|
|
166
|
+
const getImportMap: () => ImportMap;
|
|
167
|
+
}
|
|
168
|
+
|
|
154
169
|
interface Window {
|
|
155
170
|
esmsInitOptions?: ESMSInitOptions;
|
|
156
171
|
importShim: typeof importShim;
|