@remix-run/multiple-import-maps-polyfill 0.0.0 → 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,43 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 Remix Software Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ Portions of this software are derived from ES Module Shims:
24
+
25
+ Copyright (C) 2018-2025 Guy Bedford
26
+
27
+ Permission is hereby granted, free of charge, to any person obtaining a copy
28
+ of this software and associated documentation files (the "Software"), to deal
29
+ in the Software without restriction, including without limitation the rights
30
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
31
+ copies of the Software, and to permit persons to whom the Software is
32
+ furnished to do so, subject to the following conditions:
33
+
34
+ The above copyright notice and this permission notice shall be included in all
35
+ copies or substantial portions of the Software.
36
+
37
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
38
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
39
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
40
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
41
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
42
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
43
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,107 @@
1
1
  # multiple-import-maps-polyfill
2
2
 
3
- This package is a placeholder published at `0.0.0` to reserve the npm name and configure CI publishing.
3
+ Polyfill for dynamic JavaScript imports that depend on import maps added after the document's initial import map. Browsers with native support for multiple import maps continue to use native dynamic imports.
4
+
5
+ The module loading logic in this package was adapted from [ES Module Shims](https://github.com/guybedford/es-module-shims) by Guy Bedford.
6
+
7
+ This package assumes the initial document contains one complete import map before any module scripts. It is designed to load dynamic imports that depend on additional import maps installed after the initial page load.
8
+
9
+ ## Features
10
+
11
+ - Detects native support for multiple import maps
12
+ - Loads dynamic imports through every import map in the document when a polyfill is required
13
+ - Preloads dynamic modules through the same polyfill cache
14
+ - Resolves native module types through import maps while leaving their loading semantics to the browser
15
+ - Supports import-map integrity metadata
16
+
17
+ ## Installation
18
+
19
+ ```sh
20
+ npm i remix
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ Use `importModule` in place of `import()` when a dynamic import may depend on an import map added at runtime:
26
+
27
+ ```ts
28
+ import { importModule } from 'remix/multiple-import-maps-polyfill'
29
+
30
+ let moduleUrl = new URL('./features/search.ts', import.meta.url).href
31
+ let feature = await importModule(moduleUrl)
32
+ feature.openSearch()
33
+ ```
34
+
35
+ `importModule` uses native `import()` when the browser supports multiple import maps. In other browsers, it loads the module through the polyfill using every import map currently installed in the document.
36
+
37
+ Use `detectMultipleImportMapSupport` and `preloadShim` when an integration also manages module preloads. For example, configure Remix UI to load client entries discovered during navigation:
38
+
39
+ ```ts
40
+ import {
41
+ detectMultipleImportMapSupport,
42
+ importModule,
43
+ preloadShim,
44
+ } from 'remix/multiple-import-maps-polyfill'
45
+ import { run } from 'remix/ui'
46
+
47
+ run({
48
+ async loadModule(moduleUrl, exportName) {
49
+ let module = await importModule(moduleUrl)
50
+ let Component = module[exportName]
51
+ if (typeof Component !== 'function') {
52
+ throw new Error(`Unknown component: ${moduleUrl}#${exportName}`)
53
+ }
54
+ return Component
55
+ },
56
+ async processClientEntryPreloads(preloads) {
57
+ if (await detectMultipleImportMapSupport()) return preloads
58
+
59
+ preloadShim(preloads)
60
+ return []
61
+ },
62
+ })
63
+ ```
64
+
65
+ Browsers with multiple import map support retain native module loading and native `<link rel="modulepreload">` elements. Other browsers load late client entries and preloads through the polyfill.
66
+
67
+ `detectMultipleImportMapSupport()` returns a cached promise. When it detects that the polyfill is required, it begins loading the polyfill runtime in the background so the work can overlap with a later `importShim()` or `preloadShim()` call. Browsers with multiple import map support do not load the polyfill runtime.
68
+
69
+ `importShim()` always uses the polyfill to load a dynamic JavaScript import using every import map currently installed in the document. It does not detect native support. `preloadShim()` always uses the polyfill fetch cache rather than native module preload links. Like native module preloads, it fetches only the supplied module specifier or array of specifiers and caches their responses for later imports. Preload failures are ignored. `importShim()` reports the failure if the module is later required.
70
+
71
+ ## Content Security Policy
72
+
73
+ Polyfilled module graphs are evaluated from blob URLs, and `es-module-lexer` compiles its parser from Wasm. Content Security Policies must allow `blob:` module scripts and Wasm compilation with `'wasm-unsafe-eval'`.
74
+
75
+ The support detector creates a Trusted Types policy named `remix/multiple-import-maps-polyfill`. Allow this policy when Trusted Types are required for scripts, for example:
76
+
77
+ ```http
78
+ Content-Security-Policy: script-src 'self' blob: 'wasm-unsafe-eval'; require-trusted-types-for 'script'; trusted-types remix/multiple-import-maps-polyfill;
79
+ ```
80
+
81
+ ## `remix/assets` HMR Support
82
+
83
+ HMR appends mappings for updated modules to the document in additional `<script type="importmap">` elements. Configure the Remix asset server's `hmr.moduleImporter` option to use the polyfilled `importModule` function when these updates must work in browsers without native support for multiple import maps:
84
+
85
+ ```ts
86
+ import { createAssetServer } from 'remix/assets'
87
+ import { createBrowserHmrChannel } from 'remix/node-hmr/runtime'
88
+
89
+ let assets = createAssetServer({
90
+ hmr: {
91
+ channel: createBrowserHmrChannel,
92
+ moduleImporter: 'remix/multiple-import-maps-polyfill',
93
+ },
94
+ watch: true,
95
+ })
96
+ ```
97
+
98
+ The module importer and its dependencies must be available through the document's initial import map. Importing `remix/multiple-import-maps-polyfill` from the application's main client entry satisfies this requirement.
99
+
100
+ ## Related Packages
101
+
102
+ - [`assets`](https://github.com/remix-run/remix/tree/main/packages/assets) - Compiles and serves browser assets
103
+ - [`ui`](https://github.com/remix-run/remix/tree/main/packages/ui) - Loads client entries discovered during navigation
104
+
105
+ ## License
106
+
107
+ See [LICENSE](https://github.com/remix-run/remix/blob/main/packages/multiple-import-maps-polyfill/LICENSE)
@@ -0,0 +1,2 @@
1
+ export { detectMultipleImportMapSupport, importModule, importShim, preloadShim, } from './lib/polyfill.ts';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,YAAY,EACZ,UAAU,EACV,WAAW,GACZ,MAAM,mBAAmB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { detectMultipleImportMapSupport, importModule, importShim, preloadShim, } from './lib/polyfill.js';
@@ -0,0 +1,6 @@
1
+ type ModuleNamespace = Record<string, unknown>;
2
+ export declare function importShim(id: string, opts?: string | ImportCallOptions, parentUrl?: string): Promise<ModuleNamespace>;
3
+ export declare function preloadShim(ids: string | readonly string[], parentUrl?: string): Promise<void>;
4
+ export declare const registerNativeModule: (url: string) => void;
5
+ export {};
6
+ //# sourceMappingURL=core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/lib/core.ts"],"names":[],"mappings":"AA6BA,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AA2E9C,wBAAsB,UAAU,CAC9B,EAAE,EAAE,MAAM,EACV,IAAI,CAAC,EAAE,MAAM,GAAG,iBAAiB,EACjC,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,eAAe,CAAC,CAU1B;AAED,wBAAsB,WAAW,CAC/B,GAAG,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,EAC/B,SAAS,SAAc,GACtB,OAAO,CAAC,IAAI,CAAC,CASf;AAcD,eAAO,MAAM,oBAAoB,QAAS,MAAM,KAAG,IAElD,CAAA"}
@@ -0,0 +1,470 @@
1
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
+ });
6
+ }
7
+ return path;
8
+ };
9
+ import { resolveAndComposeImportMap, resolveImportMap, resolveIfNotPlainOrUrl, asURL, } from './resolve.js';
10
+ import { baseUrl as pageBaseUrl, dynamicImport, createBlob, throwError, fromParent, hasDocument, defaultFetchOpts, } from './env.js';
11
+ import { featureDetectionPromise, supportsImportMaps, supportsMultipleImportMaps, } from './features.js';
12
+ import * as lexer from 'es-module-lexer';
13
+ // This source is adapted from ES Module Shims 2.8.4.
14
+ const bridgeName = `remix.importMapPolyfill.runtime:${import.meta.url}`;
15
+ const bridgeKey = Symbol.for(bridgeName);
16
+ const bridgeExpression = `globalThis[Symbol.for(${JSON.stringify(bridgeName)})]`;
17
+ const resolve = (id, parentUrl = pageBaseUrl) => {
18
+ let urlResolved = resolveIfNotPlainOrUrl(id, parentUrl) || asURL(id);
19
+ let firstResolved = firstImportMap && resolveImportMap(firstImportMap, urlResolved || id, parentUrl);
20
+ let composedResolved = composedImportMap === firstImportMap
21
+ ? firstResolved
22
+ : resolveImportMap(composedImportMap, urlResolved || id, parentUrl);
23
+ let resolved = composedResolved || firstResolved || throwUnresolved(id, parentUrl);
24
+ // needsShim, shouldShim per load record to set on parent
25
+ let n = false, N = false;
26
+ if (!supportsMultipleImportMaps) {
27
+ // bare specifier and not resolved by first import map -> needs shim
28
+ if (!urlResolved && !firstResolved)
29
+ n = true;
30
+ // resolution doesn't match first import map -> should shim
31
+ if (firstResolved && resolved !== firstResolved)
32
+ N = true;
33
+ }
34
+ return { r: resolved, n, N };
35
+ };
36
+ // import()
37
+ export async function importShim(id, opts, parentUrl) {
38
+ if (typeof opts === 'string') {
39
+ parentUrl = opts;
40
+ opts = undefined;
41
+ }
42
+ let sourceType = opts?.with?.type;
43
+ await initPromise;
44
+ processImportMaps();
45
+ legacyAcceptingImportMaps = false;
46
+ return topLevelLoad(id, parentUrl || pageBaseUrl, defaultFetchOpts, undefined, sourceType);
47
+ }
48
+ export async function preloadShim(ids, parentUrl = pageBaseUrl) {
49
+ await initPromise;
50
+ processImportMaps();
51
+ await importMapPromise;
52
+ await Promise.allSettled((typeof ids === 'string' ? [ids] : ids).map((id) => processPreload(resolve(id, parentUrl).r, defaultFetchOpts)));
53
+ }
54
+ const throwUnresolved = (id, parentUrl) => {
55
+ throw Error(`Unable to resolve specifier '${id}'${fromParent(parentUrl)}`);
56
+ };
57
+ const metaResolve = function (id, parentUrl = this.url) {
58
+ return resolve(id, `${parentUrl}`).r;
59
+ };
60
+ const registry = {};
61
+ const nativeModules = new Set();
62
+ Reflect.set(globalThis, bridgeKey, Object.freeze({ importShim, registry }));
63
+ export const registerNativeModule = (url) => {
64
+ nativeModules.add(url);
65
+ };
66
+ const loadAll = async (load, seen) => {
67
+ seen[load.u] = 1;
68
+ await load.L;
69
+ await Promise.all(load.d.map(({ l: dep, s: sourcePhase }) => {
70
+ if (dep.b || seen[dep.u])
71
+ return;
72
+ if (sourcePhase)
73
+ return dep.f;
74
+ return loadAll(dep, seen);
75
+ }));
76
+ };
77
+ let firstImportMap = null;
78
+ // To support polyfilling multiple import maps, we separately track the composed import map from the first import map
79
+ let composedImportMap = { imports: {}, scopes: {}, integrity: {} };
80
+ const initPromise = Promise.all([lexer.init, featureDetectionPromise]).then(() => {
81
+ if (!hasDocument || !supportsImportMaps)
82
+ throw new TypeError('The multiple import map polyfill requires native import map support.');
83
+ attachMutationObserver();
84
+ });
85
+ const attachMutationObserver = () => {
86
+ let observer = new MutationObserver((mutations) => {
87
+ for (let mutation of mutations) {
88
+ if (mutation.type !== 'childList')
89
+ continue;
90
+ for (let node of mutation.addedNodes) {
91
+ if (node.tagName === 'SCRIPT') {
92
+ let script = node;
93
+ if (script.type === 'importmap')
94
+ processImportMap(script);
95
+ }
96
+ }
97
+ }
98
+ });
99
+ observer.observe(document, { childList: true });
100
+ observer.observe(document.head, { childList: true });
101
+ processImportMaps();
102
+ };
103
+ let importMapPromise = initPromise;
104
+ let legacyAcceptingImportMaps = true;
105
+ async function topLevelLoad(url, parentUrl, fetchOpts, source, sourceType) {
106
+ await initPromise;
107
+ await importMapPromise;
108
+ url = (await resolve(url, parentUrl)).r;
109
+ // we mock import('./x.css', { with: { type: 'css' }}) support via an inline static reexport
110
+ // because we can't syntactically pass through to dynamic import with a second argument
111
+ if (sourceType === 'css' || sourceType === 'json') {
112
+ // Direct reexport for hot reloading skipped due to Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=1965620
113
+ source = `import m from'${url}'with{type:"${sourceType}"};export default m;`;
114
+ url += '?entry';
115
+ }
116
+ let load = getOrCreateLoad(url, fetchOpts, undefined, source);
117
+ if (source)
118
+ load.N = true;
119
+ linkLoad(load, fetchOpts);
120
+ let seen = {};
121
+ await loadAll(load, seen);
122
+ resolveDeps(load, seen);
123
+ let module = await (load.n || load.N ? dynamicImport(load.b) : import(__rewriteRelativeImportExtension(load.u)));
124
+ // if the top-level load is a shell, run its update function
125
+ if (load.s)
126
+ (await dynamicImport(load.s)).u$_(module);
127
+ revokeObjectURLs(Object.keys(seen));
128
+ return module;
129
+ }
130
+ const revokeObjectURLs = (registryKeys) => {
131
+ let curIdx = 0;
132
+ let handler = globalThis.requestIdleCallback ||
133
+ globalThis.requestAnimationFrame ||
134
+ ((fn) => setTimeout(fn, 0));
135
+ handler(cleanup);
136
+ function cleanup() {
137
+ for (let key of registryKeys.slice(curIdx, (curIdx += 100))) {
138
+ let load = registry[key];
139
+ if (load && load.b && load.b !== load.u)
140
+ URL.revokeObjectURL(load.b);
141
+ }
142
+ if (curIdx < registryKeys.length)
143
+ handler(cleanup);
144
+ }
145
+ };
146
+ const urlJsString = (url) => `'${url.replace(/'/g, "\\'")}'`;
147
+ let resolvedSource = '';
148
+ let lastIndex = 0;
149
+ const pushStringTo = (load, originalIndex, dynamicImportEndStack) => {
150
+ while (dynamicImportEndStack[dynamicImportEndStack.length - 1] < originalIndex) {
151
+ let dynamicImportEnd = dynamicImportEndStack.pop();
152
+ resolvedSource += `${load.S.slice(lastIndex, dynamicImportEnd)}, ${urlJsString(load.r)}`;
153
+ lastIndex = dynamicImportEnd;
154
+ }
155
+ resolvedSource += load.S.slice(lastIndex, originalIndex);
156
+ lastIndex = originalIndex;
157
+ };
158
+ const pushSourceURL = (load, commentPrefix, commentStart, dynamicImportEndStack) => {
159
+ let urlStart = commentStart + commentPrefix.length;
160
+ let commentEnd = load.S.indexOf('\n', urlStart);
161
+ let urlEnd = commentEnd !== -1 ? commentEnd : load.S.length;
162
+ let sourceUrl = load.S.slice(urlStart, urlEnd);
163
+ try {
164
+ sourceUrl = new URL(sourceUrl, load.r).href;
165
+ }
166
+ catch (e) { }
167
+ pushStringTo(load, urlStart, dynamicImportEndStack);
168
+ resolvedSource += sourceUrl;
169
+ lastIndex = urlEnd;
170
+ };
171
+ const resolveDeps = (load, seen) => {
172
+ if (load.b || !seen[load.u])
173
+ return;
174
+ seen[load.u] = 0;
175
+ for (let { l: dep, s: sourcePhase } of load.d) {
176
+ if (!sourcePhase && !dep.b) {
177
+ resolveDeps(dep, seen);
178
+ }
179
+ }
180
+ if (!load.n)
181
+ load.n = load.d.some((dep) => dep.l.n);
182
+ if (!load.N)
183
+ load.N = load.d.some((dep) => dep.l.N);
184
+ // use native loader whenever possible (n = needs shim) via executable subgraph passthrough
185
+ // so long as the module doesn't use dynamic import or unsupported URL mappings (N = should shim)
186
+ if (!load.n && !load.N) {
187
+ load.b = load.u;
188
+ load.S = undefined;
189
+ return;
190
+ }
191
+ let [imports, exports] = load.a;
192
+ // "execution"
193
+ let source = load.S, depIndex = 0, dynamicImportEndStack = [];
194
+ // once all deps have loaded we can inline the dependency resolution blobs
195
+ // and define this blob
196
+ resolvedSource = '';
197
+ lastIndex = 0;
198
+ for (let { s: start, e: end, ss: statementStart, se: statementEnd, d: dynamicImportIndex, t, a, } of imports) {
199
+ // source phase
200
+ if (t === 4) {
201
+ let { l: depLoad } = load.d[depIndex++];
202
+ pushStringTo(load, start - 1, dynamicImportEndStack);
203
+ resolvedSource += `/*${source.slice(start - 1, end + 1)}*/'${depLoad.b}'`;
204
+ lastIndex = end + 1;
205
+ }
206
+ else if (t === 5 || t === 6) {
207
+ throw new TypeError('Dynamic source imports and import defer are not supported.');
208
+ }
209
+ // dependency source replacements
210
+ else if (dynamicImportIndex === -1) {
211
+ let keepAssertion = a > 0;
212
+ let { l: depLoad } = load.d[depIndex++], blobUrl = depLoad.b, cycleShell = !blobUrl;
213
+ if (cycleShell) {
214
+ let cycleLoad = depLoad;
215
+ // circular shell creation
216
+ if (!(blobUrl = cycleLoad.s)) {
217
+ blobUrl = cycleLoad.s = createBlob(`export function u$_(m){${cycleLoad.a[1]
218
+ .map(({ s, e }, i) => {
219
+ let depSource = cycleLoad.S;
220
+ let q = depSource[s] === '"' || depSource[s] === "'";
221
+ return `e$_${i}=m${q ? `[` : '.'}${depSource.slice(s, e)}${q ? `]` : ''}`;
222
+ })
223
+ .join(',')}}${cycleLoad.a[1].length
224
+ ? `let ${cycleLoad.a[1].map((_, i) => `e$_${i}`).join(',')};`
225
+ : ''}export {${cycleLoad.a[1]
226
+ .map(({ s, e }, i) => `e$_${i} as ${cycleLoad.S.slice(s, e)}`)
227
+ .join(',')}}\n//# sourceURL=${cycleLoad.r}?cycle`);
228
+ }
229
+ }
230
+ pushStringTo(load, start - 1, dynamicImportEndStack);
231
+ resolvedSource += `/*${source.slice(start - 1, end + 1)}*/'${blobUrl}'`;
232
+ // circular shell execution
233
+ if (!cycleShell && depLoad.s) {
234
+ resolvedSource += `;import*as m$_${depIndex} from'${depLoad.b}';import{u$_ as u$_${depIndex}}from'${depLoad.s}';u$_${depIndex}(m$_${depIndex})`;
235
+ depLoad.s = undefined;
236
+ }
237
+ lastIndex = keepAssertion ? end + 1 : statementEnd;
238
+ }
239
+ // import.meta
240
+ else if (dynamicImportIndex === -2) {
241
+ load.m = { url: load.r, resolve: metaResolve };
242
+ pushStringTo(load, start, dynamicImportEndStack);
243
+ resolvedSource += `${bridgeExpression}.registry[${urlJsString(load.u)}].m`;
244
+ lastIndex = statementEnd;
245
+ }
246
+ // dynamic import
247
+ else {
248
+ pushStringTo(load, statementStart, dynamicImportEndStack);
249
+ resolvedSource += `${bridgeExpression}.importShim(`;
250
+ dynamicImportEndStack.push(statementEnd - 1);
251
+ lastIndex = start;
252
+ }
253
+ }
254
+ // support progressive cycle binding updates (try statement avoids tdz errors)
255
+ if (load.s && (imports.length === 0 || imports[imports.length - 1].d === -1))
256
+ resolvedSource += `\n;import{u$_}from'${load.s}';try{u$_({${exports
257
+ .filter((e) => e.ln)
258
+ .map(({ s, e, ln }) => `${source.slice(s, e)}:${ln}`)
259
+ .join(',')}})}catch(_){};\n`;
260
+ let sourceURLCommentStart = source.lastIndexOf(sourceURLCommentPrefix);
261
+ let sourceMapURLCommentStart = source.lastIndexOf(sourceMapURLCommentPrefix);
262
+ // ignore sourceMap comments before already spliced code
263
+ if (sourceURLCommentStart < lastIndex)
264
+ sourceURLCommentStart = -1;
265
+ if (sourceMapURLCommentStart < lastIndex)
266
+ sourceMapURLCommentStart = -1;
267
+ // sourceURL first / only
268
+ if (sourceURLCommentStart !== -1 &&
269
+ (sourceMapURLCommentStart === -1 || sourceMapURLCommentStart > sourceURLCommentStart)) {
270
+ pushSourceURL(load, sourceURLCommentPrefix, sourceURLCommentStart, dynamicImportEndStack);
271
+ }
272
+ // sourceMappingURL
273
+ if (sourceMapURLCommentStart !== -1) {
274
+ pushSourceURL(load, sourceMapURLCommentPrefix, sourceMapURLCommentStart, dynamicImportEndStack);
275
+ // sourceURL last
276
+ if (sourceURLCommentStart !== -1 && sourceURLCommentStart > sourceMapURLCommentStart)
277
+ pushSourceURL(load, sourceURLCommentPrefix, sourceURLCommentStart, dynamicImportEndStack);
278
+ }
279
+ pushStringTo(load, source.length, dynamicImportEndStack);
280
+ if (sourceURLCommentStart === -1)
281
+ resolvedSource += sourceURLCommentPrefix + load.r;
282
+ load.b = createBlob(resolvedSource);
283
+ load.S = undefined;
284
+ resolvedSource = '';
285
+ };
286
+ const sourceURLCommentPrefix = '\n//# sourceURL=';
287
+ const sourceMapURLCommentPrefix = '\n//# sourceMappingURL=';
288
+ // restrict in-flight fetches to a pool of 100
289
+ const p = [];
290
+ let c = 0;
291
+ const pushFetchPool = () => {
292
+ if (++c > 100)
293
+ return new Promise((resolve) => p.push(resolve));
294
+ };
295
+ const popFetchPool = () => {
296
+ c--;
297
+ let next = p.shift();
298
+ if (next)
299
+ next();
300
+ };
301
+ const doFetch = async (url, fetchOpts, parent) => {
302
+ let res, poolQueue = pushFetchPool();
303
+ if (poolQueue)
304
+ await poolQueue;
305
+ try {
306
+ res = await fetch(url, fetchOpts);
307
+ }
308
+ catch (e) {
309
+ let error = e;
310
+ error.message =
311
+ `Unable to fetch ${url}${fromParent(parent)} - see network log for details.\n` + error.message;
312
+ throw error;
313
+ }
314
+ finally {
315
+ popFetchPool();
316
+ }
317
+ if (!res.ok) {
318
+ throw Object.assign(new TypeError(`${res.status} ${res.statusText} ${res.url}${fromParent(parent)}`), { response: res });
319
+ }
320
+ return res;
321
+ };
322
+ async function defaultSourceHook(url, fetchOpts, parent) {
323
+ let res = await doFetch(url, fetchOpts, parent), contentType = res.headers.get('Content-Type') || '';
324
+ if (!/^(?:text|application)\/(?:x-)?(?:java|type)script(?:;|$)/i.test(contentType)) {
325
+ throw Error(`Unsupported Content-Type "${contentType}" loading ${url}${fromParent(parent)}. Only JavaScript modules are supported and must be served with a valid MIME type like application/javascript.`);
326
+ }
327
+ return { url: res.url, source: await res.text() };
328
+ }
329
+ const fetchModule = async (reqUrl, fetchOpts, parent) => {
330
+ let mapIntegrity = composedImportMap.integrity[reqUrl];
331
+ fetchOpts =
332
+ mapIntegrity && !fetchOpts.integrity ? { ...fetchOpts, integrity: mapIntegrity } : fetchOpts;
333
+ let { url = reqUrl, source } = await defaultSourceHook(reqUrl, fetchOpts, parent);
334
+ return { url, source };
335
+ };
336
+ const getOrCreateLoad = (url, fetchOpts, parent, source) => {
337
+ if (source && registry[url]) {
338
+ let i = 0;
339
+ while (registry[url + '#' + ++i]) { }
340
+ url += '#' + i;
341
+ }
342
+ let load = registry[url];
343
+ if (load)
344
+ return load;
345
+ registry[url] = load = {
346
+ // url
347
+ u: url,
348
+ // response url
349
+ r: source ? url : undefined,
350
+ // fetchPromise
351
+ f: undefined,
352
+ // source
353
+ S: source,
354
+ // linkPromise
355
+ L: undefined,
356
+ // analysis
357
+ a: undefined,
358
+ // deps
359
+ d: undefined,
360
+ // blobUrl
361
+ b: undefined,
362
+ // shellUrl
363
+ s: undefined,
364
+ // needsShim: does it fail execution in the current native loader?
365
+ n: false,
366
+ // shouldShim: does it need to be loaded by the polyfill loader?
367
+ N: false,
368
+ // meta
369
+ m: null,
370
+ };
371
+ load.f = (async () => {
372
+ if (load.S === undefined) {
373
+ // preload fetch options override fetch options (race)
374
+ ;
375
+ ({ url: load.r, source: load.S } = await (fetchCache[url] ||
376
+ fetchModule(url, fetchOpts, parent)));
377
+ }
378
+ try {
379
+ load.a = lexer.parse(load.S, load.u);
380
+ }
381
+ catch (e) {
382
+ throwError(e);
383
+ load.a = [[], [], false, false];
384
+ }
385
+ return load;
386
+ })();
387
+ return load;
388
+ };
389
+ const linkLoad = (load, fetchOpts) => {
390
+ if (load.L)
391
+ return;
392
+ load.L = load.f.then(() => {
393
+ let childFetchOpts = fetchOpts;
394
+ let dependencies = load.a[0].map(({ n, d, t, a, se }) => {
395
+ let phaseImport = t >= 4;
396
+ let sourcePhase = phaseImport && t < 6;
397
+ if (phaseImport && t !== 4)
398
+ throw new TypeError('Dynamic source imports and import defer are not supported.');
399
+ // Unlike ESMS's automatic polyfill mode, this explicit loader must retain control of nested
400
+ // dynamic imports even when the currently linked graph can otherwise pass through natively.
401
+ if (d >= 0) {
402
+ load.N = true;
403
+ return;
404
+ }
405
+ if (d !== -1 || !n)
406
+ return;
407
+ let resolved = resolve(n, load.r || load.u);
408
+ if (resolved.n)
409
+ load.n = true;
410
+ if (resolved.N)
411
+ load.N = true;
412
+ let source = sourcePhase ? '' : undefined;
413
+ if (a > 0) {
414
+ let assertion = load.S.slice(a, se - 1);
415
+ // no need to fetch JSON/CSS if supported, since it's a leaf node, we'll just strip the assertion syntax
416
+ if (assertion.includes('json') || assertion.includes('css'))
417
+ source = '';
418
+ }
419
+ // The ESM wrapper lazily imports this core. Loading the wrapper through the core would
420
+ // recurse and create a second copy of modules that import the wrapper.
421
+ if (nativeModules.has(resolved.r))
422
+ return { l: { u: resolved.r, b: resolved.r }, s: false };
423
+ if (childFetchOpts.integrity)
424
+ childFetchOpts = { ...childFetchOpts, integrity: undefined };
425
+ let child = {
426
+ l: getOrCreateLoad(resolved.r, childFetchOpts, load.r, source),
427
+ s: sourcePhase,
428
+ };
429
+ // assertion case -> inline the CSS / JSON URL directly
430
+ if (source === '')
431
+ child.l.b = child.l.u;
432
+ if (!child.s)
433
+ linkLoad(child.l, fetchOpts);
434
+ // load, sourcePhase
435
+ return child;
436
+ });
437
+ load.d = dependencies.filter((dependency) => dependency !== undefined);
438
+ });
439
+ };
440
+ const processedImportMaps = new WeakSet();
441
+ const processImportMaps = () => {
442
+ for (let script of document.querySelectorAll('script[type=importmap]'))
443
+ processImportMap(script);
444
+ };
445
+ const processImportMap = (script) => {
446
+ if (processedImportMaps.has(script))
447
+ return;
448
+ processedImportMaps.add(script);
449
+ // we dont currently support external import maps in polyfill mode to match native
450
+ if (script.src)
451
+ return;
452
+ importMapPromise = importMapPromise
453
+ .then(() => {
454
+ composedImportMap = resolveAndComposeImportMap(JSON.parse(script.innerHTML), pageBaseUrl, composedImportMap);
455
+ })
456
+ .catch((e) => {
457
+ if (e instanceof SyntaxError)
458
+ e = new Error(`Unable to parse import map ${e.message} in: ${script.innerHTML}`);
459
+ throwError(e);
460
+ });
461
+ if (!firstImportMap && legacyAcceptingImportMaps)
462
+ importMapPromise.then(() => (firstImportMap = composedImportMap));
463
+ legacyAcceptingImportMaps = false;
464
+ };
465
+ const fetchCache = {};
466
+ const processPreload = (url, fetchOpts) => initPromise.then(() => {
467
+ if (fetchCache[url])
468
+ return fetchCache[url];
469
+ return (fetchCache[url] = fetchModule(url, fetchOpts));
470
+ });
@@ -0,0 +1,12 @@
1
+ export declare const hasDocument: boolean;
2
+ export declare const dynamicImport: (u: string) => Promise<Record<string, unknown>>;
3
+ export declare const defaultFetchOpts: {
4
+ credentials: "same-origin";
5
+ };
6
+ export declare const version: string;
7
+ export declare let nonce: string;
8
+ export declare const baseUrl: string;
9
+ export declare const createBlob: (source: string) => string;
10
+ export declare const throwError: (err: unknown) => void;
11
+ export declare const fromParent: (parent?: string) => string;
12
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/lib/env.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,SAAkC,CAAA;AAE1D,eAAO,MAAM,aAAa,MAAO,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAc,CAAA;AAEvF,eAAO,MAAM,gBAAgB;;CAAuD,CAAA;AAEpF,eAAO,MAAM,OAAO,QAAuE,CAAA;AAE3F,eAAO,IAAI,KAAK,QAAK,CAAA;AAMrB,eAAO,MAAM,OAAO,QAQD,CAAA;AAEnB,eAAO,MAAM,UAAU,WAAY,MAAM,KAAG,MAC0B,CAAA;AAKtE,eAAO,MAAM,UAAU,QAAS,OAAO,KAAG,IAEzC,CAAA;AAED,eAAO,MAAM,UAAU,YAAa,MAAM,KAAG,MAAoD,CAAA"}