Skip to content

Commit d649ec5

Browse files
author
David Heinemeier Hansson
committed
ES Module Shims 1.4.0
1 parent bd193b3 commit d649ec5

File tree

3 files changed

+41
-41
lines changed

3 files changed

+41
-41
lines changed

app/assets/javascripts/es-module-shims.js

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* ES Module Shims 1.3.6 */
1+
/* ES Module Shims 1.4.0 */
22
(function () {
33

44
const edge = navigator.userAgent.match(/Edge\/\d\d\.\d+$/);
@@ -130,17 +130,17 @@
130130
for (let p in packages) {
131131
const resolvedLhs = resolveIfNotPlainOrUrl(p, baseUrl) || p;
132132
if (outPackages[resolvedLhs]) {
133-
throw new Error(`Dynamic import map rejected: Overrides entry "${resolvedLhs}" from ${outPackages[resolvedLhs]} to ${packages[resolvedLhs]}.`);
133+
throw Error(`Rejected map override "${resolvedLhs}" from ${outPackages[resolvedLhs]} to ${packages[resolvedLhs]}.`);
134134
}
135135
let target = packages[p];
136-
if (typeof target !== 'string')
136+
if (typeof target !== 'string')
137137
continue;
138138
const mapped = resolveImportMap(parentMap, resolveIfNotPlainOrUrl(target, baseUrl) || target, baseUrl);
139139
if (mapped) {
140140
outPackages[resolvedLhs] = mapped;
141141
continue;
142142
}
143-
targetWarning(p, packages[p], 'bare specifier did not resolve');
143+
console.warn(`Mapping "${p}" -> "${packages[p]}" does not resolve`);
144144
}
145145
}
146146

@@ -175,17 +175,10 @@
175175
if (pkgName) {
176176
const pkg = packages[pkgName];
177177
if (pkg === null) return;
178-
if (id.length > pkgName.length && pkg[pkg.length - 1] !== '/')
179-
targetWarning(pkgName, pkg, "should have a trailing '/'");
180-
else
181-
return pkg + id.slice(pkgName.length);
178+
return pkg + id.slice(pkgName.length);
182179
}
183180
}
184181

