es-module-shims 1.5.18 → 1.6.1

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.18/dist/es-module-shims.js"></script>
32
+ <script async src="https://ga.jspm.io/npm:es-module-shims@1.6.1/dist/es-module-shims.js"></script>
33
33
 
34
34
  <!-- https://generator.jspm.io/#U2NhYGBkDM0rySzJSU1hKEpNTC5xMLTQM9Az0C1K1jMAAKFS5w0gAA -->
35
35
  <script type="importmap">
@@ -62,21 +62,15 @@ This execution failure is a feature - it avoids the polyfill causing double exec
62
62
 
63
63
  This is because the polyfill cannot disable the native loader - instead it will only execute modules that would otherwise fail resolving or parsing to avoid duplicate fetches or executions that would cause performance and reliability issues.
64
64
 
65
- ### Shim Mode
65
+ ## Polyfill Mode
66
66
 
67
- Shim mode is an alternative to polyfill mode and doesn't rely on native modules erroring - instead it is triggered by the existence of any `<script type="importmap-shim">` or `<script type="module-shim">`, or when explicitly setting the [`shimMode` init option](#shim-mode-option).
68
-
69
- In shim mode, only the above `importmap-shim` and `module-shim` tags will be parsed and executed by ES Module Shims.
70
-
71
- Shim mode also provides some additional features that aren't yet natively supported such as supporting multiple import maps, [external import maps](#external-import-maps) with a `"src"` attribute, [dynamically injecting import maps](#dynamic-import-maps), and [reading current import map state](#reading-current-import-map-state), which can be useful in certain applications.
72
-
73
- ## Polyfill Mode Details
67
+ The typical polyfill scenario is to have a static import to a bare specifier fail, which will then be polyfilled by ES Module Shims.
74
68
 
75
69
  In polyfill mode, feature detections are performed for ES modules features. In browsers with full feature support no further processing is done.
76
70
 
77
71
  In browsers with variable feature support, sources are analyzed with module specifiers rewritten using the very fast Wasm / asm.js lexer while sharing the source network fetch cache with the native loader.
78
72
 
79
- #### Polyfill Features
73
+ ### Polyfill Features
80
74
 
81
75
  The current default native baseline for the ES module shims polyfill mode is browsers supporting import maps.
82
76
 
@@ -90,9 +84,9 @@ window.esmsInitOptions = { polyfillEnable: ['css-modules', 'json-modules'] }
90
84
 
