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 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.6/dist/es-module-shims.js"></script>
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:
@@ -1,14 +1,17 @@
1
- /* ES Module Shims 1.5.6 */
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
- 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,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('import"data:text/css,{}"assert{type:"css"}')).then(() => supportsCssAssertions = true, noop),
288
- jsonModulesEnabled && dynamicImport(createBlob('import"data:text/json,{}"assert{type:"json"}')).then(() => supportsJsonAssertions = true, noop),
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
- iframe.contentWindow.document.write(`<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>`);
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
- processImportMaps();
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 (!supportsImportMaps) {
410
- const supports = HTMLScriptElement.supports || (type => type === 'classic' || type === 'module');
411
- HTMLScriptElement.supports = type => type === 'importmap' || supports(type);
412
- }
413
- if (shimMode || !baselinePassthrough) {
414
- new MutationObserver(mutations => {
415
- for (const mutation of mutations) {
416
- if (mutation.type !== 'childList') continue;
417
- for (const node of mutation.addedNodes) {
418
- if (node.tagName === 'SCRIPT') {
419
- if (node.type === (shimMode ? 'module-shim' : 'module'))
420
- processScript(node);
421
- if (node.type === (shimMode ? 'importmap-shim' : 'importmap'))
422
- 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);
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
- }).observe(document, { childList: true, subtree: true });
429
- processImportMaps();
430
- processScriptsAndPreloads();
431
- if (document.readyState === 'complete') {
432
- readyStateCompleteCheck();
433
- }
434
- else {
435
- async function readyListener () {
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
- JSON.stringify((await res.text()).replace(cssUrlRegEx, (_match, quotes = '', relUrl1, relUrl2) => `url(${quotes}${resolveUrl(relUrl1 || relUrl2, url)}${quotes})`))
655
- });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' };
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
- document.addEventListener('DOMContentLoaded', async () => {
777
- await initPromise;
778
- domContentLoadedCheck();
779
- if (shimMode || !baselinePassthrough) {
780
- processImportMaps();
781
- processScriptsAndPreloads();
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.6 */
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
- 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,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('import"data:text/css,{}"assert{type:"css"}')).then(() => supportsCssAssertions = true, noop),
286
- jsonModulesEnabled && dynamicImport(createBlob('import"data:text/json,{}"assert{type:"json"}')).then(() => supportsJsonAssertions = true, noop),
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
- iframe.contentWindow.document.write(`<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>`);
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
- processImportMaps();
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 (!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);
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
- }).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);
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
- JSON.stringify((await res.text()).replace(cssUrlRegEx, (_match, quotes = '', relUrl1, relUrl2) => `url(${quotes}${resolveUrl(relUrl1 || relUrl2, url)}${quotes})`))
653
- });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' };
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
- document.addEventListener('DOMContentLoaded', async () => {
775
- await initPromise;
776
- domContentLoadedCheck();
777
- if (shimMode || !baselinePassthrough) {
778
- processImportMaps();
779
- processScriptsAndPreloads();
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: (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.6",
3
+ "version": "1.5.7",
4
4
  "description": "Shims for the latest ES module features",
5
5
  "main": "dist/es-module-shims.js",
6
6
  "exports": {