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 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.5/dist/es-module-shims.js"></script>
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:
@@ -1,14 +1,17 @@
1
- /* ES Module Shims 1.5.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
- if (!nonce) {
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 = document.baseURI;
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 => { (window.reportError || window.safari && console.error || eoop)(err), void onerror(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 supportsImportMeta = false;
277
- let supportsImportMaps = false;
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('import"data:text/css,{}"assert{type:"css"}')).then(() => supportsCssAssertions = true, noop),
289
- jsonModulesEnabled && dynamicImport(createBlob('import"data:text/json,{}"assert{type:"json"}')).then(() => supportsJsonAssertions = true, noop),
290
- HTMLScriptElement.supports ? supportsImportMaps = HTMLScriptElement.supports('importmap') : new Promise(resolve => {
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
- iframe.srcdoc = `<script type=importmap nonce="${nonce}">{"imports":{"x":"data:text/javascript,"}}<${''}/script><script nonce="${nonce}">import('x').then(()=>1,()=>0).then(v=>parent._$s(v))<${''}/script>`;
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
- processImportMaps();
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 (!supportsImportMaps) {
408
- const supports = HTMLScriptElement.supports || (type => type === 'classic' || type === 'module');
409
- HTMLScriptElement.supports = type => type === 'importmap' || supports(type);
410
- }
411
- if (shimMode || !baselinePassthrough) {
412
- new MutationObserver(mutations => {
413
- for (const mutation of mutations) {
414
- if (mutation.type !== 'childList') continue;
415
- for (const node of mutation.addedNodes) {
416
- if (node.tagName === 'SCRIPT') {
417
- if (node.type === (shimMode ? 'module-shim' : 'module'))
418
- processScript(node);
419
- if (node.type === (shimMode ? 'importmap-shim' : 'importmap'))
420
- processImportMap(node);
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
- }).observe(document, { childList: true, subtree: true });
427
- processImportMaps();
428
- processScriptsAndPreloads();
429
- if (document.readyState === 'complete') {
430
- readyStateCompleteCheck();
431
- }
432
- else {
433
- async function readyListener () {
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
- JSON.stringify((await res.text()).replace(cssUrlRegEx, (_match, quotes = '', relUrl1, relUrl2) => `url(${quotes}${resolveUrl(relUrl1 || relUrl2, url)}${quotes})`))
653
- });export default s;`, t: 'css' };
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
- document.addEventListener('DOMContentLoaded', async () => {
775
- await initPromise;
776
- domContentLoadedCheck();
777
- if (shimMode || !baselinePassthrough) {
778
- processImportMaps();
779
- processScriptsAndPreloads();
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.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
- if (!nonce) {
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 = document.baseURI;
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 => { (window.reportError || window.safari && console.error || eoop)(err), void onerror(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 supportsImportMeta = false;
275
- let supportsImportMaps = false;
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('import"data:text/css,{}"assert{type:"css"}')).then(() => supportsCssAssertions = true, noop),
287
- jsonModulesEnabled && dynamicImport(createBlob('import"data:text/json,{}"assert{type:"json"}')).then(() => supportsJsonAssertions = true, noop),
288
- HTMLScriptElement.supports ? supportsImportMaps = HTMLScriptElement.supports('importmap') : new Promise(resolve => {
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
- iframe.srcdoc = `<script type=importmap nonce="${nonce}">{"imports":{"x":"data:text/javascript,"}}<${''}/script><script nonce="${nonce}">import('x').then(()=>1,()=>0).then(v=>parent._$s(v))<${''}/script>`;
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
- processImportMaps();
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 (!supportsImportMaps) {
406
- const supports = HTMLScriptElement.supports || (type => type === 'classic' || type === 'module');
407
- HTMLScriptElement.supports = type => type === 'importmap' || supports(type);
408
- }
409
- if (shimMode || !baselinePassthrough) {
410
- new MutationObserver(mutations => {
411
- for (const mutation of mutations) {
412
- if (mutation.type !== 'childList') continue;
413
- for (const node of mutation.addedNodes) {
414
- if (node.tagName === 'SCRIPT') {
415
- if (node.type === (shimMode ? 'module-shim' : 'module'))
416
- processScript(node);
417
- if (node.type === (shimMode ? 'importmap-shim' : 'importmap'))
418
- processImportMap(node);
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
- }).observe(document, { childList: true, subtree: true });
425
- processImportMaps();
426
- processScriptsAndPreloads();
427
- if (document.readyState === 'complete') {
428
- readyStateCompleteCheck();
429
- }
430
- else {
431
- async function readyListener () {
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
- JSON.stringify((await res.text()).replace(cssUrlRegEx, (_match, quotes = '', relUrl1, relUrl2) => `url(${quotes}${resolveUrl(relUrl1 || relUrl2, url)}${quotes})`))
651
- });export default s;`, t: 'css' };
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
- document.addEventListener('DOMContentLoaded', async () => {
773
- await initPromise;
774
- domContentLoadedCheck();
775
- if (shimMode || !baselinePassthrough) {
776
- processImportMaps();
777
- processScriptsAndPreloads();
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: (id: string, parentUrl: string, resolve: (id: string, parentUrl: string) => string) => string | Promise<string>;
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "es-module-shims",
3
- "version": "1.5.5",
3
+ "version": "1.5.8",
4
4
  "description": "Shims for the latest ES module features",
5
5
  "main": "dist/es-module-shims.js",
6
6
  "exports": {