es-module-shims 1.5.6 → 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 +41 -2
- package/dist/es-module-shims.js +91 -66
- package/dist/es-module-shims.wasm.js +101 -68
- 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:
|
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,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,7 +279,7 @@
|
|
|
273
279
|
let supportsJsonAssertions = false;
|
|
274
280
|
let supportsCssAssertions = false;
|
|
275
281
|
|
|
276
|
-
let supportsImportMaps = HTMLScriptElement.supports ? HTMLScriptElement.supports('importmap') : false;
|
|
282
|
+
let supportsImportMaps = hasDocument && HTMLScriptElement.supports ? HTMLScriptElement.supports('importmap') : false;
|
|
277
283
|
let supportsImportMeta = supportsImportMaps;
|
|
278
284
|
let supportsDynamicImport = false;
|
|
279
285
|
|
|
@@ -284,24 +290,32 @@
|
|
|
284
290
|
|
|
285
291
|
return Promise.all([
|
|
286
292
|
supportsImportMaps || dynamicImport(createBlob('import.meta')).then(() => supportsImportMeta = true, noop),
|
|
287
|
-
cssModulesEnabled && dynamicImport(createBlob(
|
|
288
|
-
jsonModulesEnabled && dynamicImport(createBlob(
|
|
289
|
-
supportsImportMaps || new Promise(resolve => {
|
|
290
|
-
self._$s = v => {
|
|
291
|
-
document.head.removeChild(iframe);
|
|
292
|
-
if (v) supportsImportMaps = true;
|
|
293
|
-
delete self._$s;
|
|
294
|
-
resolve();
|
|
295
|
-
};
|
|
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 => {
|
|
296
296
|
const iframe = document.createElement('iframe');
|
|
297
297
|
iframe.style.display = 'none';
|
|
298
298
|
iframe.setAttribute('nonce', nonce);
|
|
299
|
-
document.head.appendChild(iframe);
|
|
300
|
-
// we use document.write here because eg Weixin built-in browser doesn't support setting srcdoc
|
|
301
299
|
// setting src to a blob URL results in a navigation event in webviews
|
|
302
300
|
// setting srcdoc is not supported in React native webviews on iOS
|
|
303
|
-
|
|
304
|
-
|
|
301
|
+
// therefore, we need to first feature detect srcdoc support
|
|
302
|
+
iframe.srcdoc = `<!doctype html><script nonce="${nonce}"><${''}/script>`;
|
|
303
|
+
document.head.appendChild(iframe);
|
|
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
|
+
}))
|
|
305
319
|
]);
|
|
306
320
|
});
|
|
307
321
|
|
|
@@ -338,7 +352,9 @@
|
|
|
338
352
|
await initPromise;
|
|
339
353
|
if (importHook) await importHook(id, typeof args[1] !== 'string' ? args[1] : {}, parentUrl);
|
|
340
354
|
if (acceptingImportMaps || shimMode || !baselinePassthrough) {
|
|
341
|
-
|
|
355
|
+
if (hasDocument)
|
|
356
|
+
processImportMaps();
|
|
357
|
+
|
|
342
358
|
if (!shimMode)
|
|
343
359
|
acceptingImportMaps = false;
|
|
344
360
|
}
|
|
@@ -368,6 +384,10 @@
|
|
|
368
384
|
|
|
369
385
|
importShim.resolve = resolveSync;
|
|
370
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
|
+
};
|
|
371
391
|
|
|
372
392
|
const registry = importShim._r = {};
|
|
373
393
|
|
|
@@ -406,44 +426,47 @@
|
|
|
406
426
|
}
|
|
407
427
|
}
|
|
408
428
|
baselinePassthrough = esmsInitOptions.polyfillEnable !== true && supportsDynamicImport && supportsImportMeta && supportsImportMaps && (!jsonModulesEnabled || supportsJsonAssertions) && (!cssModulesEnabled || supportsCssAssertions) && !importMapSrcOrLazy && !false;
|
|
409
|
-
if (
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
for (const
|
|
418
|
-
if (
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
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);
|
|
423
448
|
}
|
|
424
|
-
else if (node.tagName === 'LINK' && node.rel === (shimMode ? 'modulepreload-shim' : 'modulepreload'))
|
|
425
|
-
processPreload(node);
|
|
426
449
|
}
|
|
450
|
+
}).observe(document, {childList: true, subtree: true});
|
|
451
|
+
processImportMaps();
|
|
452
|
+
processScriptsAndPreloads();
|
|
453
|
+
if (document.readyState === 'complete') {
|
|
454
|
+
readyStateCompleteCheck();
|
|
427
455
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
await initPromise;
|
|
437
|
-
processImportMaps();
|
|
438
|
-
if (document.readyState === 'complete') {
|
|
439
|
-
readyStateCompleteCheck();
|
|
440
|
-
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
|
+
}
|
|
441
464
|
}
|
|
465
|
+
document.addEventListener('readystatechange', readyListener);
|
|
442
466
|
}
|
|
443
|
-
document.addEventListener('readystatechange', readyListener);
|
|
444
467
|
}
|
|
445
|
-
return undefined;
|
|
446
468
|
}
|
|
469
|
+
return undefined;
|
|
447
470
|
});
|
|
448
471
|
let importMapPromise = initPromise;
|
|
449
472
|
let firstPolyfillLoad = true;
|
|
@@ -523,7 +546,7 @@
|
|
|
523
546
|
const source = load.S;
|
|
524
547
|
|
|
525
548
|
// edge doesnt execute sibling in order, so we fix this up by ensuring all previous executions are explicit dependencies
|
|
526
|
-
let resolvedSource = edge && lastLoad ? `import '${lastLoad}';` : '';
|
|
549
|
+
let resolvedSource = edge && lastLoad ? `import '${lastLoad}';` : '';
|
|
527
550
|
|
|
528
551
|
if (!imports.length) {
|
|
529
552
|
resolvedSource += source;
|
|
@@ -564,7 +587,7 @@
|
|
|
564
587
|
resolvedSource += `/*${source.slice(start - 1, statementEnd)}*/${urlJsString(blobUrl)}`;
|
|
565
588
|
|
|
566
589
|
// circular shell execution
|
|
567
|
-
if (!cycleShell && depLoad.s) {
|
|
590
|
+
if (!cycleShell && depLoad.s) {
|
|
568
591
|
resolvedSource += `;import*as m$_${depIndex} from'${depLoad.b}';import{u$_ as u$_${depIndex}}from'${depLoad.s}';u$_${depIndex}(m$_${depIndex})`;
|
|
569
592
|
depLoad.s = undefined;
|
|
570
593
|
}
|
|
@@ -651,8 +674,8 @@
|
|
|
651
674
|
return { r: res.url, s: `export default ${await res.text()}`, t: 'json' };
|
|
652
675
|
else if (cssContentType.test(contentType)) {
|
|
653
676
|
return { r: res.url, s: `var s=new CSSStyleSheet();s.replaceSync(${
|
|
654
|
-
|
|
655
|
-
|
|
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' };
|
|
656
679
|
}
|
|
657
680
|
else
|
|
658
681
|
throw Error(`Unsupported Content-Type "${contentType}" loading ${url}${fromParent(parent)}. Modules must be served with a valid MIME type like application/javascript.`);
|
|
@@ -773,14 +796,16 @@
|
|
|
773
796
|
document.dispatchEvent(new Event('DOMContentLoaded'));
|
|
774
797
|
}
|
|
775
798
|
// this should always trigger because we assume es-module-shims is itself a domcontentloaded requirement
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
799
|
+
if (hasDocument) {
|
|
800
|
+
document.addEventListener('DOMContentLoaded', async () => {
|
|
801
|
+
await initPromise;
|
|
802
|
+
domContentLoadedCheck();
|
|
803
|
+
if (shimMode || !baselinePassthrough) {
|
|
804
|
+
processImportMaps();
|
|
805
|
+
processScriptsAndPreloads();
|
|
806
|
+
}
|
|
807
|
+
});
|
|
808
|
+
}
|
|
784
809
|
|
|
785
810
|
let readyStateCompleteCnt = 1;
|
|
786
811
|
function readyStateCompleteCheck () {
|
|
@@ -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,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,7 +285,7 @@
|
|
|
271
285
|
let supportsJsonAssertions = false;
|
|
272
286
|
let supportsCssAssertions = false;
|
|
273
287
|
|
|
274
|
-
let supportsImportMaps = HTMLScriptElement.supports ? HTMLScriptElement.supports('importmap') : false;
|
|
288
|
+
let supportsImportMaps = hasDocument && HTMLScriptElement.supports ? HTMLScriptElement.supports('importmap') : false;
|
|
275
289
|
let supportsImportMeta = supportsImportMaps;
|
|
276
290
|
let supportsDynamicImport = false;
|
|
277
291
|
|
|
@@ -282,24 +296,32 @@
|
|
|
282
296
|
|
|
283
297
|
return Promise.all([
|
|
284
298
|
supportsImportMaps || dynamicImport(createBlob('import.meta')).then(() => supportsImportMeta = true, noop),
|
|
285
|
-
cssModulesEnabled && dynamicImport(createBlob(
|
|
286
|
-
jsonModulesEnabled && dynamicImport(createBlob(
|
|
287
|
-
supportsImportMaps || new Promise(resolve => {
|
|
288
|
-
self._$s = v => {
|
|
289
|
-
document.head.removeChild(iframe);
|
|
290
|
-
if (v) supportsImportMaps = true;
|
|
291
|
-
delete self._$s;
|
|
292
|
-
resolve();
|
|
293
|
-
};
|
|
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 => {
|
|
294
302
|
const iframe = document.createElement('iframe');
|
|
295
303
|
iframe.style.display = 'none';
|
|
296
304
|
iframe.setAttribute('nonce', nonce);
|
|
297
|
-
document.head.appendChild(iframe);
|
|
298
|
-
// we use document.write here because eg Weixin built-in browser doesn't support setting srcdoc
|
|
299
305
|
// setting src to a blob URL results in a navigation event in webviews
|
|
300
306
|
// setting srcdoc is not supported in React native webviews on iOS
|
|
301
|
-
|
|
302
|
-
|
|
307
|
+
// therefore, we need to first feature detect srcdoc support
|
|
308
|
+
iframe.srcdoc = `<!doctype html><script nonce="${nonce}"><${''}/script>`;
|
|
309
|
+
document.head.appendChild(iframe);
|
|
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
|
+
}))
|
|
303
325
|
]);
|
|
304
326
|
});
|
|
305
327
|
|
|
@@ -336,7 +358,9 @@
|
|
|
336
358
|
await initPromise;
|
|
337
359
|
if (importHook) await importHook(id, typeof args[1] !== 'string' ? args[1] : {}, parentUrl);
|
|
338
360
|
if (acceptingImportMaps || shimMode || !baselinePassthrough) {
|
|
339
|
-
|
|
361
|
+
if (hasDocument)
|
|
362
|
+
processImportMaps();
|
|
363
|
+
|
|
340
364
|
if (!shimMode)
|
|
341
365
|
acceptingImportMaps = false;
|
|
342
366
|
}
|
|
@@ -366,6 +390,10 @@
|
|
|
366
390
|
|
|
367
391
|
importShim.resolve = resolveSync;
|
|
368
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
|
+
};
|
|
369
397
|
|
|
370
398
|
const registry = importShim._r = {};
|
|
371
399
|
|
|
@@ -404,44 +432,47 @@
|
|
|
404
432
|
}
|
|
405
433
|
}
|
|
406
434
|
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
|
-
|
|
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);
|
|
421
454
|
}
|
|
422
|
-
else if (node.tagName === 'LINK' && node.rel === (shimMode ? 'modulepreload-shim' : 'modulepreload'))
|
|
423
|
-
processPreload(node);
|
|
424
455
|
}
|
|
456
|
+
}).observe(document, {childList: true, subtree: true});
|
|
457
|
+
processImportMaps();
|
|
458
|
+
processScriptsAndPreloads();
|
|
459
|
+
if (document.readyState === 'complete') {
|
|
460
|
+
readyStateCompleteCheck();
|
|
425
461
|
}
|
|
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);
|
|
462
|
+
else {
|
|
463
|
+
async function readyListener() {
|
|
464
|
+
await initPromise;
|
|
465
|
+
processImportMaps();
|
|
466
|
+
if (document.readyState === 'complete') {
|
|
467
|
+
readyStateCompleteCheck();
|
|
468
|
+
document.removeEventListener('readystatechange', readyListener);
|
|
469
|
+
}
|
|
439
470
|
}
|
|
471
|
+
document.addEventListener('readystatechange', readyListener);
|
|
440
472
|
}
|
|
441
|
-
document.addEventListener('readystatechange', readyListener);
|
|
442
473
|
}
|
|
443
|
-
return init;
|
|
444
474
|
}
|
|
475
|
+
return init;
|
|
445
476
|
});
|
|
446
477
|
let importMapPromise = initPromise;
|
|
447
478
|
let firstPolyfillLoad = true;
|
|
@@ -521,7 +552,7 @@
|
|
|
521
552
|
const source = load.S;
|
|
522
553
|
|
|
523
554
|
// 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}';` : '';
|
|
555
|
+
let resolvedSource = edge && lastLoad ? `import '${lastLoad}';` : '';
|
|
525
556
|
|
|
526
557
|
if (!imports.length) {
|
|
527
558
|
resolvedSource += source;
|
|
@@ -562,7 +593,7 @@
|
|
|
562
593
|
resolvedSource += `/*${source.slice(start - 1, statementEnd)}*/${urlJsString(blobUrl)}`;
|
|
563
594
|
|
|
564
595
|
// circular shell execution
|
|
565
|
-
if (!cycleShell && depLoad.s) {
|
|
596
|
+
if (!cycleShell && depLoad.s) {
|
|
566
597
|
resolvedSource += `;import*as m$_${depIndex} from'${depLoad.b}';import{u$_ as u$_${depIndex}}from'${depLoad.s}';u$_${depIndex}(m$_${depIndex})`;
|
|
567
598
|
depLoad.s = undefined;
|
|
568
599
|
}
|
|
@@ -649,8 +680,8 @@
|
|
|
649
680
|
return { r: res.url, s: `export default ${await res.text()}`, t: 'json' };
|
|
650
681
|
else if (cssContentType.test(contentType)) {
|
|
651
682
|
return { r: res.url, s: `var s=new CSSStyleSheet();s.replaceSync(${
|
|
652
|
-
|
|
653
|
-
|
|
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' };
|
|
654
685
|
}
|
|
655
686
|
else
|
|
656
687
|
throw Error(`Unsupported Content-Type "${contentType}" loading ${url}${fromParent(parent)}. Modules must be served with a valid MIME type like application/javascript.`);
|
|
@@ -771,14 +802,16 @@
|
|
|
771
802
|
document.dispatchEvent(new Event('DOMContentLoaded'));
|
|
772
803
|
}
|
|
773
804
|
// this should always trigger because we assume es-module-shims is itself a domcontentloaded requirement
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
805
|
+
if (hasDocument) {
|
|
806
|
+
document.addEventListener('DOMContentLoaded', async () => {
|
|
807
|
+
await initPromise;
|
|
808
|
+
domContentLoadedCheck();
|
|
809
|
+
if (shimMode || !baselinePassthrough) {
|
|
810
|
+
processImportMaps();
|
|
811
|
+
processScriptsAndPreloads();
|
|
812
|
+
}
|
|
813
|
+
});
|
|
814
|
+
}
|
|
782
815
|
|
|
783
816
|
let readyStateCompleteCnt = 1;
|
|
784
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;
|