es-module-shims 1.5.4 → 1.5.7
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 +43 -2
- package/dist/es-module-shims.js +106 -69
- package/dist/es-module-shims.wasm.js +116 -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.7/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:
|
|
@@ -675,6 +714,8 @@ window.polyfilling = () => console.log('The polyfill is actively applying');
|
|
|
675
714
|
|
|
676
715
|
The default hook will log a message to the console with `console.info` noting that polyfill mode is enabled and that the native error can be ignored.
|
|
677
716
|
|
|
717
|
+
Overriding this hook with an empty function will disable the default polyfill log output.
|
|
718
|
+
|
|
678
719
|
In the above, running in latest Chromium browsers, nothing will be logged, while running in an older browser that does not support newer features like import maps the console log will be output.
|
|
679
720
|
|
|
680
721
|
#### Error hook
|
package/dist/es-module-shims.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
/* ES Module Shims 1.5.
|
|
1
|
+
/* ES Module Shims 1.5.7 */
|
|
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,18 +20,19 @@
|
|
|
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');
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
const onerror = globalHook(esmsInitOptions.onerror || noop);
|
|
31
|
-
const onpolyfill = esmsInitOptions.onpolyfill ? globalHook(esmsInitOptions.onpolyfill) : () =>
|
|
33
|
+
const onpolyfill = esmsInitOptions.onpolyfill ? globalHook(esmsInitOptions.onpolyfill) : () => {
|
|
34
|
+
console.log('%c^^ Module TypeError above is polyfilled and can be ignored ^^', 'font-weight:900;color:#391');
|
|
35
|
+
};
|
|
32
36
|
|
|
33
37
|
const { revokeBlobURLs, noLoadEventRetriggers, enforceIntegrity } = esmsInitOptions;
|
|
34
38
|
|
|
@@ -46,7 +50,11 @@
|
|
|
46
50
|
|
|
47
51
|
const edge = !navigator.userAgentData && !!navigator.userAgent.match(/Edge\/\d+\.\d+/);
|
|
48
52
|
|
|
49
|
-
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}`;
|
|
50
58
|
|
|
51
59
|
function createBlob (source, type = 'text/javascript') {
|
|
52
60
|
return URL.createObjectURL(new Blob([source], { type }));
|
|
@@ -54,7 +62,7 @@
|
|
|
54
62
|
|
|
55
63
|
const eoop = err => setTimeout(() => { throw err });
|
|
56
64
|
|
|
57
|
-
const throwError = err => { (
|
|
65
|
+
const throwError = err => { (self.reportError || hasWindow && window.safari && console.error || eoop)(err), void onerror(err); };
|
|
58
66
|
|
|
59
67
|
function fromParent (parent) {
|
|
60
68
|
return parent ? ` imported from ${parent}` : '';
|
|
@@ -271,32 +279,43 @@
|
|
|
271
279
|
let supportsJsonAssertions = false;
|
|
272
280
|
let supportsCssAssertions = false;
|
|
273
281
|
|
|
274
|
-
let
|
|
275
|
-
let
|
|
276
|
-
|
|
282
|
+
let supportsImportMaps = hasDocument && HTMLScriptElement.supports ? HTMLScriptElement.supports('importmap') : false;
|
|
283
|
+
let supportsImportMeta = supportsImportMaps;
|
|
277
284
|
let supportsDynamicImport = false;
|
|
278
285
|
|
|
279
|
-
const featureDetectionPromise = Promise.resolve(supportsDynamicImportCheck).then(_supportsDynamicImport => {
|
|
286
|
+
const featureDetectionPromise = Promise.resolve(supportsImportMaps || supportsDynamicImportCheck).then(_supportsDynamicImport => {
|
|
280
287
|
if (!_supportsDynamicImport)
|
|
281
288
|
return;
|
|
282
289
|
supportsDynamicImport = true;
|
|
283
290
|
|
|
284
291
|
return Promise.all([
|
|
285
|
-
dynamicImport(createBlob('import.meta')).then(() => supportsImportMeta = true, noop),
|
|
286
|
-
cssModulesEnabled && dynamicImport(createBlob(
|
|
287
|
-
jsonModulesEnabled && dynamicImport(createBlob(
|
|
288
|
-
new Promise(resolve => {
|
|
289
|
-
self._$s = v => {
|
|
290
|
-
document.head.removeChild(iframe);
|
|
291
|
-
if (v) supportsImportMaps = true;
|
|
292
|
-
delete self._$s;
|
|
293
|
-
resolve();
|
|
294
|
-
};
|
|
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 => {
|
|
295
296
|
const iframe = document.createElement('iframe');
|
|
296
297
|
iframe.style.display = 'none';
|
|
297
|
-
iframe.
|
|
298
|
+
iframe.setAttribute('nonce', nonce);
|
|
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>`;
|
|
298
303
|
document.head.appendChild(iframe);
|
|
299
|
-
|
|
304
|
+
iframe.contentWindow.addEventListener('DOMContentLoaded', () => {
|
|
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
|
+
}))
|
|
300
319
|
]);
|
|
301
320
|
});
|
|
302
321
|
|
|
@@ -333,7 +352,9 @@
|
|
|
333
352
|
await initPromise;
|
|
334
353
|
if (importHook) await importHook(id, typeof args[1] !== 'string' ? args[1] : {}, parentUrl);
|
|
335
354
|
if (acceptingImportMaps || shimMode || !baselinePassthrough) {
|
|
336
|
-
|
|
355
|
+
if (hasDocument)
|
|
356
|
+
processImportMaps();
|
|
357
|
+
|
|
337
358
|
if (!shimMode)
|
|
338
359
|
acceptingImportMaps = false;
|
|
339
360
|
}
|
|
@@ -363,6 +384,10 @@
|
|
|
363
384
|
|
|
364
385
|
importShim.resolve = resolveSync;
|
|
365
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
|
+
};
|
|
366
391
|
|
|
367
392
|
const registry = importShim._r = {};
|
|
368
393
|
|
|
@@ -401,26 +426,47 @@
|
|
|
401
426
|
}
|
|
402
427
|
}
|
|
403
428
|
baselinePassthrough = esmsInitOptions.polyfillEnable !== true && supportsDynamicImport && supportsImportMeta && supportsImportMaps && (!jsonModulesEnabled || supportsJsonAssertions) && (!cssModulesEnabled || supportsCssAssertions) && !importMapSrcOrLazy && !false;
|
|
404
|
-
if (
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
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);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}).observe(document, {childList: true, subtree: true});
|
|
451
|
+
processImportMaps();
|
|
452
|
+
processScriptsAndPreloads();
|
|
453
|
+
if (document.readyState === 'complete') {
|
|
454
|
+
readyStateCompleteCheck();
|
|
455
|
+
}
|
|
456
|
+
else {
|
|
457
|
+
async function readyListener() {
|
|
458
|
+
await initPromise;
|
|
459
|
+
processImportMaps();
|
|
460
|
+
if (document.readyState === 'complete') {
|
|
461
|
+
readyStateCompleteCheck();
|
|
462
|
+
document.removeEventListener('readystatechange', readyListener);
|
|
414
463
|
}
|
|
415
|
-
else if (node.tagName === 'LINK' && node.rel === (shimMode ? 'modulepreload-shim' : 'modulepreload'))
|
|
416
|
-
processPreload(node);
|
|
417
464
|
}
|
|
465
|
+
document.addEventListener('readystatechange', readyListener);
|
|
418
466
|
}
|
|
419
|
-
}
|
|
420
|
-
processImportMaps();
|
|
421
|
-
processScriptsAndPreloads();
|
|
422
|
-
return undefined;
|
|
467
|
+
}
|
|
423
468
|
}
|
|
469
|
+
return undefined;
|
|
424
470
|
});
|
|
425
471
|
let importMapPromise = initPromise;
|
|
426
472
|
let firstPolyfillLoad = true;
|
|
@@ -500,7 +546,7 @@
|
|
|
500
546
|
const source = load.S;
|
|
501
547
|
|
|
502
548
|
// edge doesnt execute sibling in order, so we fix this up by ensuring all previous executions are explicit dependencies
|
|
503
|
-
let resolvedSource = edge && lastLoad ? `import '${lastLoad}';` : '';
|
|
549
|
+
let resolvedSource = edge && lastLoad ? `import '${lastLoad}';` : '';
|
|
504
550
|
|
|
505
551
|
if (!imports.length) {
|
|
506
552
|
resolvedSource += source;
|
|
@@ -541,7 +587,7 @@
|
|
|
541
587
|
resolvedSource += `/*${source.slice(start - 1, statementEnd)}*/${urlJsString(blobUrl)}`;
|
|
542
588
|
|
|
543
589
|
// circular shell execution
|
|
544
|
-
if (!cycleShell && depLoad.s) {
|
|
590
|
+
if (!cycleShell && depLoad.s) {
|
|
545
591
|
resolvedSource += `;import*as m$_${depIndex} from'${depLoad.b}';import{u$_ as u$_${depIndex}}from'${depLoad.s}';u$_${depIndex}(m$_${depIndex})`;
|
|
546
592
|
depLoad.s = undefined;
|
|
547
593
|
}
|
|
@@ -628,8 +674,8 @@
|
|
|
628
674
|
return { r: res.url, s: `export default ${await res.text()}`, t: 'json' };
|
|
629
675
|
else if (cssContentType.test(contentType)) {
|
|
630
676
|
return { r: res.url, s: `var s=new CSSStyleSheet();s.replaceSync(${
|
|
631
|
-
|
|
632
|
-
|
|
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' };
|
|
633
679
|
}
|
|
634
680
|
else
|
|
635
681
|
throw Error(`Unsupported Content-Type "${contentType}" loading ${url}${fromParent(parent)}. Modules must be served with a valid MIME type like application/javascript.`);
|
|
@@ -699,7 +745,7 @@
|
|
|
699
745
|
load.L = load.f.then(async () => {
|
|
700
746
|
let childFetchOpts = fetchOpts;
|
|
701
747
|
load.d = (await Promise.all(load.a[0].map(async ({ n, d }) => {
|
|
702
|
-
if (d >= 0 && !supportsDynamicImport || d === 2 && !supportsImportMeta)
|
|
748
|
+
if (d >= 0 && !supportsDynamicImport || d === -2 && !supportsImportMeta)
|
|
703
749
|
load.n = true;
|
|
704
750
|
if (d !== -1 || !n) return;
|
|
705
751
|
const { r, b } = await resolve(n, load.r || load.u);
|
|
@@ -750,26 +796,18 @@
|
|
|
750
796
|
document.dispatchEvent(new Event('DOMContentLoaded'));
|
|
751
797
|
}
|
|
752
798
|
// this should always trigger because we assume es-module-shims is itself a domcontentloaded requirement
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
domContentLoadedCheck();
|
|
756
|
-
if (shimMode || !baselinePassthrough) {
|
|
757
|
-
processImportMaps();
|
|
758
|
-
processScriptsAndPreloads();
|
|
759
|
-
}
|
|
760
|
-
});
|
|
761
|
-
|
|
762
|
-
let readyStateCompleteCnt = 1;
|
|
763
|
-
if (document.readyState === 'complete') {
|
|
764
|
-
readyStateCompleteCheck();
|
|
765
|
-
}
|
|
766
|
-
else {
|
|
767
|
-
document.addEventListener('readystatechange', async () => {
|
|
768
|
-
processImportMaps();
|
|
799
|
+
if (hasDocument) {
|
|
800
|
+
document.addEventListener('DOMContentLoaded', async () => {
|
|
769
801
|
await initPromise;
|
|
770
|
-
|
|
802
|
+
domContentLoadedCheck();
|
|
803
|
+
if (shimMode || !baselinePassthrough) {
|
|
804
|
+
processImportMaps();
|
|
805
|
+
processScriptsAndPreloads();
|
|
806
|
+
}
|
|
771
807
|
});
|
|
772
808
|
}
|
|
809
|
+
|
|
810
|
+
let readyStateCompleteCnt = 1;
|
|
773
811
|
function readyStateCompleteCheck () {
|
|
774
812
|
if (--readyStateCompleteCnt === 0 && !noLoadEventRetriggers)
|
|
775
813
|
document.dispatchEvent(new Event('readystatechange'));
|
|
@@ -809,14 +847,13 @@
|
|
|
809
847
|
return;
|
|
810
848
|
script.ep = true;
|
|
811
849
|
// does this load block readystate complete
|
|
812
|
-
const
|
|
850
|
+
const isBlockingReadyScript = script.getAttribute('async') === null && readyStateCompleteCnt > 0;
|
|
813
851
|
// does this load block DOMContentLoaded
|
|
814
852
|
const isDomContentLoadedScript = domContentLoadedCnt > 0;
|
|
815
|
-
if (
|
|
853
|
+
if (isBlockingReadyScript) readyStateCompleteCnt++;
|
|
816
854
|
if (isDomContentLoadedScript) domContentLoadedCnt++;
|
|
817
|
-
const
|
|
818
|
-
|
|
819
|
-
if (blocks)
|
|
855
|
+
const loadPromise = topLevelLoad(script.src || baseUrl, getFetchOpts(script), !script.src && script.innerHTML, !shimMode, isBlockingReadyScript && lastStaticLoadPromise).catch(throwError);
|
|
856
|
+
if (isBlockingReadyScript)
|
|
820
857
|
lastStaticLoadPromise = loadPromise.then(readyStateCompleteCheck);
|
|
821
858
|
if (isDomContentLoadedScript)
|
|
822
859
|
loadPromise.then(domContentLoadedCheck);
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
/* ES Module Shims Wasm 1.5.
|
|
1
|
+
/* ES Module Shims Wasm 1.5.7 */
|
|
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,18 +20,19 @@
|
|
|
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');
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
const onerror = globalHook(esmsInitOptions.onerror || noop);
|
|
31
|
-
const onpolyfill = esmsInitOptions.onpolyfill ? globalHook(esmsInitOptions.onpolyfill) : () =>
|
|
33
|
+
const onpolyfill = esmsInitOptions.onpolyfill ? globalHook(esmsInitOptions.onpolyfill) : () => {
|
|
34
|
+
console.log('%c^^ Module TypeError above is polyfilled and can be ignored ^^', 'font-weight:900;color:#391');
|
|
35
|
+
};
|
|
32
36
|
|
|
33
37
|
const { revokeBlobURLs, noLoadEventRetriggers, enforceIntegrity } = esmsInitOptions;
|
|
34
38
|
|
|
@@ -46,7 +50,11 @@
|
|
|
46
50
|
|
|
47
51
|
const edge = !navigator.userAgentData && !!navigator.userAgent.match(/Edge\/\d+\.\d+/);
|
|
48
52
|
|
|
49
|
-
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}`;
|
|
50
58
|
|
|
51
59
|
function createBlob (source, type = 'text/javascript') {
|
|
52
60
|
return URL.createObjectURL(new Blob([source], { type }));
|
|
@@ -54,7 +62,7 @@
|
|
|
54
62
|
|
|
55
63
|
const eoop = err => setTimeout(() => { throw err });
|
|
56
64
|
|
|
57
|
-
const throwError = err => { (
|
|
65
|
+
const throwError = err => { (self.reportError || hasWindow && window.safari && console.error || eoop)(err), void onerror(err); };
|
|
58
66
|
|
|
59
67
|
function fromParent (parent) {
|
|
60
68
|
return parent ? ` imported from ${parent}` : '';
|
|
@@ -232,6 +240,15 @@
|
|
|
232
240
|
|
|
233
241
|
let supportsDynamicImportCheck = false;
|
|
234
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
|
|
235
252
|
let dynamicImport;
|
|
236
253
|
try {
|
|
237
254
|
dynamicImport = (0, eval)('u=>import(u)');
|
|
@@ -239,7 +256,7 @@
|
|
|
239
256
|
}
|
|
240
257
|
catch (e) {}
|
|
241
258
|
|
|
242
|
-
if (!supportsDynamicImportCheck) {
|
|
259
|
+
if (hasDocument && !supportsDynamicImportCheck) {
|
|
243
260
|
let err;
|
|
244
261
|
window.addEventListener('error', _err => err = _err);
|
|
245
262
|
dynamicImport = (url, { errUrl = url }) => {
|
|
@@ -247,7 +264,6 @@
|
|
|
247
264
|
const src = createBlob(`import*as m from'${url}';self._esmsi=m;`);
|
|
248
265
|
const s = Object.assign(document.createElement('script'), { type: 'module', src });
|
|
249
266
|
s.setAttribute('noshim', '');
|
|
250
|
-
s.setAttribute('nonce', nonce);
|
|
251
267
|
document.head.appendChild(s);
|
|
252
268
|
return new Promise((resolve, reject) => {
|
|
253
269
|
s.addEventListener('load', () => {
|
|
@@ -269,32 +285,43 @@
|
|
|
269
285
|
let supportsJsonAssertions = false;
|
|
270
286
|
let supportsCssAssertions = false;
|
|
271
287
|
|
|
272
|
-
let
|
|
273
|
-
let
|
|
274
|
-
|
|
288
|
+
let supportsImportMaps = hasDocument && HTMLScriptElement.supports ? HTMLScriptElement.supports('importmap') : false;
|
|
289
|
+
let supportsImportMeta = supportsImportMaps;
|
|
275
290
|
let supportsDynamicImport = false;
|
|
276
291
|
|
|
277
|
-
const featureDetectionPromise = Promise.resolve(supportsDynamicImportCheck).then(_supportsDynamicImport => {
|
|
292
|
+
const featureDetectionPromise = Promise.resolve(supportsImportMaps || supportsDynamicImportCheck).then(_supportsDynamicImport => {
|
|
278
293
|
if (!_supportsDynamicImport)
|
|
279
294
|
return;
|
|
280
295
|
supportsDynamicImport = true;
|
|
281
296
|
|
|
282
297
|
return Promise.all([
|
|
283
|
-
dynamicImport(createBlob('import.meta')).then(() => supportsImportMeta = true, noop),
|
|
284
|
-
cssModulesEnabled && dynamicImport(createBlob(
|
|
285
|
-
jsonModulesEnabled && dynamicImport(createBlob(
|
|
286
|
-
new Promise(resolve => {
|
|
287
|
-
self._$s = v => {
|
|
288
|
-
document.head.removeChild(iframe);
|
|
289
|
-
if (v) supportsImportMaps = true;
|
|
290
|
-
delete self._$s;
|
|
291
|
-
resolve();
|
|
292
|
-
};
|
|
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 => {
|
|
293
302
|
const iframe = document.createElement('iframe');
|
|
294
303
|
iframe.style.display = 'none';
|
|
295
|
-
iframe.
|
|
304
|
+
iframe.setAttribute('nonce', nonce);
|
|
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>`;
|
|
296
309
|
document.head.appendChild(iframe);
|
|
297
|
-
|
|
310
|
+
iframe.contentWindow.addEventListener('DOMContentLoaded', () => {
|
|
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
|
+
}))
|
|
298
325
|
]);
|
|
299
326
|
});
|
|
300
327
|
|
|
@@ -331,7 +358,9 @@
|
|
|
331
358
|
await initPromise;
|
|
332
359
|
if (importHook) await importHook(id, typeof args[1] !== 'string' ? args[1] : {}, parentUrl);
|
|
333
360
|
if (acceptingImportMaps || shimMode || !baselinePassthrough) {
|
|
334
|
-
|
|
361
|
+
if (hasDocument)
|
|
362
|
+
processImportMaps();
|
|
363
|
+
|
|
335
364
|
if (!shimMode)
|
|
336
365
|
acceptingImportMaps = false;
|
|
337
366
|
}
|
|
@@ -361,6 +390,10 @@
|
|
|
361
390
|
|
|
362
391
|
importShim.resolve = resolveSync;
|
|
363
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
|
+
};
|
|
364
397
|
|
|
365
398
|
const registry = importShim._r = {};
|
|
366
399
|
|
|
@@ -399,26 +432,47 @@
|
|
|
399
432
|
}
|
|
400
433
|
}
|
|
401
434
|
baselinePassthrough = esmsInitOptions.polyfillEnable !== true && supportsDynamicImport && supportsImportMeta && supportsImportMaps && (!jsonModulesEnabled || supportsJsonAssertions) && (!cssModulesEnabled || supportsCssAssertions) && !importMapSrcOrLazy && !false;
|
|
402
|
-
if (
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
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);
|
|
412
454
|
}
|
|
413
|
-
else if (node.tagName === 'LINK' && node.rel === (shimMode ? 'modulepreload-shim' : 'modulepreload'))
|
|
414
|
-
processPreload(node);
|
|
415
455
|
}
|
|
456
|
+
}).observe(document, {childList: true, subtree: true});
|
|
457
|
+
processImportMaps();
|
|
458
|
+
processScriptsAndPreloads();
|
|
459
|
+
if (document.readyState === 'complete') {
|
|
460
|
+
readyStateCompleteCheck();
|
|
416
461
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
462
|
+
else {
|
|
463
|
+
async function readyListener() {
|
|
464
|
+
await initPromise;
|
|
465
|
+
processImportMaps();
|
|
466
|
+
if (document.readyState === 'complete') {
|
|
467
|
+
readyStateCompleteCheck();
|
|
468
|
+
document.removeEventListener('readystatechange', readyListener);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
document.addEventListener('readystatechange', readyListener);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
421
474
|
}
|
|
475
|
+
return init;
|
|
422
476
|
});
|
|
423
477
|
let importMapPromise = initPromise;
|
|
424
478
|
let firstPolyfillLoad = true;
|
|
@@ -498,7 +552,7 @@
|
|
|
498
552
|
const source = load.S;
|
|
499
553
|
|
|
500
554
|
// edge doesnt execute sibling in order, so we fix this up by ensuring all previous executions are explicit dependencies
|
|
501
|
-
let resolvedSource = edge && lastLoad ? `import '${lastLoad}';` : '';
|
|
555
|
+
let resolvedSource = edge && lastLoad ? `import '${lastLoad}';` : '';
|
|
502
556
|
|
|
503
557
|
if (!imports.length) {
|
|
504
558
|
resolvedSource += source;
|
|
@@ -539,7 +593,7 @@
|
|
|
539
593
|
resolvedSource += `/*${source.slice(start - 1, statementEnd)}*/${urlJsString(blobUrl)}`;
|
|
540
594
|
|
|
541
595
|
// circular shell execution
|
|
542
|
-
if (!cycleShell && depLoad.s) {
|
|
596
|
+
if (!cycleShell && depLoad.s) {
|
|
543
597
|
resolvedSource += `;import*as m$_${depIndex} from'${depLoad.b}';import{u$_ as u$_${depIndex}}from'${depLoad.s}';u$_${depIndex}(m$_${depIndex})`;
|
|
544
598
|
depLoad.s = undefined;
|
|
545
599
|
}
|
|
@@ -626,8 +680,8 @@
|
|
|
626
680
|
return { r: res.url, s: `export default ${await res.text()}`, t: 'json' };
|
|
627
681
|
else if (cssContentType.test(contentType)) {
|
|
628
682
|
return { r: res.url, s: `var s=new CSSStyleSheet();s.replaceSync(${
|
|
629
|
-
|
|
630
|
-
|
|
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' };
|
|
631
685
|
}
|
|
632
686
|
else
|
|
633
687
|
throw Error(`Unsupported Content-Type "${contentType}" loading ${url}${fromParent(parent)}. Modules must be served with a valid MIME type like application/javascript.`);
|
|
@@ -697,7 +751,7 @@
|
|
|
697
751
|
load.L = load.f.then(async () => {
|
|
698
752
|
let childFetchOpts = fetchOpts;
|
|
699
753
|
load.d = (await Promise.all(load.a[0].map(async ({ n, d }) => {
|
|
700
|
-
if (d >= 0 && !supportsDynamicImport || d === 2 && !supportsImportMeta)
|
|
754
|
+
if (d >= 0 && !supportsDynamicImport || d === -2 && !supportsImportMeta)
|
|
701
755
|
load.n = true;
|
|
702
756
|
if (d !== -1 || !n) return;
|
|
703
757
|
const { r, b } = await resolve(n, load.r || load.u);
|
|
@@ -748,26 +802,18 @@
|
|
|
748
802
|
document.dispatchEvent(new Event('DOMContentLoaded'));
|
|
749
803
|
}
|
|
750
804
|
// this should always trigger because we assume es-module-shims is itself a domcontentloaded requirement
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
domContentLoadedCheck();
|
|
754
|
-
if (shimMode || !baselinePassthrough) {
|
|
755
|
-
processImportMaps();
|
|
756
|
-
processScriptsAndPreloads();
|
|
757
|
-
}
|
|
758
|
-
});
|
|
759
|
-
|
|
760
|
-
let readyStateCompleteCnt = 1;
|
|
761
|
-
if (document.readyState === 'complete') {
|
|
762
|
-
readyStateCompleteCheck();
|
|
763
|
-
}
|
|
764
|
-
else {
|
|
765
|
-
document.addEventListener('readystatechange', async () => {
|
|
766
|
-
processImportMaps();
|
|
805
|
+
if (hasDocument) {
|
|
806
|
+
document.addEventListener('DOMContentLoaded', async () => {
|
|
767
807
|
await initPromise;
|
|
768
|
-
|
|
808
|
+
domContentLoadedCheck();
|
|
809
|
+
if (shimMode || !baselinePassthrough) {
|
|
810
|
+
processImportMaps();
|
|
811
|
+
processScriptsAndPreloads();
|
|
812
|
+
}
|
|
769
813
|
});
|
|
770
814
|
}
|
|
815
|
+
|
|
816
|
+
let readyStateCompleteCnt = 1;
|
|
771
817
|
function readyStateCompleteCheck () {
|
|
772
818
|
if (--readyStateCompleteCnt === 0 && !noLoadEventRetriggers)
|
|
773
819
|
document.dispatchEvent(new Event('readystatechange'));
|
|
@@ -807,14 +853,13 @@
|
|
|
807
853
|
return;
|
|
808
854
|
script.ep = true;
|
|
809
855
|
// does this load block readystate complete
|
|
810
|
-
const
|
|
856
|
+
const isBlockingReadyScript = script.getAttribute('async') === null && readyStateCompleteCnt > 0;
|
|
811
857
|
// does this load block DOMContentLoaded
|
|
812
858
|
const isDomContentLoadedScript = domContentLoadedCnt > 0;
|
|
813
|
-
if (
|
|
859
|
+
if (isBlockingReadyScript) readyStateCompleteCnt++;
|
|
814
860
|
if (isDomContentLoadedScript) domContentLoadedCnt++;
|
|
815
|
-
const
|
|
816
|
-
|
|
817
|
-
if (blocks)
|
|
861
|
+
const loadPromise = topLevelLoad(script.src || baseUrl, getFetchOpts(script), !script.src && script.innerHTML, !shimMode, isBlockingReadyScript && lastStaticLoadPromise).catch(throwError);
|
|
862
|
+
if (isBlockingReadyScript)
|
|
818
863
|
lastStaticLoadPromise = loadPromise.then(readyStateCompleteCheck);
|
|
819
864
|
if (isDomContentLoadedScript)
|
|
820
865
|
loadPromise.then(domContentLoadedCheck);
|
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;
|