185-
function targetWarning (match, target, msg) {
186-
console.warn("Package target " + msg + ", resolving target '" + target + "' for " + match);
187-
}
188-
189182
function resolveImportMap (importMap, resolvedOrPlain, parentUrl) {
190183
let scopeUrl = parentUrl && getMatch(parentUrl, importMap.scopes);
191184
while (scopeUrl) {
@@ -215,9 +208,9 @@
215208
}
216209

217210
const onerror = globalHook(esmsInitOptions.onerror || noop);
218-
const onpolyfill = globalHook(esmsInitOptions.onpolyfill || noop);
211+
const onpolyfill = esmsInitOptions.onpolyfill ? globalHook(esmsInitOptions.onpolyfill) : () => console.info(`OK: "Uncaught TypeError" module failure has been polyfilled`);
219212

220-
const { revokeBlobURLs, noLoadEventRetriggers } = esmsInitOptions;
213+
const { revokeBlobURLs, noLoadEventRetriggers, enforceIntegrity } = esmsInitOptions;
221214

222215
const fetchHook = esmsInitOptions.fetch ? globalHook(esmsInitOptions.fetch) : fetch;
223216

@@ -340,34 +333,36 @@
340333
const initPromise = featureDetectionPromise.then(() => {
341334
// shim mode is determined on initialization, no late shim mode
342335
if (!shimMode) {
343-
let seenScript = false;
344-
for (const script of document.querySelectorAll('script[type="module-shim"],script[type="importmap-shim"],script[type="module"],script[type="importmap"]')) {
345-
if (!seenScript && script.type === 'module')
346-
seenScript = true;
347-
if (script.type.endsWith('-shim')) {
348-
setShimMode();
349-
break;
350-
}
351-
if (seenScript && script.type === 'importmap') {
352-
importMapSrcOrLazy = true;
353-
break;
336+
if (document.querySelectorAll('script[type=module-shim],script[type=importmap-shim],link[rel=modulepreload-shim]').length) {
337+
setShimMode();
338+
}
339+
else {
340+
let seenScript = false;
341+
for (const script of document.querySelectorAll('script[type=module],script[type=importmap]')) {
342+
if (!seenScript) {
343+
if (script.type === 'module')
344+
seenScript = true;
345+
}
346+
else if (script.type === 'importmap') {
347+
importMapSrcOrLazy = true;
348+
break;
349+
}
354350
}
355351
}
356352
}
357353
baselinePassthrough = supportsDynamicImport && supportsImportMeta && supportsImportMaps && (!jsonModulesEnabled || supportsJsonAssertions) && (!cssModulesEnabled || supportsCssAssertions) && !importMapSrcOrLazy && !false;
358-
if (!baselinePassthrough) onpolyfill();
359354
if (shimMode || !baselinePassthrough) {
360355
new MutationObserver(mutations => {
361356
for (const mutation of mutations) {
362357
if (mutation.type !== 'childList') continue;
363358
for (const node of mutation.addedNodes) {
364359
if (node.tagName === 'SCRIPT') {
365-
if (!shimMode && node.type === 'module' || shimMode && node.type === 'module-shim')
360+
if (node.type === (shimMode ? 'module-shim' : 'module'))
366361
processScript(node);
367-
if (!shimMode && node.type === 'importmap' || shimMode && node.type === 'importmap-shim')
362+
if (node.type === (shimMode ? 'importmap-shim' : 'importmap'))
368363
processImportMap(node);
369364
}
370-
else if (node.tagName === 'LINK' && node.rel === 'modulepreload')
365+
else if (node.tagName === 'LINK' && node.rel === (shimMode ? 'modulepreload-shim' : 'modulepreload'))
371366
processPreload(node);
372367
}
373368
}
@@ -378,8 +373,9 @@
378373
}
379374
});
380375
let importMapPromise = initPromise;
381-
376+
let firstPolyfillLoad = true;
382377
let acceptingImportMaps = true;
378+
383379
async function topLevelLoad (url, fetchOpts, source, nativelyLoaded, lastStaticLoadPromise) {
384380
if (!shimMode)
385381
acceptingImportMaps = false;
@@ -403,6 +399,10 @@
403399
if (revokeBlobURLs) revokeObjectURLs(Object.keys(seen));
404400
return module;
405401
}
402+
if (firstPolyfillLoad && !shimMode && load.n && nativelyLoaded) {
403+
onpolyfill();
404+
firstPolyfillLoad = false;
405+
}
406406
const module = await dynamicImport(!shimMode && !load.n && nativelyLoaded ? load.u : load.b, { errUrl: load.u });
407407
// if the top-level load is a shell, run its update function
408408
if (load.s)
@@ -544,7 +544,6 @@
544544
const jsContentType = /^(text|application)\/(x-)?javascript(;|$)/;
545545
const jsonContentType = /^(text|application)\/json(;|$)/;
546546
const cssContentType = /^(text|application)\/css(;|$)/;
547-
const wasmContentType = /^application\/wasm(;|$)/;
548547

549548
const cssUrlRegEx = /url\(\s*(?:(["'])((?:\\.|[^\n\\"'])+)\1|((?:\\.|[^\s,"'()\\])+))\s*\)/g;
550549

@@ -562,6 +561,8 @@
562561
}
563562

564563
async function doFetch (url, fetchOpts) {
564+
if (enforceIntegrity && !fetchOpts.integrity)
565+
throw Error(`No integrity for ${url}`);
565566
const poolQueue = pushFetchPool();
566567
if (poolQueue) await poolQueue;
567568
try {
@@ -571,7 +572,7 @@
571572
popFetchPool();
572573
}
573574
if (!res.ok)
574-
throw new Error(`${res.status} ${res.statusText} ${res.url}`);
575+
throw Error(`${res.status} ${res.statusText} ${res.url}`);
575576
const contentType = res.headers.get('content-type');
576577
if (jsContentType.test(contentType))
577578
return { r: res.url, s: await res.text(), t: 'js' };
@@ -581,10 +582,8 @@
581582
return { r: res.url, s: `var s=new CSSStyleSheet();s.replaceSync(${
582583
JSON.stringify((await res.text()).replace(cssUrlRegEx, (_match, quotes, relUrl1, relUrl2) => `url(${quotes}${resolveUrl(relUrl1 || relUrl2, url)}${quotes})`))
583584
});export default s;`, t: 'css' };
584-
else if (wasmContentType.test(contentType))
585-
throw new Error('WASM modules not supported');
586585
else
587-
throw new Error(`Unknown Content-Type "${contentType}"`);
586+
throw Error(`Unsupported Content-Type "${contentType}"`);
588587
}
589588

590589
function getOrCreateLoad (url, fetchOpts, source) {
@@ -624,7 +623,7 @@
624623
({ r: load.r, s: source, t } = await (fetchCache[url] || doFetch(url, fetchOpts)));
625624
if (t && !shimMode) {
626625
if (t === 'css' && !cssModulesEnabled || t === 'json' && !jsonModulesEnabled)
627-
throw new Error(`${t}-modules require <script type="esms-options">{ "polyfillEnable": ["${t}-modules"] }<${''}/script>`);
626+
throw Error(`${t}-modules require <script type="esms-options">{ "polyfillEnable": ["${t}-modules"] }<${''}/script>`);
628627
if (t === 'css' && !supportsCssAssertions || t === 'json' && !supportsJsonAssertions)
629628
load.n = true;
630629
}
@@ -663,9 +662,9 @@
663662
}
664663

665664
function processScriptsAndPreloads () {
666-
for (const script of document.querySelectorAll(shimMode ? 'script[type="module-shim"]' : 'script[type="module"]'))
665+
for (const script of document.querySelectorAll(shimMode ? 'script[type=module-shim]' : 'script[type=module]'))
667666
processScript(script);
668-
for (const link of document.querySelectorAll('link[rel="modulepreload"]'))
667+
for (const link of document.querySelectorAll(shimMode ? 'link[rel=modulepreload-shim]' : 'link[rel=modulepreload]'))
669668
processPreload(link);
670669
}
671670

@@ -763,7 +762,8 @@
763762
if (isDomContentLoadedScript) domContentLoadedCnt++;
764763
const blocks = script.getAttribute('async') === null && isReadyScript;
765764
const loadPromise = topLevelLoad(script.src || `${baseUrl}?${id++}`, getFetchOpts(script), !script.src && script.innerHTML, !shimMode, blocks && lastStaticLoadPromise).catch(e => {
766-
setTimeout(() => { throw e });
765+
// This used to be a setTimeout(() => { throw e }) but this breaks Safari stacks
766+
console.error(e);
767767
onerror(e);
768768
});
769769
if (blocks)

app/assets/javascripts/es-module-shims.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)