@depup/webpack 5.110.1-depup.0 → 5.110.3-depup.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/README.md +4 -4
- package/changes.json +3 -3
- package/lib/ChunkGraph.js +20 -18
- package/lib/Compilation.js +1 -1
- package/lib/ConcatenationScope.js +25 -35
- package/lib/DotenvPlugin.js +41 -13
- package/lib/ExportsInfo.js +10 -0
- package/lib/FlagDependencyUsagePlugin.js +8 -2
- package/lib/NormalModule.js +13 -20
- package/lib/RuntimePlugin.js +3 -0
- package/lib/RuntimeTemplate.js +437 -432
- package/lib/async-modules/AsyncModuleHelpers.js +10 -4
- package/lib/config/defaults.js +26 -16
- package/lib/config/normalization.js +18 -8
- package/lib/css/CssLoadingRuntimeModule.js +32 -13
- package/lib/css/CssModulesPlugin.js +9 -17
- package/lib/css/data.js +13 -3
- package/lib/css/syntax.js +78 -10
- package/lib/dependencies/CommonJsRequireDependency.js +18 -4
- package/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +20 -7
- package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +10 -4
- package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +2 -0
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +143 -17
- package/lib/dependencies/HarmonyImportDependency.js +94 -41
- package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +93 -14
- package/lib/dependencies/HarmonyImportSideEffectDependency.js +114 -0
- package/lib/dependencies/HtmlEntryDependency.js +12 -2
- package/lib/dependencies/ImportContextDependency.js +43 -3
- package/lib/dependencies/ImportDependency.js +8 -29
- package/lib/dependencies/ImportParserPlugin.js +24 -14
- package/lib/dependencies/RequireHeaderDependency.js +20 -21
- package/lib/dependencies/WorkerAndWorkletPlugin.js +1 -0
- package/lib/dependencies/WorkerDependency.js +6 -12
- package/lib/dependencies/WorkletDependency.js +7 -11
- package/lib/dependencies/importOptionsCheck.js +47 -0
- package/lib/errors/DotenvFileError.js +29 -0
- package/lib/errors/ImportedBindingAssignmentError.js +30 -0
- package/lib/esm/ModuleChunkLoadingPlugin.js +6 -9
- package/lib/esm/ModuleChunkLoadingRuntimeModule.js +7 -1
- package/lib/html/HtmlModulesPlugin.js +84 -38
- package/lib/html/syntax.js +417 -169
- package/lib/javascript/JavascriptModulesPlugin.js +5 -10
- package/lib/loaders/LoaderRunner.js +33 -5
- package/lib/node/ReadFileCompileAsyncWasmPlugin.js +8 -15
- package/lib/optimize/ConcatenatedModule.js +46 -7
- package/lib/optimize/ConstExportsPlugin.js +5 -0
- package/lib/optimize/InlineExports.js +121 -0
- package/lib/optimize/RealContentHashPlugin.js +111 -35
- package/lib/prefetch/ResourceHintPlugin.js +12 -13
- package/lib/runtime/AsyncModuleRuntimeModule.js +5 -1
- package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +11 -1
- package/lib/schemes/HttpUriPlugin.js +22 -5
- package/lib/serialization/FileMiddleware.js +15 -2
- package/lib/typescript/TypeScriptPlugin.js +8 -10
- package/lib/util/ArrayQueue.js +3 -3
- package/lib/util/SourceProcessor.js +24 -8
- package/lib/util/URLAbsoluteSpecifier.js +3 -1
- package/lib/util/conventions.js +5 -1
- package/lib/util/createMappings.js +25 -3
- package/lib/util/internalSerializables.js +2 -0
- package/lib/util/removeBOM.js +82 -1
- package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +5 -3
- package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +5 -3
- package/lib/wasm-async/UniversalCompileAsyncWasmPlugin.js +7 -12
- package/lib/web/FetchCompileAsyncWasmPlugin.js +10 -6
- package/lib/web/FetchCompileWasmPlugin.js +4 -2
- package/package.json +7 -7
- package/schemas/WebpackOptions.check.js +1 -1
- package/schemas/WebpackOptions.json +9 -10
- package/types.d.ts +95 -27
package/lib/RuntimeTemplate.js
CHANGED
|
@@ -55,6 +55,7 @@ const {
|
|
|
55
55
|
const getCssModulesPlugin = memoize(() => require("./css/CssModulesPlugin"));
|
|
56
56
|
// `Compilation` requires this module, so its stage constants are read lazily.
|
|
57
57
|
const getCompilation = memoize(() => require("./Compilation"));
|
|
58
|
+
const getExternalModule = memoize(() => require("./ExternalModule"));
|
|
58
59
|
|
|
59
60
|
/**
|
|
60
61
|
* @typedef {object} ChunkAssetNaming
|
|
@@ -178,6 +179,20 @@ const DEFER_BAILOUT =
|
|
|
178
179
|
* @property {boolean | null} loaded whether the chunk loader fetched the chunk
|
|
179
180
|
*/
|
|
180
181
|
|
|
182
|
+
/**
|
|
183
|
+
* @typedef {object} AnalyzableChunkUrls
|
|
184
|
+
* @property {Map<ChunkId, string>} urls the urls that could be written, by chunk id
|
|
185
|
+
* @property {boolean} complete false when some chunk kept the runtime form, whose
|
|
186
|
+
* ids the consumer then still resolves through the runtime name lookup
|
|
187
|
+
*/
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* @typedef {object} WasmGroups
|
|
191
|
+
* @property {(key: string) => string} groupOf the group a runtime key answers with
|
|
192
|
+
* @property {Set<string>} fetching groups an entry of which reads binaries with `fetch`
|
|
193
|
+
* @property {Map<string, boolean>} onlyFetching groups every entry of which fetches
|
|
194
|
+
*/
|
|
195
|
+
|
|
181
196
|
// A reference in no chunk at all: nothing is known about where it is read from.
|
|
182
197
|
/** @type {Placement} */
|
|
183
198
|
const NO_PLACEMENT = { undo: null, loaded: null };
|
|
@@ -242,6 +257,10 @@ const SPECIFIER_PART_KINDS = new Set([
|
|
|
242
257
|
// Only these carry a chunk id, which is the one part value that may be a number.
|
|
243
258
|
const CHUNK_SPECIFIER_PART_KINDS = new Set(["chunk", "cssChunk"]);
|
|
244
259
|
|
|
260
|
+
// Only these are spelled out of the compilation hash, so a stand-in holding one moves
|
|
261
|
+
// the chunk it lands in into the round after that hash settles.
|
|
262
|
+
const FULL_HASH_PART_KINDS = new Set(["publicPath", "template", "unserved"]);
|
|
263
|
+
|
|
245
264
|
// What the deferred pass scans for — the other half of what the class spells.
|
|
246
265
|
const ANALYZABLE_TOKEN_REGEXP = /\.\/@@webpackAnalyzableChunk:([\w-]+)@@/g;
|
|
247
266
|
|
|
@@ -331,6 +350,25 @@ const createHashProbeChunk = (chunk, hash, present) => {
|
|
|
331
350
|
return probeChunk;
|
|
332
351
|
};
|
|
333
352
|
|
|
353
|
+
/**
|
|
354
|
+
* A filename function's answer to the stand-in hash, which says what shape the name
|
|
355
|
+
* has before any real hash exists.
|
|
356
|
+
* @param {Exclude<ChunkFilenameTemplate, string>} template the filename function
|
|
357
|
+
* @param {Chunk} chunk the chunk being referenced
|
|
358
|
+
* @param {string} contentHashType which of the chunk's hashes the name reads
|
|
359
|
+
* @param {string} hash the stand-in hash
|
|
360
|
+
* @param {boolean} present whether the chunk is claimed to carry content hashes
|
|
361
|
+
* @returns {string} what the function names it
|
|
362
|
+
*/
|
|
363
|
+
const probeTemplateName = (template, chunk, contentHashType, hash, present) =>
|
|
364
|
+
template({
|
|
365
|
+
chunk: createHashProbeChunk(chunk, hash, present),
|
|
366
|
+
runtime: chunk.runtime,
|
|
367
|
+
contentHashType,
|
|
368
|
+
hash,
|
|
369
|
+
contentHash: hash
|
|
370
|
+
});
|
|
371
|
+
|
|
334
372
|
/**
|
|
335
373
|
* No module id error message.
|
|
336
374
|
* @param {Module} module the module
|
|
@@ -385,6 +423,11 @@ function getGlobalObject(definition) {
|
|
|
385
423
|
return `Object(${trimmed})`;
|
|
386
424
|
}
|
|
387
425
|
|
|
426
|
+
// An async external is a promise, not a module record with an evaluating state.
|
|
427
|
+
const isAsyncExternal = (/** @type {Module} */ module) =>
|
|
428
|
+
Boolean(/** @type {BuildMeta} */ (module.buildMeta).async) &&
|
|
429
|
+
module instanceof getExternalModule();
|
|
430
|
+
|
|
388
431
|
class RuntimeTemplate {
|
|
389
432
|
/**
|
|
390
433
|
* Creates an instance of RuntimeTemplate.
|
|
@@ -426,14 +469,10 @@ class RuntimeTemplate {
|
|
|
426
469
|
this._placementByChunk = new WeakMap();
|
|
427
470
|
/** @type {Map<string, string | null | undefined>} */
|
|
428
471
|
this._entryBaseUriByRuntime = new Map();
|
|
429
|
-
/** @type {
|
|
430
|
-
this.
|
|
431
|
-
/** @type {Set<string> | false | undefined} */
|
|
432
|
-
this._wasmFetchingGroupSet = undefined;
|
|
472
|
+
/** @type {WasmGroups | undefined} */
|
|
473
|
+
this._wasmGroupsValue = undefined;
|
|
433
474
|
/** @type {Map<string, boolean> | undefined} */
|
|
434
475
|
this._wasmAnchorKnownByGroup = undefined;
|
|
435
|
-
/** @type {Map<string, boolean> | undefined} */
|
|
436
|
-
this._wasmGroupOnlyFetchesMap = undefined;
|
|
437
476
|
}
|
|
438
477
|
|
|
439
478
|
isIIFE() {
|
|
@@ -630,28 +669,28 @@ class RuntimeTemplate {
|
|
|
630
669
|
placedModule
|
|
631
670
|
)
|
|
632
671
|
) {
|
|
633
|
-
this._analyzableBailout(
|
|
672
|
+
return this._analyzableBailout(
|
|
634
673
|
module,
|
|
635
|
-
"__webpack_public_path__ is reassigned in a runtime this module belongs to"
|
|
674
|
+
"__webpack_public_path__ is reassigned in a runtime this module belongs to",
|
|
675
|
+
false
|
|
636
676
|
);
|
|
637
|
-
return false;
|
|
638
677
|
}
|
|
639
678
|
|
|
640
679
|
if (form === "import") {
|
|
641
680
|
// Read through a native `import()`, or it is not this feature at all.
|
|
642
681
|
if (outputOptions.chunkFormat !== "module") {
|
|
643
|
-
this._analyzableBailout(
|
|
682
|
+
return this._analyzableBailout(
|
|
644
683
|
module,
|
|
645
|
-
`output.chunkFormat is ${JSON.stringify(outputOptions.chunkFormat)}, so chunks are not read through a native import()
|
|
684
|
+
`output.chunkFormat is ${JSON.stringify(outputOptions.chunkFormat)}, so chunks are not read through a native import()`,
|
|
685
|
+
false
|
|
646
686
|
);
|
|
647
|
-
return false;
|
|
648
687
|
}
|
|
649
688
|
if (outputOptions.importFunctionName !== "import") {
|
|
650
|
-
this._analyzableBailout(
|
|
689
|
+
return this._analyzableBailout(
|
|
651
690
|
module,
|
|
652
|
-
`output.importFunctionName is ${JSON.stringify(outputOptions.importFunctionName)}, so the call site is not a native import()
|
|
691
|
+
`output.importFunctionName is ${JSON.stringify(outputOptions.importFunctionName)}, so the call site is not a native import()`,
|
|
692
|
+
false
|
|
653
693
|
);
|
|
654
|
-
return false;
|
|
655
694
|
}
|
|
656
695
|
// A worker loading its own chunks some other way keeps that runtime; one on
|
|
657
696
|
// `import` uses the same ESM loader as the main graph, so it can be analyzable.
|
|
@@ -662,29 +701,23 @@ class RuntimeTemplate {
|
|
|
662
701
|
if (!entryOptions || !entryOptions.worker) continue;
|
|
663
702
|
// `WorkerAndWorkletPlugin` always seeds this from `output.workerChunkLoading`.
|
|
664
703
|
if (entryOptions.chunkLoading !== "import") {
|
|
665
|
-
this._analyzableBailout(
|
|
704
|
+
return this._analyzableBailout(
|
|
666
705
|
module,
|
|
667
|
-
`this worker loads its chunks with ${JSON.stringify(entryOptions.chunkLoading)}, not "import"
|
|
706
|
+
`this worker loads its chunks with ${JSON.stringify(entryOptions.chunkLoading)}, not "import"`,
|
|
707
|
+
false
|
|
668
708
|
);
|
|
669
|
-
return false;
|
|
670
709
|
}
|
|
671
710
|
}
|
|
672
711
|
return true;
|
|
673
712
|
}
|
|
674
713
|
|
|
675
714
|
// `url-inline` asks whether the file can be named at the call site at all, and
|
|
676
|
-
// its `.p + <file>` fallback spells that without `import.meta` — so
|
|
677
|
-
// below
|
|
715
|
+
// its `.p + <file>` fallback spells that without `import.meta` — so the gate
|
|
716
|
+
// below does not rule it out, and the asset's javascript wrapper stays dropped.
|
|
717
|
+
// `environment.module` is deliberately not consulted: ESM output writes
|
|
718
|
+
// `import.meta` regardless (the public path, the chunk loader), so the url forms
|
|
719
|
+
// only match what the rest of the bundle already assumes the target reads.
|
|
678
720
|
if (form === "url-inline") return true;
|
|
679
|
-
// `import.meta` is ESM syntax the target has to read. A chunk `import()` is
|
|
680
|
-
// emitted by the module chunk loader either way, so only the url forms check.
|
|
681
|
-
if (!this.supportsEcmaScriptModuleSyntax()) {
|
|
682
|
-
this._analyzableBailout(
|
|
683
|
-
module,
|
|
684
|
-
"output.environment.module is false, so the target does not read the import.meta this form needs"
|
|
685
|
-
);
|
|
686
|
-
return false;
|
|
687
|
-
}
|
|
688
721
|
// `eval` devtool wraps each module in `eval(...)`, where `import.meta` is a
|
|
689
722
|
// syntax error. Runtime modules are emitted beside them, never wrapped.
|
|
690
723
|
const { devtool } = this.compilation.options;
|
|
@@ -693,22 +726,22 @@ class RuntimeTemplate {
|
|
|
693
726
|
typeof devtool === "string" &&
|
|
694
727
|
devtool.includes("eval")
|
|
695
728
|
) {
|
|
696
|
-
this._analyzableBailout(
|
|
729
|
+
return this._analyzableBailout(
|
|
697
730
|
module,
|
|
698
|
-
`devtool ${JSON.stringify(devtool)} wraps the module in eval(), where import.meta does not parse
|
|
731
|
+
`devtool ${JSON.stringify(devtool)} wraps the module in eval(), where import.meta does not parse`,
|
|
732
|
+
false
|
|
699
733
|
);
|
|
700
|
-
return false;
|
|
701
734
|
}
|
|
702
735
|
if (form === "url" || form === "url-runtime") return true;
|
|
703
736
|
// A bare relative URL is what `__webpack_require__.p + path` means only under an
|
|
704
737
|
// `auto` public path; anything else has to be baked, which is the "wasm" form.
|
|
705
738
|
if (form === "wasm-relative") {
|
|
706
739
|
if (outputOptions.publicPath === "auto") return true;
|
|
707
|
-
this._analyzableBailout(
|
|
740
|
+
return this._analyzableBailout(
|
|
708
741
|
module,
|
|
709
|
-
"output.publicPath is set, so a bare relative url no longer means what the public path would have resolved to"
|
|
742
|
+
"output.publicPath is set, so a bare relative url no longer means what the public path would have resolved to",
|
|
743
|
+
false
|
|
710
744
|
);
|
|
711
|
-
return false;
|
|
712
745
|
}
|
|
713
746
|
|
|
714
747
|
// The rest is the `"wasm"` form: whether the whole binary url can be spelled
|
|
@@ -727,11 +760,11 @@ class RuntimeTemplate {
|
|
|
727
760
|
this._anyWasmChunkFetches(runtime) &&
|
|
728
761
|
!this._wasmFetchAnchorIsKnown(runtime)
|
|
729
762
|
) {
|
|
730
|
-
this._analyzableBailout(
|
|
763
|
+
return this._analyzableBailout(
|
|
731
764
|
module,
|
|
732
|
-
"output.publicPath needs a base, and no one path back to the document fits every chunk `fetch` reads it from"
|
|
765
|
+
"output.publicPath needs a base, and no one path back to the document fits every chunk `fetch` reads it from",
|
|
766
|
+
false
|
|
733
767
|
);
|
|
734
|
-
return false;
|
|
735
768
|
}
|
|
736
769
|
}
|
|
737
770
|
// The compilation hash is settled after code generation, so a name carrying one
|
|
@@ -753,19 +786,22 @@ class RuntimeTemplate {
|
|
|
753
786
|
* the channel `ModuleConcatenationPlugin` already reports through, so it reaches
|
|
754
787
|
* `stats.optimizationBailout`. Silent unless the build asked for ESM output, where
|
|
755
788
|
* alone the answer is actionable; deduplicated because a module may write many.
|
|
789
|
+
* Answers with `answer` so a caller states the refusal and its reason at once —
|
|
790
|
+
* `false` where it answers a question, `null` where it was building a specifier.
|
|
791
|
+
* @template {false | null} T
|
|
756
792
|
* @param {Module | undefined} module the module the reference is emitted into
|
|
757
793
|
* @param {string} reason why no literal could be baked
|
|
758
|
-
* @
|
|
794
|
+
* @param {T} answer what the caller hands back
|
|
795
|
+
* @returns {T} that answer
|
|
759
796
|
*/
|
|
760
|
-
_analyzableBailout(module, reason) {
|
|
761
|
-
if (module
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
if (existing === text) return;
|
|
797
|
+
_analyzableBailout(module, reason, answer) {
|
|
798
|
+
if (module !== undefined && this.outputOptions.module) {
|
|
799
|
+
const text = `Analyzable ESM bailout: ${reason}`;
|
|
800
|
+
const bailouts =
|
|
801
|
+
this.compilation.moduleGraph.getOptimizationBailout(module);
|
|
802
|
+
if (!bailouts.includes(text)) bailouts.push(text);
|
|
767
803
|
}
|
|
768
|
-
|
|
804
|
+
return answer;
|
|
769
805
|
}
|
|
770
806
|
|
|
771
807
|
/**
|
|
@@ -810,8 +846,7 @@ class RuntimeTemplate {
|
|
|
810
846
|
*/
|
|
811
847
|
_canDeferOrBail(chunks, module) {
|
|
812
848
|
if (this._canDeferAnalyzableName(chunks)) return true;
|
|
813
|
-
this._analyzableBailout(module, DEFER_BAILOUT);
|
|
814
|
-
return false;
|
|
849
|
+
return this._analyzableBailout(module, DEFER_BAILOUT, false);
|
|
815
850
|
}
|
|
816
851
|
|
|
817
852
|
/**
|
|
@@ -861,9 +896,7 @@ class RuntimeTemplate {
|
|
|
861
896
|
*/
|
|
862
897
|
_partsBakeFullHash(parts) {
|
|
863
898
|
for (const [kind, value] of parts) {
|
|
864
|
-
if (kind
|
|
865
|
-
return true;
|
|
866
|
-
}
|
|
899
|
+
if (FULL_HASH_PART_KINDS.has(kind)) return true;
|
|
867
900
|
if (kind === "literal" && this._hasReservedFullHash(String(value))) {
|
|
868
901
|
return true;
|
|
869
902
|
}
|
|
@@ -962,95 +995,83 @@ class RuntimeTemplate {
|
|
|
962
995
|
const base = this.analyzableUrlReadsBaseUri()
|
|
963
996
|
? this.entryBaseUri(runtime)
|
|
964
997
|
: undefined;
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
}
|
|
973
|
-
// A relative one is no base of its own: the runtime reads it against the
|
|
974
|
-
// chunk, so the literal spells it there rather than resolving against it.
|
|
975
|
-
if (isChunkRelativeBaseUri(base)) {
|
|
976
|
-
return this._getAnalyzableFileSpecifier(
|
|
977
|
-
module,
|
|
978
|
-
chunkGraph,
|
|
979
|
-
[["literal", filename]],
|
|
980
|
-
true,
|
|
981
|
-
base
|
|
982
|
-
);
|
|
983
|
-
}
|
|
984
|
-
const chunks = this._moduleChunks(module, chunkGraph);
|
|
985
|
-
// A protocol-relative base names a host but no scheme, and the runtime reads it
|
|
986
|
-
// against the chunk's own url to get one — the very url this literal is
|
|
987
|
-
// resolved against — so it may stay protocol-relative instead of being settled
|
|
988
|
-
// here. Nothing walks back to the output root first: the base replaces it.
|
|
989
|
-
if (base.startsWith("//")) {
|
|
990
|
-
const relative = this._resolvePublicPathPrefix(
|
|
991
|
-
publicPath,
|
|
992
|
-
module,
|
|
993
|
-
chunks
|
|
994
|
-
);
|
|
995
|
-
return relative === null
|
|
996
|
-
? null
|
|
997
|
-
: this._specifierOf(
|
|
998
|
-
[
|
|
999
|
-
["literal", base],
|
|
1000
|
-
...rootedParts(relative),
|
|
1001
|
-
["literal", filename]
|
|
1002
|
-
],
|
|
1003
|
-
chunks,
|
|
1004
|
-
module
|
|
1005
|
-
);
|
|
1006
|
-
}
|
|
1007
|
-
if (!isAbsoluteBaseUri(base)) {
|
|
1008
|
-
this._analyzableBailout(
|
|
1009
|
-
module,
|
|
1010
|
-
`an entry sets a baseUri of ${JSON.stringify(base)}, whose scheme names no base anything can be resolved against`
|
|
1011
|
-
);
|
|
1012
|
-
return null;
|
|
1013
|
-
}
|
|
1014
|
-
const parts = this._resolvePublicPathPrefix(publicPath, module, chunks);
|
|
1015
|
-
if (parts === null) return null;
|
|
1016
|
-
// Resolved here rather than against the output root, and only an absolute base
|
|
1017
|
-
// settles it — a relative one has no base of its own to be read against.
|
|
1018
|
-
const spelled = literalText(parts);
|
|
1019
|
-
// A hash the deferred pass still has to fill in cannot be resolved against the
|
|
1020
|
-
// base here: the fill would land inside an already-resolved url, where a hash
|
|
1021
|
-
// opening with a letter reads as a scheme and drops the base entirely.
|
|
1022
|
-
const text =
|
|
1023
|
-
spelled !== null && !this._hasReservedFullHash(spelled)
|
|
1024
|
-
? spelled
|
|
1025
|
-
: null;
|
|
1026
|
-
/** @type {URL} */
|
|
1027
|
-
let resolved;
|
|
1028
|
-
try {
|
|
1029
|
-
// Empty where only the deferred pass can spell the rest, which still settles
|
|
1030
|
-
// whether the base itself is one anything may be resolved against.
|
|
1031
|
-
resolved = new URL(text === null ? "" : text + filename, base);
|
|
1032
|
-
} catch (_error) {
|
|
1033
|
-
this._analyzableBailout(
|
|
1034
|
-
module,
|
|
1035
|
-
`an entry sets a baseUri of ${JSON.stringify(base)}, which is not absolute, so no url can be resolved against it here`
|
|
1036
|
-
);
|
|
1037
|
-
return null;
|
|
1038
|
-
}
|
|
1039
|
-
if (text !== null) return toJsStringLiteral(resolved.href);
|
|
1040
|
-
if (!this._canDeferOrBail(chunks, module)) return null;
|
|
1041
|
-
return toJsStringLiteral(
|
|
1042
|
-
this._reserveAnalyzableSpecifier([
|
|
1043
|
-
["base", base],
|
|
1044
|
-
...parts,
|
|
1045
|
-
["literal", filename]
|
|
1046
|
-
])
|
|
998
|
+
// No base of its own: the name is spelled against the output root, as a chunk is.
|
|
999
|
+
if (base === undefined) {
|
|
1000
|
+
return this._getAnalyzableFileSpecifier(
|
|
1001
|
+
module,
|
|
1002
|
+
chunkGraph,
|
|
1003
|
+
[["literal", filename]],
|
|
1004
|
+
true
|
|
1047
1005
|
);
|
|
1048
1006
|
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1007
|
+
if (base === null) {
|
|
1008
|
+
return this._analyzableBailout(
|
|
1009
|
+
module,
|
|
1010
|
+
"the entries this module is generated for set different baseUri values, so no one url resolves for all of them",
|
|
1011
|
+
null
|
|
1012
|
+
);
|
|
1013
|
+
}
|
|
1014
|
+
// A relative one is no base of its own: the runtime reads it against the
|
|
1015
|
+
// chunk, so the literal spells it there rather than resolving against it.
|
|
1016
|
+
if (isChunkRelativeBaseUri(base)) {
|
|
1017
|
+
return this._getAnalyzableFileSpecifier(
|
|
1018
|
+
module,
|
|
1019
|
+
chunkGraph,
|
|
1020
|
+
[["literal", filename]],
|
|
1021
|
+
true,
|
|
1022
|
+
base
|
|
1023
|
+
);
|
|
1024
|
+
}
|
|
1025
|
+
const chunks = this._moduleChunks(module, chunkGraph);
|
|
1026
|
+
const parts = this._resolvePublicPathPrefix(publicPath, module, chunks);
|
|
1027
|
+
if (parts === null) return null;
|
|
1028
|
+
// A protocol-relative base names a host but no scheme, and the runtime reads it
|
|
1029
|
+
// against the chunk's own url to get one — the very url this literal is
|
|
1030
|
+
// resolved against — so it may stay protocol-relative instead of being settled
|
|
1031
|
+
// here. Nothing walks back to the output root first: the base replaces it.
|
|
1032
|
+
if (base.startsWith("//")) {
|
|
1033
|
+
return this._specifierOf(
|
|
1034
|
+
[["literal", base], ...rootedParts(parts), ["literal", filename]],
|
|
1035
|
+
chunks,
|
|
1036
|
+
module
|
|
1037
|
+
);
|
|
1038
|
+
}
|
|
1039
|
+
if (!isAbsoluteBaseUri(base)) {
|
|
1040
|
+
return this._analyzableBailout(
|
|
1041
|
+
module,
|
|
1042
|
+
`an entry sets a baseUri of ${JSON.stringify(base)}, whose scheme names no base anything can be resolved against`,
|
|
1043
|
+
null
|
|
1044
|
+
);
|
|
1045
|
+
}
|
|
1046
|
+
// Resolved here rather than against the output root, and only an absolute base
|
|
1047
|
+
// settles it — a relative one has no base of its own to be read against.
|
|
1048
|
+
const spelled = literalText(parts);
|
|
1049
|
+
// A hash the deferred pass still has to fill in cannot be resolved against the
|
|
1050
|
+
// base here: the fill would land inside an already-resolved url, where a hash
|
|
1051
|
+
// opening with a letter reads as a scheme and drops the base entirely.
|
|
1052
|
+
const text =
|
|
1053
|
+
spelled !== null && !this._hasReservedFullHash(spelled) ? spelled : null;
|
|
1054
|
+
/** @type {URL} */
|
|
1055
|
+
let resolved;
|
|
1056
|
+
try {
|
|
1057
|
+
// Empty where only the deferred pass can spell the rest, which still settles
|
|
1058
|
+
// whether the base itself is one anything may be resolved against.
|
|
1059
|
+
resolved = new URL(text === null ? "" : text + filename, base);
|
|
1060
|
+
} catch (_error) {
|
|
1061
|
+
return this._analyzableBailout(
|
|
1062
|
+
module,
|
|
1063
|
+
`an entry sets a baseUri of ${JSON.stringify(base)}, which is not absolute, so no url can be resolved against it here`,
|
|
1064
|
+
null
|
|
1065
|
+
);
|
|
1066
|
+
}
|
|
1067
|
+
if (text !== null) return toJsStringLiteral(resolved.href);
|
|
1068
|
+
if (!this._canDeferOrBail(chunks, module)) return null;
|
|
1069
|
+
return toJsStringLiteral(
|
|
1070
|
+
this._reserveAnalyzableSpecifier([
|
|
1071
|
+
["base", base],
|
|
1072
|
+
...parts,
|
|
1073
|
+
["literal", filename]
|
|
1074
|
+
])
|
|
1054
1075
|
);
|
|
1055
1076
|
}
|
|
1056
1077
|
|
|
@@ -1121,55 +1142,119 @@ class RuntimeTemplate {
|
|
|
1121
1142
|
return publicPath.includes("[") ? undefined : publicPath;
|
|
1122
1143
|
}
|
|
1123
1144
|
|
|
1145
|
+
/**
|
|
1146
|
+
* Runtime keys grouped by the binaries they share, with what the entries of each
|
|
1147
|
+
* group asked for. Code generation runs once for runtimes a module hashes alike in,
|
|
1148
|
+
* and nothing in a binary's hash knows which loader will read it — so a binary two
|
|
1149
|
+
* runtimes reach carries one shape into both, and a third runtime sharing another
|
|
1150
|
+
* binary with either is pulled in after them. Only an entry names a loader; every
|
|
1151
|
+
* other chunk of the runtime is served by the one its entry asked for. Asked of the
|
|
1152
|
+
* same modules the loaders are created for, and only once per compilation.
|
|
1153
|
+
* @returns {WasmGroups} the grouping, and which groups fetch
|
|
1154
|
+
*/
|
|
1155
|
+
_wasmGroups() {
|
|
1156
|
+
if (this._wasmGroupsValue === undefined) {
|
|
1157
|
+
const { chunkGraph, chunks, modules } = this.compilation;
|
|
1158
|
+
/** @type {Map<string, string>} */
|
|
1159
|
+
const parent = new Map();
|
|
1160
|
+
/**
|
|
1161
|
+
* @param {string} key runtime key
|
|
1162
|
+
* @returns {string} the key naming its group
|
|
1163
|
+
*/
|
|
1164
|
+
const find = (key) => {
|
|
1165
|
+
let root = key;
|
|
1166
|
+
let seen = parent.get(root);
|
|
1167
|
+
while (seen !== undefined && seen !== root) {
|
|
1168
|
+
root = seen;
|
|
1169
|
+
seen = parent.get(root);
|
|
1170
|
+
}
|
|
1171
|
+
// Path compression keeps a long share chain from costing more than once.
|
|
1172
|
+
let walk = key;
|
|
1173
|
+
let next = parent.get(walk);
|
|
1174
|
+
while (next !== undefined && next !== root) {
|
|
1175
|
+
parent.set(walk, root);
|
|
1176
|
+
walk = next;
|
|
1177
|
+
next = parent.get(walk);
|
|
1178
|
+
}
|
|
1179
|
+
return root;
|
|
1180
|
+
};
|
|
1181
|
+
/** @type {string[]} */
|
|
1182
|
+
const keys = [];
|
|
1183
|
+
for (const module of modules) {
|
|
1184
|
+
if (module.type !== WEBASSEMBLY_MODULE_TYPE_ASYNC) continue;
|
|
1185
|
+
keys.length = 0;
|
|
1186
|
+
for (const runtime of chunkGraph.getModuleRuntimes(module)) {
|
|
1187
|
+
forEachRuntime(runtime, (key) => {
|
|
1188
|
+
keys.push(/** @type {string} */ (key));
|
|
1189
|
+
});
|
|
1190
|
+
}
|
|
1191
|
+
for (const key of keys) if (!parent.has(key)) parent.set(key, key);
|
|
1192
|
+
// Every runtime this binary reaches answers with the first one.
|
|
1193
|
+
for (let i = 1; i < keys.length; i++) {
|
|
1194
|
+
parent.set(find(keys[i]), find(keys[0]));
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
// Flattened once, so a lookup is a single `get` rather than a chain walk.
|
|
1198
|
+
for (const key of parent.keys()) parent.set(key, find(key));
|
|
1199
|
+
/**
|
|
1200
|
+
* @param {string} key a runtime key
|
|
1201
|
+
* @returns {string} the group it answers with, or itself when it shares nothing
|
|
1202
|
+
*/
|
|
1203
|
+
const groupOf = (key) => {
|
|
1204
|
+
const group = parent.get(key);
|
|
1205
|
+
// An entry named "" makes "" a runtime key, so test absence, not a falsy value.
|
|
1206
|
+
return group === undefined ? key : group;
|
|
1207
|
+
};
|
|
1208
|
+
/** @type {Set<string>} */
|
|
1209
|
+
const fetching = new Set();
|
|
1210
|
+
/** @type {Map<string, boolean>} */
|
|
1211
|
+
const onlyFetching = new Map();
|
|
1212
|
+
for (const chunk of chunks) {
|
|
1213
|
+
if (!chunk.getEntryOptions()) continue;
|
|
1214
|
+
const fetches = this._chunkWasmLoading(chunk) === "fetch";
|
|
1215
|
+
forEachRuntime(chunk.runtime, (key) => {
|
|
1216
|
+
const group = groupOf(/** @type {string} */ (key));
|
|
1217
|
+
if (fetches) fetching.add(group);
|
|
1218
|
+
onlyFetching.set(group, onlyFetching.get(group) !== false && fetches);
|
|
1219
|
+
});
|
|
1220
|
+
}
|
|
1221
|
+
this._wasmGroupsValue = { groupOf, fetching, onlyFetching };
|
|
1222
|
+
}
|
|
1223
|
+
return this._wasmGroupsValue;
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
/**
|
|
1227
|
+
* @param {RuntimeSpec} runtime the runtime being asked about
|
|
1228
|
+
* @returns {string[]} the wasm runtime groups it reaches
|
|
1229
|
+
*/
|
|
1230
|
+
_wasmGroupsOf(runtime) {
|
|
1231
|
+
const { groupOf } = this._wasmGroups();
|
|
1232
|
+
/** @type {string[]} */
|
|
1233
|
+
const reached = [];
|
|
1234
|
+
forEachRuntime(runtime, (key) => {
|
|
1235
|
+
reached.push(groupOf(/** @type {string} */ (key)));
|
|
1236
|
+
});
|
|
1237
|
+
return reached;
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1124
1240
|
/**
|
|
1125
1241
|
* Whether a chunk loads WebAssembly through `fetch`, which is the only loader the
|
|
1126
1242
|
* public path reaches: `readFile` resolves the binary's name against the chunk it is
|
|
1127
1243
|
* read from, exactly as a baked literal does, so a public path is irrelevant to it.
|
|
1128
|
-
* Answered per
|
|
1244
|
+
* Answered per group rather than per chunk on purpose — a module's generated source
|
|
1129
1245
|
* and the runtime module of every chunk holding it have to agree on the shape, and
|
|
1130
|
-
* they ask from opposite ends; one loader serves a whole
|
|
1131
|
-
*
|
|
1132
|
-
* told apart, the answer covers the compilation.
|
|
1246
|
+
* they ask from opposite ends; one loader serves a whole group, so that is the finest
|
|
1247
|
+
* scope on which they can. Without a runtime the answer covers the compilation.
|
|
1133
1248
|
* @param {RuntimeSpec=} runtime the runtime being asked about
|
|
1134
1249
|
* @returns {boolean} true when a chunk of that runtime fetches its binaries
|
|
1135
1250
|
*/
|
|
1136
1251
|
_anyWasmChunkFetches(runtime) {
|
|
1137
|
-
const fetching = this.
|
|
1138
|
-
if (fetching ===
|
|
1252
|
+
const { fetching } = this._wasmGroups();
|
|
1253
|
+
if (fetching.size === 0) return false;
|
|
1139
1254
|
// Without a runtime to place it in there is nothing to narrow by, so any chunk
|
|
1140
1255
|
// answers for all of them.
|
|
1141
1256
|
if (runtime === undefined) return true;
|
|
1142
|
-
|
|
1143
|
-
if (typeof runtime === "string") {
|
|
1144
|
-
return fetching.has(this._wasmGroupOf(groups, runtime));
|
|
1145
|
-
}
|
|
1146
|
-
for (const key of runtime) {
|
|
1147
|
-
if (fetching.has(this._wasmGroupOf(groups, key))) return true;
|
|
1148
|
-
}
|
|
1149
|
-
return false;
|
|
1150
|
-
}
|
|
1151
|
-
|
|
1152
|
-
/**
|
|
1153
|
-
* Whether every entry of a wasm runtime group reads its binaries with `fetch`. Only
|
|
1154
|
-
* an entry names a loader, so the scan is of entries, as `_wasmFetchingGroups` is.
|
|
1155
|
-
* @returns {Map<string, boolean>} whether each group fetches and nothing else
|
|
1156
|
-
*/
|
|
1157
|
-
_wasmGroupOnlyFetches() {
|
|
1158
|
-
if (this._wasmGroupOnlyFetchesMap === undefined) {
|
|
1159
|
-
const groups = this._wasmRuntimeGroups();
|
|
1160
|
-
/** @type {Map<string, boolean>} */
|
|
1161
|
-
const only = new Map();
|
|
1162
|
-
for (const chunk of this.compilation.chunks) {
|
|
1163
|
-
if (!chunk.getEntryOptions()) continue;
|
|
1164
|
-
const fetches = this._chunkWasmLoading(chunk) === "fetch";
|
|
1165
|
-
forEachRuntime(chunk.runtime, (key) => {
|
|
1166
|
-
const group = this._wasmGroupOf(groups, /** @type {string} */ (key));
|
|
1167
|
-
only.set(group, only.get(group) !== false && fetches);
|
|
1168
|
-
});
|
|
1169
|
-
}
|
|
1170
|
-
this._wasmGroupOnlyFetchesMap = only;
|
|
1171
|
-
}
|
|
1172
|
-
return this._wasmGroupOnlyFetchesMap;
|
|
1257
|
+
return this._wasmGroupsOf(runtime).some((group) => fetching.has(group));
|
|
1173
1258
|
}
|
|
1174
1259
|
|
|
1175
1260
|
/**
|
|
@@ -1182,30 +1267,31 @@ class RuntimeTemplate {
|
|
|
1182
1267
|
_wasmFetchAnchorIsKnown(runtime) {
|
|
1183
1268
|
if (this._wasmAnchorKnownByGroup === undefined) {
|
|
1184
1269
|
const { chunkGraph, modules } = this.compilation;
|
|
1185
|
-
const
|
|
1186
|
-
this.outputOptions.publicPath
|
|
1187
|
-
);
|
|
1188
|
-
const groups = this._wasmRuntimeGroups();
|
|
1270
|
+
const { groupOf, onlyFetching } = this._wasmGroups();
|
|
1189
1271
|
/** @type {Map<string, boolean>} */
|
|
1190
1272
|
const known = new Map();
|
|
1191
1273
|
for (const module of modules) {
|
|
1192
1274
|
if (module.type !== WEBASSEMBLY_MODULE_TYPE_ASYNC) continue;
|
|
1275
|
+
// Probed through the very builder the generator runs, so the gate is
|
|
1276
|
+
// exact: a prefix it can spell — the per-asset deferrals included — is
|
|
1277
|
+
// one the group may bake. The probe name stands in for the binary's.
|
|
1193
1278
|
const spellable =
|
|
1194
|
-
this.
|
|
1195
|
-
|
|
1279
|
+
this._getAnalyzableFileSpecifier(
|
|
1280
|
+
module,
|
|
1281
|
+
/** @type {ChunkGraph} */ (chunkGraph),
|
|
1282
|
+
[["literal", "x"]],
|
|
1283
|
+
true
|
|
1284
|
+
) !== null;
|
|
1196
1285
|
for (const moduleRuntime of chunkGraph.getModuleRuntimes(module)) {
|
|
1197
1286
|
forEachRuntime(moduleRuntime, (key) => {
|
|
1198
|
-
const group =
|
|
1199
|
-
groups,
|
|
1200
|
-
/** @type {string} */ (key)
|
|
1201
|
-
);
|
|
1287
|
+
const group = groupOf(/** @type {string} */ (key));
|
|
1202
1288
|
known.set(group, known.get(group) !== false && spellable);
|
|
1203
1289
|
});
|
|
1204
1290
|
}
|
|
1205
1291
|
}
|
|
1206
1292
|
// A group one entry reads with `readFile` cannot take a prefix meant for the
|
|
1207
1293
|
// document, and only an entry names its loader.
|
|
1208
|
-
for (const [group, only] of
|
|
1294
|
+
for (const [group, only] of onlyFetching) {
|
|
1209
1295
|
if (!only) known.set(group, false);
|
|
1210
1296
|
}
|
|
1211
1297
|
this._wasmAnchorKnownByGroup = known;
|
|
@@ -1217,124 +1303,9 @@ class RuntimeTemplate {
|
|
|
1217
1303
|
for (const value of known.values()) if (!value) return false;
|
|
1218
1304
|
return known.size > 0;
|
|
1219
1305
|
}
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
}
|
|
1224
|
-
for (const key of runtime) {
|
|
1225
|
-
if (known.get(this._wasmGroupOf(groups, key)) !== true) return false;
|
|
1226
|
-
}
|
|
1227
|
-
return true;
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1230
|
-
/**
|
|
1231
|
-
* The runtime groups an entry of which asked for the `fetch` loader, or `undefined`
|
|
1232
|
-
* where none did — the cheap answer for a compilation with no fetching entry at all,
|
|
1233
|
-
* which is every non-web target. Only an entry names a loader; every other chunk of
|
|
1234
|
-
* the runtime is served by the one its entry asked for.
|
|
1235
|
-
* @returns {Set<string> | undefined} the groups that fetch
|
|
1236
|
-
*/
|
|
1237
|
-
_wasmFetchingGroups() {
|
|
1238
|
-
if (this._wasmFetchingGroupSet === undefined) {
|
|
1239
|
-
/** @type {Set<string>} */
|
|
1240
|
-
const fetching = new Set();
|
|
1241
|
-
/** @type {Map<string, string> | undefined} */
|
|
1242
|
-
let groups;
|
|
1243
|
-
for (const chunk of this.compilation.chunks) {
|
|
1244
|
-
// Only an entry names a loader; every other chunk of the runtime is served
|
|
1245
|
-
// by the one its entry asked for, so it says nothing on its own.
|
|
1246
|
-
if (!chunk.getEntryOptions()) continue;
|
|
1247
|
-
if (this._chunkWasmLoading(chunk) !== "fetch") continue;
|
|
1248
|
-
// Built only once something fetches, so nothing pays for the grouping.
|
|
1249
|
-
if (groups === undefined) groups = this._wasmRuntimeGroups();
|
|
1250
|
-
const named = /** @type {Map<string, string>} */ (groups);
|
|
1251
|
-
forEachRuntime(chunk.runtime, (key) => {
|
|
1252
|
-
fetching.add(this._wasmGroupOf(named, /** @type {string} */ (key)));
|
|
1253
|
-
});
|
|
1254
|
-
}
|
|
1255
|
-
this._wasmFetchingGroupSet = fetching.size === 0 ? false : fetching;
|
|
1256
|
-
}
|
|
1257
|
-
return this._wasmFetchingGroupSet === false
|
|
1258
|
-
? undefined
|
|
1259
|
-
: this._wasmFetchingGroupSet;
|
|
1260
|
-
}
|
|
1261
|
-
|
|
1262
|
-
/**
|
|
1263
|
-
* Runtime keys mapped to the group they answer with, named by one key of it. Code
|
|
1264
|
-
* generation runs once for runtimes a module hashes alike in, and nothing in a
|
|
1265
|
-
* binary's hash knows which loader will read it — so a binary two runtimes reach
|
|
1266
|
-
* carries one shape into both, and a third runtime sharing another binary with
|
|
1267
|
-
* either is pulled in after them. A key in no group answers as itself. Asked of the
|
|
1268
|
-
* same modules the loaders are created for, and only once per compilation.
|
|
1269
|
-
* @returns {Map<string, string>} runtime key to the group it answers with
|
|
1270
|
-
*/
|
|
1271
|
-
_wasmRuntimeGroups() {
|
|
1272
|
-
if (this._wasmRuntimeGroupsByKey === undefined) {
|
|
1273
|
-
const { chunkGraph } = this.compilation;
|
|
1274
|
-
/** @type {Map<string, string>} */
|
|
1275
|
-
const parent = new Map();
|
|
1276
|
-
/**
|
|
1277
|
-
* @param {string} key runtime key
|
|
1278
|
-
* @returns {string} the key naming its group
|
|
1279
|
-
*/
|
|
1280
|
-
const find = (key) => {
|
|
1281
|
-
let root = key;
|
|
1282
|
-
let seen = parent.get(root);
|
|
1283
|
-
while (seen !== undefined && seen !== root) {
|
|
1284
|
-
root = seen;
|
|
1285
|
-
seen = parent.get(root);
|
|
1286
|
-
}
|
|
1287
|
-
// Path compression keeps a long share chain from costing more than once.
|
|
1288
|
-
let walk = key;
|
|
1289
|
-
let next = parent.get(walk);
|
|
1290
|
-
while (next !== undefined && next !== root) {
|
|
1291
|
-
parent.set(walk, root);
|
|
1292
|
-
walk = next;
|
|
1293
|
-
next = parent.get(walk);
|
|
1294
|
-
}
|
|
1295
|
-
return root;
|
|
1296
|
-
};
|
|
1297
|
-
/** @type {string[]} */
|
|
1298
|
-
const keys = [];
|
|
1299
|
-
/**
|
|
1300
|
-
* @param {RuntimeSpec} runtime a runtime the module is generated for
|
|
1301
|
-
* @returns {void}
|
|
1302
|
-
*/
|
|
1303
|
-
const collectKeys = (runtime) => {
|
|
1304
|
-
forEachRuntime(runtime, (key) => {
|
|
1305
|
-
keys.push(/** @type {string} */ (key));
|
|
1306
|
-
});
|
|
1307
|
-
};
|
|
1308
|
-
for (const module of this.compilation.modules) {
|
|
1309
|
-
if (module.type !== WEBASSEMBLY_MODULE_TYPE_ASYNC) continue;
|
|
1310
|
-
keys.length = 0;
|
|
1311
|
-
for (const runtime of chunkGraph.getModuleRuntimes(module)) {
|
|
1312
|
-
collectKeys(runtime);
|
|
1313
|
-
}
|
|
1314
|
-
for (const key of keys) {
|
|
1315
|
-
if (!parent.has(key)) parent.set(key, key);
|
|
1316
|
-
}
|
|
1317
|
-
// Every runtime this binary reaches answers with the first one.
|
|
1318
|
-
for (let i = 1; i < keys.length; i++) {
|
|
1319
|
-
parent.set(find(keys[i]), find(keys[0]));
|
|
1320
|
-
}
|
|
1321
|
-
}
|
|
1322
|
-
// Flattened once, so a lookup is a single `get` rather than a chain walk.
|
|
1323
|
-
for (const key of parent.keys()) parent.set(key, find(key));
|
|
1324
|
-
this._wasmRuntimeGroupsByKey = parent;
|
|
1325
|
-
}
|
|
1326
|
-
return this._wasmRuntimeGroupsByKey;
|
|
1327
|
-
}
|
|
1328
|
-
|
|
1329
|
-
/**
|
|
1330
|
-
* @param {Map<string, string>} groups runtime key to the group it answers with
|
|
1331
|
-
* @param {string} key a runtime key
|
|
1332
|
-
* @returns {string} the group it answers with, or itself when it shares nothing
|
|
1333
|
-
*/
|
|
1334
|
-
_wasmGroupOf(groups, key) {
|
|
1335
|
-
const group = groups.get(key);
|
|
1336
|
-
// An entry named "" makes "" a runtime key, so test absence, not a falsy value.
|
|
1337
|
-
return group === undefined ? key : group;
|
|
1306
|
+
return this._wasmGroupsOf(runtime).every(
|
|
1307
|
+
(group) => known.get(group) === true
|
|
1308
|
+
);
|
|
1338
1309
|
}
|
|
1339
1310
|
|
|
1340
1311
|
supportTemplateLiteral() {
|
|
@@ -2019,6 +1990,9 @@ class RuntimeTemplate {
|
|
|
2019
1990
|
(m) => chunkGraph.getModuleId(m)
|
|
2020
1991
|
).filter((id) => id !== null);
|
|
2021
1992
|
if (asyncDeps.length) {
|
|
1993
|
+
runtimeRequirements.add(
|
|
1994
|
+
RuntimeGlobals.deferredModuleAsyncTransitiveDependencies
|
|
1995
|
+
);
|
|
2022
1996
|
if (header) {
|
|
2023
1997
|
appending = `.then(${this.basicFunction(
|
|
2024
1998
|
"",
|
|
@@ -2255,11 +2229,14 @@ class RuntimeTemplate {
|
|
|
2255
2229
|
(dependency instanceof HarmonyImportDependency ||
|
|
2256
2230
|
dependency instanceof ImportDependency) &&
|
|
2257
2231
|
ImportPhaseUtils.isDefer(dependency.phase) &&
|
|
2258
|
-
!(
|
|
2232
|
+
!isAsyncExternal(module);
|
|
2259
2233
|
|
|
2260
2234
|
if (isModuleDeferred) {
|
|
2261
2235
|
/** @type {Set<Module>} */
|
|
2262
2236
|
const outgoingAsyncModules = getOutgoingAsyncModules(moduleGraph, module);
|
|
2237
|
+
// A module deferring itself is already evaluating, so awaiting it here
|
|
2238
|
+
// would deadlock; forcing the namespace throws instead.
|
|
2239
|
+
outgoingAsyncModules.delete(originModule);
|
|
2263
2240
|
|
|
2264
2241
|
importContent = `/* deferred harmony import */ ${optDeclaration}${importVar} = ${getOptimizedDeferredModule(
|
|
2265
2242
|
moduleId,
|
|
@@ -2344,7 +2321,7 @@ class RuntimeTemplate {
|
|
|
2344
2321
|
(dependency instanceof HarmonyImportDependency ||
|
|
2345
2322
|
dependency instanceof ImportDependency) &&
|
|
2346
2323
|
ImportPhaseUtils.isDefer(dependency.phase) &&
|
|
2347
|
-
!(
|
|
2324
|
+
!isAsyncExternal(module);
|
|
2348
2325
|
|
|
2349
2326
|
if (defaultInterop) {
|
|
2350
2327
|
// when the defaultInterop is used (when a ESM imports a CJS module),
|
|
@@ -2684,6 +2661,22 @@ class RuntimeTemplate {
|
|
|
2684
2661
|
return `Promise.resolve(${comment.trim()})`;
|
|
2685
2662
|
}
|
|
2686
2663
|
|
|
2664
|
+
/**
|
|
2665
|
+
* Whether any module of `chunk` carries a source type with a chunk handler of its
|
|
2666
|
+
* own, which `.ei` dispatches alongside the javascript one.
|
|
2667
|
+
* @param {Chunk} chunk the chunk being imported
|
|
2668
|
+
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
2669
|
+
* @returns {boolean} true when a handler beyond the javascript one is reached
|
|
2670
|
+
*/
|
|
2671
|
+
_chunkLoadsBeyondJs(chunk, chunkGraph) {
|
|
2672
|
+
for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
|
|
2673
|
+
for (const type of chunkGraph.getModuleSourceTypes(module)) {
|
|
2674
|
+
if (!TYPES_WITHOUT_CHUNK_HANDLER.has(type)) return true;
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
return false;
|
|
2678
|
+
}
|
|
2679
|
+
|
|
2687
2680
|
/**
|
|
2688
2681
|
* For ESM module output, load a single statically-named chunk through the
|
|
2689
2682
|
* `analyzableChunkImport` helper — a literal `import("./chunk.js")` other bundlers
|
|
@@ -2711,30 +2704,15 @@ class RuntimeTemplate {
|
|
|
2711
2704
|
) {
|
|
2712
2705
|
return null;
|
|
2713
2706
|
}
|
|
2714
|
-
// Prefetch/preload children are injected by the runtime `.f` handlers, which `.ei`
|
|
2715
|
-
// runs too — but they attach to `.f`, so it has to exist.
|
|
2716
|
-
const needsHintHandlers =
|
|
2717
|
-
chunk.hasChildByOrder(chunkGraph, "prefetch", true) ||
|
|
2718
|
-
chunk.hasChildByOrder(chunkGraph, "preload", true) ||
|
|
2719
|
-
chunk.hasChildByOrder(chunkGraph, "cssPreload", true);
|
|
2720
2707
|
// `.ei` always performs the import, where `.e` only reaches the javascript
|
|
2721
2708
|
// loader when there is javascript to load. A module federation remote is the
|
|
2722
2709
|
// case that matters: its chunk is emitted by the container's build, not this one.
|
|
2723
2710
|
if (!JavascriptModulesPlugin.chunkHasJs(chunk, chunkGraph)) {
|
|
2724
|
-
this._analyzableBailout(
|
|
2711
|
+
return this._analyzableBailout(
|
|
2725
2712
|
originModule,
|
|
2726
|
-
"this compilation emits no javascript for the chunk, so there is nothing to import"
|
|
2713
|
+
"this compilation emits no javascript for the chunk, so there is nothing to import",
|
|
2714
|
+
null
|
|
2727
2715
|
);
|
|
2728
|
-
return null;
|
|
2729
|
-
}
|
|
2730
|
-
let hasNonJsTypes = false;
|
|
2731
|
-
for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
|
|
2732
|
-
for (const type of chunkGraph.getModuleSourceTypes(module)) {
|
|
2733
|
-
if (!TYPES_WITHOUT_CHUNK_HANDLER.has(type)) {
|
|
2734
|
-
// Loaded by that type's own `.f` handler, which `.ei` still dispatches.
|
|
2735
|
-
hasNonJsTypes = true;
|
|
2736
|
-
}
|
|
2737
|
-
}
|
|
2738
2716
|
}
|
|
2739
2717
|
// Relative to the consuming chunk (`import.meta.url`) for `auto`, else an
|
|
2740
2718
|
// absolute publicPath prefix.
|
|
@@ -2756,9 +2734,15 @@ class RuntimeTemplate {
|
|
|
2756
2734
|
? specifier
|
|
2757
2735
|
: `"./${specifier.slice(1)}`;
|
|
2758
2736
|
runtimeRequirements.add(RuntimeGlobals.analyzableChunkImport);
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2737
|
+
// Prefetch/preload children and every non-javascript source type are loaded by a
|
|
2738
|
+
// `.f` handler, which `.ei` dispatches — but they attach to `.f`, so it has to
|
|
2739
|
+
// exist. The runtime `ensureChunk` around it does not.
|
|
2740
|
+
if (
|
|
2741
|
+
chunk.hasChildByOrder(chunkGraph, "prefetch", true) ||
|
|
2742
|
+
chunk.hasChildByOrder(chunkGraph, "preload", true) ||
|
|
2743
|
+
chunk.hasChildByOrder(chunkGraph, "cssPreload", true) ||
|
|
2744
|
+
this._chunkLoadsBeyondJs(chunk, chunkGraph)
|
|
2745
|
+
) {
|
|
2762
2746
|
runtimeRequirements.add(RuntimeGlobals.ensureChunkHandlers);
|
|
2763
2747
|
}
|
|
2764
2748
|
// Drop-in for `ensureChunk(id)`: the literal `import()` can be statically
|
|
@@ -2928,6 +2912,11 @@ class RuntimeTemplate {
|
|
|
2928
2912
|
/** @type {Set<string>} */
|
|
2929
2913
|
const names = new Set();
|
|
2930
2914
|
let found = false;
|
|
2915
|
+
// Its own copy, since `lastIndex` is walked below; reset by the loop that ends it.
|
|
2916
|
+
const regexp = new RegExp(
|
|
2917
|
+
ANALYZABLE_TOKEN_REGEXP.source,
|
|
2918
|
+
ANALYZABLE_TOKEN_REGEXP.flags
|
|
2919
|
+
);
|
|
2931
2920
|
for (const module of modules) {
|
|
2932
2921
|
if (!results.has(module, chunk.runtime)) continue;
|
|
2933
2922
|
const source = results.getSource(module, chunk.runtime, JAVASCRIPT_TYPE);
|
|
@@ -2937,10 +2926,6 @@ class RuntimeTemplate {
|
|
|
2937
2926
|
carriesFullHash = true;
|
|
2938
2927
|
found = true;
|
|
2939
2928
|
}
|
|
2940
|
-
const regexp = new RegExp(
|
|
2941
|
-
ANALYZABLE_TOKEN_REGEXP.source,
|
|
2942
|
-
ANALYZABLE_TOKEN_REGEXP.flags
|
|
2943
|
-
);
|
|
2944
2929
|
/** @type {RegExpExecArray | null} */
|
|
2945
2930
|
let match;
|
|
2946
2931
|
while ((match = regexp.exec(content)) !== null) {
|
|
@@ -2948,11 +2933,7 @@ class RuntimeTemplate {
|
|
|
2948
2933
|
if (parts === null) continue;
|
|
2949
2934
|
found = true;
|
|
2950
2935
|
for (const [kind, value] of parts) {
|
|
2951
|
-
if (
|
|
2952
|
-
kind === "publicPath" ||
|
|
2953
|
-
kind === "template" ||
|
|
2954
|
-
kind === "unserved"
|
|
2955
|
-
) {
|
|
2936
|
+
if (FULL_HASH_PART_KINDS.has(kind)) {
|
|
2956
2937
|
carriesFullHash = true;
|
|
2957
2938
|
} else if (CHUNK_SPECIFIER_PART_KINDS.has(kind)) {
|
|
2958
2939
|
names.add(String(value));
|
|
@@ -3213,13 +3194,13 @@ class RuntimeTemplate {
|
|
|
3213
3194
|
return template.replace(HASH_IN_FILENAME_GLOBAL, "x");
|
|
3214
3195
|
}
|
|
3215
3196
|
try {
|
|
3216
|
-
return
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3197
|
+
return probeTemplateName(
|
|
3198
|
+
template,
|
|
3199
|
+
chunk,
|
|
3200
|
+
JAVASCRIPT_TYPE,
|
|
3201
|
+
HASH_PROBE,
|
|
3202
|
+
true
|
|
3203
|
+
).replace(HASH_IN_FILENAME_GLOBAL, "x");
|
|
3223
3204
|
} catch (_error) {
|
|
3224
3205
|
// Nothing to report: the naming call is given strictly less than this probe, so
|
|
3225
3206
|
// one that throws here fails the build where the name is actually needed.
|
|
@@ -3311,6 +3292,41 @@ class RuntimeTemplate {
|
|
|
3311
3292
|
: { undo, loaded };
|
|
3312
3293
|
}
|
|
3313
3294
|
|
|
3295
|
+
/**
|
|
3296
|
+
* Static literal specifier (already quoted) for the `new URL(<here>, import.meta.url)`
|
|
3297
|
+
* a worker or worklet entry chunk bakes to, or `null` to keep the runtime form. The
|
|
3298
|
+
* gate and the build are asked together so every call site agrees on both — the
|
|
3299
|
+
* `new Worker(...)` emit, and the resource hint `ResourceHintPlugin` spells for it.
|
|
3300
|
+
* @param {string | undefined} overridePublicPath a `publicPath` set on the worker itself
|
|
3301
|
+
* @param {Chunk} chunk the worker's entry chunk
|
|
3302
|
+
* @param {Module} module the module the reference is emitted into
|
|
3303
|
+
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3304
|
+
* @param {RuntimeRequirements} runtimeRequirements what the consuming chunk needs
|
|
3305
|
+
* @returns {string | null} a quoted literal, or `null` to fall back
|
|
3306
|
+
*/
|
|
3307
|
+
getAnalyzableWorkerUrl(
|
|
3308
|
+
overridePublicPath,
|
|
3309
|
+
chunk,
|
|
3310
|
+
module,
|
|
3311
|
+
chunkGraph,
|
|
3312
|
+
runtimeRequirements
|
|
3313
|
+
) {
|
|
3314
|
+
// Without an id nothing can name the chunk in a stand-in.
|
|
3315
|
+
if (
|
|
3316
|
+
chunk.id === null ||
|
|
3317
|
+
!this.supportsAnalyzable("url", chunkGraph, module)
|
|
3318
|
+
) {
|
|
3319
|
+
return null;
|
|
3320
|
+
}
|
|
3321
|
+
return this._getAnalyzableChunkSpecifier(
|
|
3322
|
+
overridePublicPath,
|
|
3323
|
+
chunk,
|
|
3324
|
+
module,
|
|
3325
|
+
chunkGraph,
|
|
3326
|
+
runtimeRequirements
|
|
3327
|
+
);
|
|
3328
|
+
}
|
|
3329
|
+
|
|
3314
3330
|
/**
|
|
3315
3331
|
* Static literal specifier (already quoted) for a `new URL(<here>, import.meta.url)`
|
|
3316
3332
|
* or `import(<here>)` pointing at `chunk`'s JS file, or `null` when it can't be known
|
|
@@ -3358,33 +3374,30 @@ class RuntimeTemplate {
|
|
|
3358
3374
|
const chunks =
|
|
3359
3375
|
consumingChunks ||
|
|
3360
3376
|
this._moduleChunks(/** @type {Module} */ (consumingModule), chunkGraph);
|
|
3361
|
-
|
|
3362
|
-
// reaches back has no fixed point if both bake, so only the lower id's name does.
|
|
3363
|
-
const cycles =
|
|
3364
|
-
deferred &&
|
|
3365
|
-
this._reachesAny(chunk, chunks) &&
|
|
3366
|
-
!this._namesBeforeAll(chunk, chunks);
|
|
3377
|
+
const namesFirst = this._namesBeforeAll(chunk, chunks);
|
|
3367
3378
|
// An id names the chunk in the stand-in. No reference reaches here without one —
|
|
3368
3379
|
// `blockPromise` drops an id-less chunk before asking, and one the whole build
|
|
3369
3380
|
// keeps has no name to be emitted under — so the guard carries no reason of its
|
|
3370
|
-
// own; it only keeps `null` out of a name.
|
|
3381
|
+
// own; it only keeps `null` out of a name. A pair naming each other is fine here:
|
|
3382
|
+
// `RealContentHashPlugin`, which deferring requires, re-hashes the pair as one
|
|
3383
|
+
// group, so neither hash chases the other.
|
|
3371
3384
|
const canReserve =
|
|
3372
|
-
chunk.id !== null &&
|
|
3385
|
+
chunk.id !== null && this._canDeferAnalyzableName(chunks);
|
|
3373
3386
|
// A content-named consumer bakes anyway when this chunk settles first: the fold
|
|
3374
|
-
// puts the name into its hash. Only what `_foldsWholeName` covers, though
|
|
3375
|
-
|
|
3387
|
+
// puts the name into its hash. Only what `_foldsWholeName` covers, though — and
|
|
3388
|
+
// a pair that reaches back has no fold order, so only the one hashing first does.
|
|
3389
|
+
const canFold = !canReserve && namesFirst;
|
|
3376
3390
|
/**
|
|
3377
3391
|
* @returns {null} always, having recorded why no stand-in may be reserved
|
|
3378
3392
|
*/
|
|
3379
|
-
const cannotReserve = () =>
|
|
3393
|
+
const cannotReserve = () =>
|
|
3380
3394
|
this._analyzableBailout(
|
|
3381
3395
|
consumingModule,
|
|
3382
|
-
|
|
3383
|
-
? "this chunk and the one it references name each other,
|
|
3384
|
-
: DEFER_BAILOUT
|
|
3396
|
+
!namesFirst && this._reachesAny(chunk, chunks)
|
|
3397
|
+
? "this chunk and the one it references name each other, which only optimization.realContentHash could settle"
|
|
3398
|
+
: DEFER_BAILOUT,
|
|
3399
|
+
null
|
|
3385
3400
|
);
|
|
3386
|
-
return null;
|
|
3387
|
-
};
|
|
3388
3401
|
if (deferred && !canReserve && !canFold) return cannotReserve();
|
|
3389
3402
|
const filename = deferred
|
|
3390
3403
|
? ""
|
|
@@ -3483,24 +3496,17 @@ class RuntimeTemplate {
|
|
|
3483
3496
|
// Each knows its own answer, so the fill asks per asset — where each has one,
|
|
3484
3497
|
// and where nothing else goes between the two shapes.
|
|
3485
3498
|
if (relativeBase !== undefined || !this._eachChunkServedOneWay(chunks)) {
|
|
3486
|
-
this._analyzableBailout(module, SERVED_BAILOUT);
|
|
3487
|
-
return null;
|
|
3499
|
+
return this._analyzableBailout(module, SERVED_BAILOUT, null);
|
|
3488
3500
|
}
|
|
3489
3501
|
return [...head, ["unserved", ""]];
|
|
3490
3502
|
}
|
|
3491
3503
|
if (climb !== "" && relativeBase === undefined) return head;
|
|
3492
3504
|
const resolved = resolve();
|
|
3493
3505
|
if (resolved === null) return null;
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
),
|
|
3499
|
-
.../** @type {SpecifierPart[]} */ (
|
|
3500
|
-
relativeBase === undefined ? [] : [["literal", relativeBase]]
|
|
3501
|
-
),
|
|
3502
|
-
...rootedParts(resolved)
|
|
3503
|
-
];
|
|
3506
|
+
if (climb !== "") head.push(["literal", climb]);
|
|
3507
|
+
if (relativeBase !== undefined) head.push(["literal", relativeBase]);
|
|
3508
|
+
head.push(...rootedParts(resolved));
|
|
3509
|
+
return head;
|
|
3504
3510
|
}
|
|
3505
3511
|
|
|
3506
3512
|
/**
|
|
@@ -3626,11 +3632,6 @@ class RuntimeTemplate {
|
|
|
3626
3632
|
) {
|
|
3627
3633
|
const { publicPath } = this.outputOptions;
|
|
3628
3634
|
const chunks = this._moduleChunks(module, chunkGraph);
|
|
3629
|
-
/**
|
|
3630
|
-
* @param {SpecifierPart[]} parts the whole specifier
|
|
3631
|
-
* @returns {string | null} it already quoted, or `null` when no stand-in may be reserved
|
|
3632
|
-
*/
|
|
3633
|
-
const specifier = (parts) => this._specifierOf(parts, chunks, module);
|
|
3634
3635
|
if (bakePublicPath && publicPath !== "auto") {
|
|
3635
3636
|
const prefix = this._analyzablePathPrefix(
|
|
3636
3637
|
module,
|
|
@@ -3638,25 +3639,24 @@ class RuntimeTemplate {
|
|
|
3638
3639
|
chunks,
|
|
3639
3640
|
relativeBase
|
|
3640
3641
|
);
|
|
3641
|
-
|
|
3642
|
+
if (prefix === null) return null;
|
|
3643
|
+
return this._specifierOf([...prefix, ...file], chunks, module);
|
|
3642
3644
|
}
|
|
3643
3645
|
// No public path to place it against, so the `../` path back to the output root
|
|
3644
3646
|
// is the whole prefix. Different depths — no one is right for every asset the
|
|
3645
3647
|
// reference is emitted into, so the deferred pass builds each asset's own.
|
|
3646
3648
|
const { undo } = this._modulePlacement(module, chunkGraph);
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
...file
|
|
3653
|
-
]);
|
|
3649
|
+
/** @type {SpecifierPart[]} */
|
|
3650
|
+
const parts = [undo === null ? ["undo", ""] : ["literal", undo]];
|
|
3651
|
+
if (relativeBase !== undefined) parts.push(["literal", relativeBase]);
|
|
3652
|
+
parts.push(...file);
|
|
3653
|
+
return this._specifierOf(parts, chunks, module);
|
|
3654
3654
|
}
|
|
3655
3655
|
|
|
3656
3656
|
/**
|
|
3657
3657
|
* Static `new URL(<file>, import.meta.url)` for every stylesheet a runtime can load,
|
|
3658
|
-
* keyed by chunk id
|
|
3659
|
-
* `publicPath + getChunkCssFilename(id)` form. Both the runtime module reading them
|
|
3658
|
+
* keyed by chunk id — one that cannot be named leaves the map incomplete, and its
|
|
3659
|
+
* id keeps the runtime `publicPath + getChunkCssFilename(id)` form. Both the runtime module reading them
|
|
3660
3660
|
* and the plugin declaring what it needs ask this, so the two always agree. The
|
|
3661
3661
|
* runtime hands an absolute url string to `link.href`, and so does this — the browser
|
|
3662
3662
|
* resolves the element against the document, which is not where the chunk sits, and
|
|
@@ -3666,7 +3666,7 @@ class RuntimeTemplate {
|
|
|
3666
3666
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3667
3667
|
* @param {ReadOnlyRuntimeRequirements} runtimeRequirements what that chunk needs
|
|
3668
3668
|
* @param {Module=} consumingModule the runtime module, where one exists to report against
|
|
3669
|
-
* @returns {
|
|
3669
|
+
* @returns {AnalyzableChunkUrls | null} the urls, or `null` to keep the runtime form
|
|
3670
3670
|
*/
|
|
3671
3671
|
analyzableCssChunkUrls(
|
|
3672
3672
|
runtimeChunk,
|
|
@@ -3698,14 +3698,14 @@ class RuntimeTemplate {
|
|
|
3698
3698
|
/**
|
|
3699
3699
|
* Static `new URL(<file>, import.meta.url).href` for every javascript chunk a
|
|
3700
3700
|
* runtime can hint at with `<link rel="prefetch"/"modulepreload">`, keyed by chunk
|
|
3701
|
-
* id
|
|
3702
|
-
* `publicPath + getChunkScriptFilename(id)` form. Both the runtime module reading
|
|
3701
|
+
* id — one that cannot be named leaves the map incomplete, and its id keeps the
|
|
3702
|
+
* runtime `publicPath + getChunkScriptFilename(id)` form. Both the runtime module reading
|
|
3703
3703
|
* them and the plugin declaring what it needs ask this, so the two always agree.
|
|
3704
3704
|
* @param {Chunk} runtimeChunk the chunk holding the hint handlers
|
|
3705
3705
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3706
3706
|
* @param {ReadOnlyRuntimeRequirements} runtimeRequirements what that chunk needs
|
|
3707
3707
|
* @param {Module=} consumingModule the runtime module, where one exists to report against
|
|
3708
|
-
* @returns {
|
|
3708
|
+
* @returns {AnalyzableChunkUrls | null} the urls, or `null` to keep the runtime form
|
|
3709
3709
|
*/
|
|
3710
3710
|
analyzableChunkScriptUrls(
|
|
3711
3711
|
runtimeChunk,
|
|
@@ -3722,11 +3722,9 @@ class RuntimeTemplate {
|
|
|
3722
3722
|
);
|
|
3723
3723
|
/** @type {Set<ChunkId>} */
|
|
3724
3724
|
const hinted = new Set();
|
|
3725
|
-
for (const
|
|
3726
|
-
for (const
|
|
3727
|
-
for (const id of
|
|
3728
|
-
hinted.add(id);
|
|
3729
|
-
}
|
|
3725
|
+
for (const byParent of Object.values(orders)) {
|
|
3726
|
+
for (const ids of Object.values(byParent)) {
|
|
3727
|
+
for (const id of ids) hinted.add(id);
|
|
3730
3728
|
}
|
|
3731
3729
|
}
|
|
3732
3730
|
/** @type {Chunk[]} */
|
|
@@ -3746,14 +3744,15 @@ class RuntimeTemplate {
|
|
|
3746
3744
|
|
|
3747
3745
|
/**
|
|
3748
3746
|
* The urls of one asset of each of `chunks`, written out so they can be read by
|
|
3749
|
-
* chunk id
|
|
3747
|
+
* chunk id. A chunk that cannot be named here leaves the map incomplete rather
|
|
3748
|
+
* than losing it — the consumer keeps the runtime form for the ids the map lacks.
|
|
3750
3749
|
* @param {Iterable<Chunk>} chunks the chunks whose asset is wanted
|
|
3751
3750
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3752
3751
|
* @param {Module | undefined} consumingModule the runtime module, where one exists to report against
|
|
3753
3752
|
* @param {Chunk[]} consumingChunks the chunks the urls are written into
|
|
3754
3753
|
* @param {string} sourceType which asset of each chunk to name
|
|
3755
3754
|
* @param {ReadOnlyRuntimeRequirements} runtimeRequirements what the runtime chunk needs
|
|
3756
|
-
* @returns {
|
|
3755
|
+
* @returns {AnalyzableChunkUrls | null} the urls, or `null` to keep the runtime form
|
|
3757
3756
|
*/
|
|
3758
3757
|
_analyzableChunkUrls(
|
|
3759
3758
|
chunks,
|
|
@@ -3773,6 +3772,7 @@ class RuntimeTemplate {
|
|
|
3773
3772
|
}
|
|
3774
3773
|
/** @type {Map<ChunkId, string>} */
|
|
3775
3774
|
const urls = new Map();
|
|
3775
|
+
let complete = true;
|
|
3776
3776
|
for (const chunk of chunks) {
|
|
3777
3777
|
if (chunk.id === null) continue;
|
|
3778
3778
|
const specifier = this._getAnalyzableChunkSpecifier(
|
|
@@ -3784,10 +3784,14 @@ class RuntimeTemplate {
|
|
|
3784
3784
|
consumingChunks,
|
|
3785
3785
|
sourceType
|
|
3786
3786
|
);
|
|
3787
|
-
|
|
3787
|
+
// `_getAnalyzableChunkSpecifier` has already recorded why.
|
|
3788
|
+
if (specifier === null) {
|
|
3789
|
+
complete = false;
|
|
3790
|
+
continue;
|
|
3791
|
+
}
|
|
3788
3792
|
urls.set(chunk.id, `${this.importMetaUrl(specifier)}.href`);
|
|
3789
3793
|
}
|
|
3790
|
-
return urls.size > 0 ? urls : null;
|
|
3794
|
+
return urls.size > 0 ? { urls, complete } : null;
|
|
3791
3795
|
}
|
|
3792
3796
|
|
|
3793
3797
|
/**
|
|
@@ -3852,20 +3856,20 @@ class RuntimeTemplate {
|
|
|
3852
3856
|
try {
|
|
3853
3857
|
// Everything the naming call is given except the hashes, so only a hash can
|
|
3854
3858
|
// make the two answers differ.
|
|
3855
|
-
const template =
|
|
3856
|
-
|
|
3857
|
-
|
|
3859
|
+
const template = probeTemplateName(
|
|
3860
|
+
filenameTemplate,
|
|
3861
|
+
chunk,
|
|
3858
3862
|
contentHashType,
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
const probe =
|
|
3863
|
-
|
|
3864
|
-
|
|
3863
|
+
HASH_PROBE,
|
|
3864
|
+
true
|
|
3865
|
+
);
|
|
3866
|
+
const probe = probeTemplateName(
|
|
3867
|
+
filenameTemplate,
|
|
3868
|
+
chunk,
|
|
3865
3869
|
contentHashType,
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3870
|
+
HASH_PROBE_ALTERNATE,
|
|
3871
|
+
false
|
|
3872
|
+
);
|
|
3869
3873
|
return template === probe ? template : undefined;
|
|
3870
3874
|
} catch (_error) {
|
|
3871
3875
|
// Nothing to report: the probe is given strictly more than the naming call,
|
|
@@ -3882,21 +3886,16 @@ class RuntimeTemplate {
|
|
|
3882
3886
|
* @returns {boolean} true when every runtime reaching it fetches
|
|
3883
3887
|
*/
|
|
3884
3888
|
_wasmModuleFetches(module, chunkGraph) {
|
|
3885
|
-
|
|
3886
|
-
|
|
3889
|
+
const { onlyFetching } = this._wasmGroups();
|
|
3890
|
+
let placed = false;
|
|
3887
3891
|
for (const moduleRuntime of chunkGraph.getModuleRuntimes(module)) {
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3892
|
+
for (const group of this._wasmGroupsOf(moduleRuntime)) {
|
|
3893
|
+
placed = true;
|
|
3894
|
+
if (!onlyFetching.get(group)) return false;
|
|
3895
|
+
}
|
|
3891
3896
|
}
|
|
3892
3897
|
// In no runtime at all nothing named a loader, so `output` answers.
|
|
3893
|
-
|
|
3894
|
-
const only = this._wasmGroupOnlyFetches();
|
|
3895
|
-
const groups = this._wasmRuntimeGroups();
|
|
3896
|
-
for (const key of keys) {
|
|
3897
|
-
if (!only.get(this._wasmGroupOf(groups, key))) return false;
|
|
3898
|
-
}
|
|
3899
|
-
return true;
|
|
3898
|
+
return placed || this.outputOptions.wasmLoading === "fetch";
|
|
3900
3899
|
}
|
|
3901
3900
|
|
|
3902
3901
|
/**
|
|
@@ -4073,6 +4072,18 @@ class RuntimeTemplate {
|
|
|
4073
4072
|
let chunksById;
|
|
4074
4073
|
/** @type {Map<string, Chunk> | undefined} */
|
|
4075
4074
|
let chunkByAsset;
|
|
4075
|
+
/** @type {string | undefined} */
|
|
4076
|
+
let publicPathText;
|
|
4077
|
+
// One value for the whole pass, however many stand-ins read it.
|
|
4078
|
+
const resolvedPublicPath = () => {
|
|
4079
|
+
if (publicPathText === undefined) {
|
|
4080
|
+
publicPathText = compilation.getPath(
|
|
4081
|
+
outputOptions.publicPath || "",
|
|
4082
|
+
{}
|
|
4083
|
+
);
|
|
4084
|
+
}
|
|
4085
|
+
return publicPathText;
|
|
4086
|
+
};
|
|
4076
4087
|
/**
|
|
4077
4088
|
* @param {string} name an emitted asset's name
|
|
4078
4089
|
* @returns {Chunk | undefined} the chunk it was emitted for
|
|
@@ -4127,10 +4138,7 @@ class RuntimeTemplate {
|
|
|
4127
4138
|
{}
|
|
4128
4139
|
);
|
|
4129
4140
|
} else if (kind === "publicPath") {
|
|
4130
|
-
specifier +=
|
|
4131
|
-
outputOptions.publicPath || "",
|
|
4132
|
-
{}
|
|
4133
|
-
);
|
|
4141
|
+
specifier += resolvedPublicPath();
|
|
4134
4142
|
} else if (kind === "unserved") {
|
|
4135
4143
|
const holder = chunkOf(assetName);
|
|
4136
4144
|
if (holder === undefined) return null;
|
|
@@ -4141,10 +4149,7 @@ class RuntimeTemplate {
|
|
|
4141
4149
|
compilation.runtimeTemplate._chunkPlacement(holder).loaded ===
|
|
4142
4150
|
false
|
|
4143
4151
|
) {
|
|
4144
|
-
const path =
|
|
4145
|
-
outputOptions.publicPath || "",
|
|
4146
|
-
{}
|
|
4147
|
-
);
|
|
4152
|
+
const path = resolvedPublicPath();
|
|
4148
4153
|
// The `../` already reached the root this is read from.
|
|
4149
4154
|
specifier += path.startsWith("./") ? path.slice(2) : path;
|
|
4150
4155
|
}
|