91
85
  To verify when the polyfill is actively engaging as opposed to relying on the native loader, [a `polyfill` hook](#polyfill-hook) is also provided.
92
86
 
93
- #### Polyfill Edge Case: Dynamic Import
87
+ ### Polyfill Edge Case: Dynamic Import
94
88
 
95
- The guarantee of the polyfill is that any module graph that would have failed will be reexecuted through the shim layer. This leaves any edge case where execution succeeds but not as expected. For example when using dynamic imports:
89
+ Module feature errors that are not _static errors_ but rather _runtime errors_ cause edge cases with the polyfill feature detection. For example when using dynamic imports:
96
90
 
97
91
  ```html
98
92
  <script type="module">
@@ -130,11 +124,11 @@ If a static failure is not possible and dynamic import must be used, rather use
130
124
 
131
125
  `importShim` will automatically pass-through to native dynamic import or polyfill as necessary, just like it does for script tags.
132
126
 
133
- #### Polyfill Edge Case: Instance Sharing
127
+ ### Polyfill Edge Case: Instance Sharing
134
128
 
135
129
  When running in polyfill mode, it can be thought of that are effectively two loaders running on the page - the ES Module Shims polyfill loader, and the native loader.
136
130
 
137
- Note that instances are not shared between these loaders for consistency and performance.
131
+ Note that instances are not shared between these loaders for consistency and performance, since some browsers do not properly share the fetch cache and native loader cache resulting in a double fetch which would be inefficient.
138
132
 
139
133
  As a result, if you have two module graphs - one native and one polyfilled, they will not share the same dependency instance, for example:
140
134
 
@@ -154,15 +148,29 @@ import 'dep';
154
148
  </script>
155
149
  ```
156
150
 
157
- In the above, on browsers without import maps support, the `/dep.js` instance will be loaded natively by the first module, then the second import will fail.
151
+ ```dep
152
+ console.log('DEP');
153
+ ```
158
154
 
159
- ES Module Shims will pick up on the second import and reexecute `/dep.js`. As a result, `/dep.js` will be executed twice on the page.
155
+ When polyfilling import maps, ES Module Shims will pick up on the second import failure and reexecute `/dep.js` as a new instance, logging `"DEP"` twice.
160
156
 
161
157
  For this reason it is important to always ensure all modules hit the polyfill path, either by having all graphs use import maps at the top-level, or via `importShim` directly.
162
158
 
163
- #### Skip Polyfill
159
+ If you really need to support instance sharing with the native loader, a useful workaround is to use the [`skip` option](#skip) to list modules which should always be loaded via the native loader:
160
+
161
+ ```html
162
+ <script type="esms-options">
163
+ {
164
+ "skip": ["/dep.js"]
165
+ }
166
+ </script>
167
+ ```
168
+
169
+ The above would then fully cause dependency module instance to be shared between ES Module Shims and the native loader, with the polyfill then logging `"DEP"` only once.
170
+
171
+ #### No Shim Scripts
164
172
 
165
- Adding the `"noshim"` attribute to the script tag will also ensure that ES Module Shims skips processing this script entirely:
173
+ If the polyfill is analyzing or applying to a module script that doesn't need to or shouldn't be polyfilled, adding the `"noshim"` attribute to the script tag will ensure that ES Module Shims ignores processing this script entirely:
166
174
 
167
175
  ```html
168
176
  <script type="module" noshim>
@@ -170,6 +178,14 @@ Adding the `"noshim"` attribute to the script tag will also ensure that ES Modul
170
178
  </script>
171
179
  ```
172
180
 
181
+ ## Shim Mode
182
+
183
+ Shim mode is an alternative to polyfill mode and doesn't rely on native modules erroring - instead it is triggered by the existence of any `<script type="importmap-shim">` or `<script type="module-shim">`, or when explicitly setting the [`shimMode` init option](#shim-mode-option).
184
+
185
+ In shim mode, only the above `importmap-shim` and `module-shim` tags will be parsed and executed by ES Module Shims.
186
+
187
+ Shim mode also provides some additional features that aren't yet natively supported such as supporting multiple import maps, [external import maps](#external-import-maps) with a `"src"` attribute, [dynamically injecting import maps](#dynamic-import-maps), and [reading current import map state](#reading-current-import-map-state), which can be useful in certain applications.
188
+
173
189
  ## Benchmarks
174
190
 
175
191
  ES Module Shims is designed for production performance. A [comprehensive benchmark suite](bench/README.md) tracks multiple loading scenarios for the project.
@@ -469,7 +485,7 @@ Provide a `esmsInitOptions` on the global scope before `es-module-shims` is load
469
485
  * [enforceIntegrity](#enforce-integrity)
470
486
  * [nonce](#nonce)
471
487
  * [noLoadEventRetriggers](#no-load-event-retriggers)
472
- * [skip](#skip-processing)
488
+ * [skip](#skip)
473
489
  * [onerror](#error-hook)
474
490
  * [onpolyfill](#polyfill-hook)
475
491
  * [resolve](#resolve-hook)
@@ -622,16 +638,27 @@ In such a case, this double event firing can be disabled with the `noLoadEventRe
622
638
  <script async src="es-module-shims.js"></script>
623
639
  ```
624
640
 
625
- ### Skip Processing
641
+ ### Skip
642
+
643
+ When loading modules that you know will only use baseline modules features, it is possible to set a rule to explicitly opt-out modules from being polyfilled to always load and be referenced through the native loader only. This enables instance sharing with the native loader and also improves performance because those modules then do not need to be processed or transformed at all, so that only local application code is handled and not library code.
626
644
 
627
- When loading modules that you know will only use baseline modules features, it is possible to set a rule to explicitly opt-out modules from rewriting. This improves performance because those modules then do not need to be processed or transformed at all, so that only local application code is handled and not library code.
645
+ The `skip` option supports a string regular expression or array of exact module URLs to check:
646
+
647
+ ```js
648
+ <script type="esms-options">
649
+ {
650
+ "skip": "^https?:\/\/(cdn\.skypack\.dev|jspm\.dev)\/"
651
+ }
652
+ </script>
653
+ <script async src="es-module-shims.js"></script>
654
+ ```
628
655
 
629
- This can be configured by providing a URL regular expression for the `skip` option:
656
+ When passing an array, relative URLs or paths ending in `/` can be provided:
630
657
 
631
658
  ```js
632
659
  <script type="esms-options">
633
660
  {
634
- "skip": "/^https?:\/\/(cdn\.skypack\.dev|jspm\.dev)\//"
661
+ "skip": ["./app.js", "https://jspm.dev/"]
635
662
  }
636
663
  </script>
637
664
  <script async src="es-module-shims.js"></script>
@@ -1,4 +1,4 @@
1
- /* ES Module Shims 1.5.18 */
1
+ /* ES Module Shims 1.6.1 */
2
2
  (function () {
3
3
 
4
4
  const hasWindow = typeof window !== 'undefined';
@@ -18,8 +18,6 @@
18
18
  let fetchHook = esmsInitOptions.fetch ? globalHook(esmsInitOptions.fetch) : fetch;
19
19
  const metaHook = esmsInitOptions.meta ? globalHook(shimMode && esmsInitOptions.meta) : noop;
20
20
 
21
- const skip = esmsInitOptions.skip ? new RegExp(esmsInitOptions.skip) : null;
22
-
23
21
  const mapOverrides = esmsInitOptions.mapOverrides;
24
22
 
25
23
  let nonce = esmsInitOptions.nonce;
@@ -53,6 +51,15 @@
53
51
  : location.pathname}`;
54
52
 
55
53
  const createBlob = (source, type = 'text/javascript') => URL.createObjectURL(new Blob([source], { type }));
54
+ let { skip } = esmsInitOptions;
55
+ if (Array.isArray(skip)) {
56
+ const l = skip.map(s => new URL(s, baseUrl).href);
57
+ skip = s => l.some(i => i[i.length - 1] === '/' && s.startsWith(i) || s === i);
58
+ }
59
+ else if (typeof skip === 'string') {
60
+ const r = new RegExp(skip);
61
+ skip = s => r.test(s);
62
+ }
56
63
 
57
64
  const eoop = err => setTimeout(() => { throw err });
58
65
 
@@ -778,7 +785,8 @@
778
785
  const { r, b } = await resolve(n, load.r || load.u);
779
786
  if (b && (!supportsImportMaps || importMapSrcOrLazy))
780
787
  load.n = true;
781
- if (skip && skip.test(r)) return { b: r };
788
+ if (d !== -1) return;
789
+ if (skip && skip(r)) return { b: r };
782
790
  if (childFetchOpts.integrity)
783
791
  childFetchOpts = Object.assign({}, childFetchOpts, { integrity: undefined });
784
792
  return getOrCreateLoad(r, childFetchOpts, load.r).f;
@@ -1,4 +1,4 @@
1
- /* ES Module Shims Wasm 1.5.18 */
1
+ /* ES Module Shims Wasm 1.6.1 */
2
2
  (function () {
3
3
 
4
4
  const hasWindow = typeof window !== 'undefined';
@@ -18,8 +18,6 @@
18
18
  let fetchHook = esmsInitOptions.fetch ? globalHook(esmsInitOptions.fetch) : fetch;
19
19
  const metaHook = esmsInitOptions.meta ? globalHook(shimMode && esmsInitOptions.meta) : noop;
20
20
 
21
- const skip = esmsInitOptions.skip ? new RegExp(esmsInitOptions.skip) : null;
22
-
23
21
  const mapOverrides = esmsInitOptions.mapOverrides;
24
22
 
25
23
  let nonce = esmsInitOptions.nonce;
@@ -53,6 +51,15 @@
53
51
  : location.pathname}`;
54
52
 
55
53
  const createBlob = (source, type = 'text/javascript') => URL.createObjectURL(new Blob([source], { type }));
54
+ let { skip } = esmsInitOptions;
55
+ if (Array.isArray(skip)) {
56
+ const l = skip.map(s => new URL(s, baseUrl).href);
57
+ skip = s => l.some(i => i[i.length - 1] === '/' && s.startsWith(i) || s === i);
58
+ }
59
+ else if (typeof skip === 'string') {
60
+ const r = new RegExp(skip);
61
+ skip = s => r.test(s);
62
+ }
56
63
 
57
64
  const eoop = err => setTimeout(() => { throw err });
58
65
 
@@ -778,7 +785,8 @@
778
785
  const { r, b } = await resolve(n, load.r || load.u);
779
786
  if (b && (!supportsImportMaps || importMapSrcOrLazy))
780
787
  load.n = true;
781
- if (skip && skip.test(r)) return { b: r };
788
+ if (d !== -1) return;
789
+ if (skip && skip(r)) return { b: r };
782
790
  if (childFetchOpts.integrity)
783
791
  childFetchOpts = Object.assign({}, childFetchOpts, { integrity: undefined });
784
792
  return getOrCreateLoad(r, childFetchOpts, load.r).f;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "es-module-shims",
3
- "version": "1.5.18",
3
+ "version": "1.6.1",
4
4
  "description": "Shims for the latest ES module features",
5
5
  "main": "dist/es-module-shims.js",
6
6
  "exports": {
@@ -36,8 +36,8 @@
36
36
  "test": "test"
37
37
  },
38
38
  "scripts": {
39
- "build": "cargo install chompbuild ; chomp build",
40
- "test": "cargo install chompbuild ; chomp test"
39
+ "build": "npm install -g chomp ; chomp build",
40
+ "test": "npm install -g chomp ; chomp test"
41
41
  },
42
42
  "repository": {
43
43
  "type": "git",