webpack 5.110.2 → 5.111.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 +5 -2
- package/lib/APIPlugin.js +23 -7
- package/lib/AutomaticPrefetchPlugin.js +1 -1
- package/lib/Cache.js +8 -3
- package/lib/CacheFacade.js +1 -1
- package/lib/ChunkGraph.js +20 -18
- package/lib/CircularModulesPlugin.js +157 -55
- package/lib/CleanPlugin.js +2 -2
- package/lib/Compilation.js +321 -303
- package/lib/Compiler.js +209 -46
- package/lib/ConcatenationScope.js +25 -35
- package/lib/ContextModule.js +17 -81
- package/lib/ContextModuleFactory.js +1 -1
- package/lib/CopyPlugin.js +1054 -0
- package/lib/DefinePlugin.js +24 -8
- package/lib/DotenvPlugin.js +41 -13
- package/lib/ExternalModule.js +41 -14
- package/lib/FileSystemInfo.js +17 -14
- package/lib/FlagDependencyExportsPlugin.js +45 -21
- package/lib/FlagDependencyUsagePlugin.js +8 -2
- package/lib/HotModuleReplacementPlugin.js +53 -7
- package/lib/JavascriptMetaInfoPlugin.js +5 -3
- package/lib/MainTemplate.js +5 -1
- package/lib/Module.js +16 -7
- package/lib/MultiCompiler.js +1 -1
- package/lib/MultiWatching.js +1 -1
- package/lib/NormalModule.js +58 -32
- package/lib/NormalModuleFactory.js +1 -1
- package/lib/RuntimeGlobals.js +21 -7
- package/lib/RuntimeModule.js +28 -12
- package/lib/RuntimePlugin.js +33 -3
- package/lib/RuntimeTemplate.js +794 -477
- package/lib/SourceMapDevToolPlugin.js +1 -1
- package/lib/Watching.js +9 -0
- package/lib/WebpackOptionsApply.js +84 -91
- package/lib/asset/AssetGenerator.js +25 -8
- package/lib/asset/AssetModule.js +3 -0
- package/lib/asset/WebManifestParser.js +7 -5
- package/lib/async-modules/AsyncModuleHelpers.js +10 -4
- package/lib/cache/AddBuildDependenciesPlugin.js +33 -4
- package/lib/cache/IdleFileCachePlugin.js +2 -2
- package/lib/cache/PackFileCacheStrategy.js +14 -1
- package/lib/config/browserslistTargetHandler.js +19 -0
- package/lib/config/defaults.js +110 -64
- package/lib/config/normalization.js +100 -20
- package/lib/config/target.js +10 -0
- package/lib/container/ContainerReferencePlugin.js +6 -0
- package/lib/container/RemoteRuntimeModule.js +9 -0
- package/lib/container/declaredRemotes.js +39 -0
- package/lib/css/CssGenerator.js +8 -0
- package/lib/css/CssInjectStyleRuntimeModule.js +9 -0
- package/lib/css/CssLoadingRuntimeModule.js +94 -36
- package/lib/css/CssModule.js +1 -1
- package/lib/css/CssModulesPlugin.js +7 -6
- package/lib/css/CssParser.js +144 -11
- package/lib/css/CssServerStylesRuntimeModule.js +9 -0
- package/lib/css/cssMinify.js +11 -3
- package/lib/css/data.js +2814 -678
- package/lib/css/syntax.js +4082 -248
- package/lib/debug/ProfilingPlugin.js +4 -0
- package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -3
- package/lib/dependencies/AMDRuntimeModules.js +18 -0
- package/lib/dependencies/CommonJsExportRequireDependency.js +3 -1
- package/lib/dependencies/CommonJsExportsParserPlugin.js +12 -13
- package/lib/dependencies/CommonJsImportsParserPlugin.js +1 -0
- package/lib/dependencies/CommonJsPlugin.js +19 -3
- package/lib/dependencies/CommonJsRequireDependency.js +32 -9
- package/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +20 -7
- package/lib/dependencies/CssIcssExportDependency.js +7 -1
- package/lib/dependencies/HarmonyCompatibilityDependency.js +58 -4
- package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +8 -3
- package/lib/dependencies/HarmonyExportExpressionDependency.js +44 -29
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +171 -32
- package/lib/dependencies/HarmonyExportInitFragment.js +99 -19
- package/lib/dependencies/HarmonyExportSpecifierDependency.js +18 -30
- package/lib/dependencies/HarmonyImportBareSideEffectDependency.js +59 -0
- package/lib/dependencies/HarmonyImportDependency.js +99 -41
- package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +20 -3
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +24 -1
- package/lib/dependencies/HarmonyModulesPlugin.js +20 -0
- package/lib/dependencies/HtmlEntryDependency.js +62 -2
- package/lib/dependencies/ImportContextDependency.js +43 -3
- package/lib/dependencies/ImportDependency.js +8 -29
- package/lib/dependencies/ImportMetaMainDependency.js +104 -0
- package/lib/dependencies/ImportMetaPlugin.js +59 -15
- package/lib/dependencies/ImportParserPlugin.js +24 -14
- package/lib/dependencies/RequireHeaderDependency.js +20 -21
- package/lib/dependencies/SystemRuntimeModule.js +9 -0
- package/lib/dependencies/WorkerDependency.js +1 -2
- package/lib/dependencies/WorkletDependency.js +1 -2
- package/lib/dependencies/importOptionsCheck.js +47 -0
- package/lib/dll/DelegatedModule.js +18 -1
- package/lib/dll/DllReferencePlugin.js +11 -8
- package/lib/dll/LibManifestPlugin.js +1 -1
- package/lib/errors/AnalyzableBailoutsWarning.js +41 -0
- package/lib/errors/DotenvFileError.js +29 -0
- package/lib/errors/DuplicateModulesWarning.js +12 -7
- package/lib/errors/EmptyCopyPatternWarning.js +26 -0
- package/lib/errors/ExternalStarReexportError.js +44 -0
- package/lib/errors/ImportedBindingAssignmentError.js +30 -0
- package/lib/errors/MissingSourceMapsWarning.js +36 -0
- package/lib/errors/ModuleParseError.js +2 -1
- package/lib/errors/UnusedAssetsWarning.js +36 -0
- package/lib/errors/UnusedFederationWarning.js +35 -0
- package/lib/errors/UnusedModulesWarning.js +38 -0
- package/lib/esm/ExportWebpackRequireRuntimeModule.js +9 -0
- package/lib/esm/ModuleChunkFormatPlugin.js +28 -3
- package/lib/esm/ModuleChunkLoadingPlugin.js +30 -11
- package/lib/esm/ModuleChunkLoadingRuntimeModule.js +92 -60
- package/lib/hmr/HotModuleReplacement.runtime.js +8 -2
- package/lib/hmr/HotModuleReplacementRuntimeModule.js +9 -0
- package/lib/html/HtmlGenerator.js +11 -5
- package/lib/html/HtmlModulesPlugin.js +360 -84
- package/lib/html/HtmlParser.js +13 -6
- package/lib/html/builtinEmbeddedRenderer.js +107 -0
- package/lib/html/data.js +121 -7
- package/lib/html/htmlMinify.js +84 -113
- package/lib/html/syntax.js +1067 -569
- package/lib/ids/HashedModuleIdsPlugin.js +2 -1
- package/lib/index.js +3 -0
- package/lib/javascript/JavascriptModule.js +1 -0
- package/lib/javascript/JavascriptModulesPlugin.js +52 -22
- package/lib/javascript/JavascriptParser.js +1255 -728
- package/lib/javascript/StartupHelpers.js +27 -3
- package/lib/javascript/data.js +172 -0
- package/lib/javascript/grammar.js +5546 -0
- package/lib/javascript/parser.js +1494 -0
- package/lib/javascript/regexp.js +1762 -0
- package/lib/javascript/regexpData.js +51 -0
- package/lib/javascript/syntax.js +8696 -5225
- package/lib/library/ModuleLibraryPlugin.js +116 -5
- package/lib/node/ReadFileChunkLoadingRuntimeModule.js +22 -0
- package/lib/node/RequireChunkLoadingRuntimeModule.js +22 -0
- package/lib/optimize/ConcatenatedModule.js +133 -25
- package/lib/optimize/ConstExportsPlugin.js +50 -39
- package/lib/optimize/InlineExports.js +20 -123
- package/lib/optimize/MangleExportsPlugin.js +10 -0
- package/lib/optimize/ModuleConcatenationPlugin.js +24 -1
- package/lib/optimize/RealContentHashPlugin.js +68 -9
- package/lib/optimize/SideEffectsFlagPlugin.js +17 -9
- package/lib/performance/AnalyzableBailoutsPlugin.js +115 -0
- package/lib/performance/CacheEffectivenessPlugin.js +4 -3
- package/lib/performance/DuplicateModulesPlugin.js +57 -13
- package/lib/performance/EvalUsagePlugin.js +5 -2
- package/lib/performance/MissingSourceMapsPlugin.js +115 -0
- package/lib/performance/PureAnnotationsPlugin.js +6 -3
- package/lib/performance/TopLevelThisPlugin.js +5 -4
- package/lib/performance/UnusedAssetsPlugin.js +109 -0
- package/lib/performance/UnusedFederationPlugin.js +147 -0
- package/lib/performance/UnusedModulesPlugin.js +141 -0
- package/lib/performance/UnusedReexportsPlugin.js +1 -55
- package/lib/performance/isOnlyReexported.js +65 -0
- package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +25 -5
- package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +2 -0
- package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +9 -0
- package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +9 -0
- package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +9 -0
- package/lib/prefetch/ResourceHintPlugin.js +7 -3
- package/lib/prefetch/ResourceHintRuntimeModule.js +9 -0
- package/lib/prefetch/StartupAssetHintRuntimeModule.js +9 -0
- package/lib/rules/RuleSetCompiler.js +211 -4
- package/lib/runtime/AsyncModuleRuntimeModule.js +105 -67
- package/lib/runtime/AutoPublicPathRuntimeModule.js +9 -0
- package/lib/runtime/BaseUriRuntimeModule.js +9 -0
- package/lib/runtime/ChunkNameRuntimeModule.js +9 -0
- package/lib/runtime/EnsureChunkRuntimeModule.js +35 -16
- package/lib/runtime/GetChunkFilenameRuntimeModule.js +9 -0
- package/lib/runtime/GetFullHashRuntimeModule.js +9 -0
- package/lib/runtime/GetMainFilenameRuntimeModule.js +9 -0
- package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +9 -0
- package/lib/runtime/GlobalRuntimeModule.js +9 -0
- package/lib/runtime/HasOwnPropertyRuntimeModule.js +9 -0
- package/lib/runtime/HelperRuntimeModule.js +10 -0
- package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +338 -217
- package/lib/runtime/NonceRuntimeModule.js +9 -0
- package/lib/runtime/OnChunksLoadedRuntimeModule.js +67 -20
- package/lib/runtime/PublicPathRuntimeModule.js +9 -0
- package/lib/runtime/RuntimeIdRuntimeModule.js +9 -0
- package/lib/runtime/SpecNamespaceObjectRuntimeModule.js +90 -0
- package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +9 -0
- package/lib/runtime/StartupEntrypointRuntimeModule.js +9 -0
- package/lib/runtime/SystemContextRuntimeModule.js +9 -0
- package/lib/runtime/ToBinaryRuntimeModule.js +9 -0
- package/lib/schemes/HttpUriPlugin.js +22 -5
- package/lib/serialization/FileMiddleware.js +15 -2
- package/lib/serialization/ObjectMiddleware.js +138 -106
- package/lib/sharing/ConsumeSharedPlugin.js +12 -0
- package/lib/sharing/ConsumeSharedRuntimeModule.js +11 -0
- package/lib/sharing/ShareRuntimeModule.js +9 -0
- package/lib/sharing/declaredShared.js +47 -0
- package/lib/stats/DefaultStatsFactoryPlugin.js +3 -1
- package/lib/stats/DefaultStatsPrinterPlugin.js +3 -0
- package/lib/util/ArrayQueue.js +3 -3
- package/lib/util/SourceProcessor.js +76 -69
- package/lib/util/URLAbsoluteSpecifier.js +3 -1
- package/lib/util/async.js +292 -0
- package/lib/util/buildDiagnostics.js +69 -0
- package/lib/util/conventions.js +5 -1
- package/lib/util/fs.js +27 -1
- package/lib/util/handlerKeys.js +40 -0
- package/lib/util/identifier.js +20 -0
- package/lib/util/internalSerializables.js +6 -0
- package/lib/util/registerExternalSerializer.js +6 -45
- package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +9 -0
- package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +9 -0
- package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +9 -0
- package/lib/web/JsonpChunkLoadingRuntimeModule.js +36 -0
- package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +19 -0
- package/package.json +22 -16
- package/schemas/WebpackOptions.check.js +1 -1
- package/schemas/WebpackOptions.json +388 -76
- package/schemas/plugins/LoaderOptionsPlugin.check.js +1 -1
- package/schemas/plugins/ManifestPlugin.check.js +1 -1
- package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
- package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
- package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
- package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
- package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
- package/schemas/plugins/debug/ProfilingPlugin.check.js +1 -1
- package/schemas/plugins/dll/DllReferencePlugin.check.js +1 -1
- package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +1 -1
- package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
- package/types.d.ts +1440 -331
- package/lib/dependencies/ExportBindingInitFragment.js +0 -191
- package/lib/errors/EntrypointOverlapWarning.js +0 -45
- package/lib/performance/EntrypointOverlapPlugin.js +0 -122
package/lib/RuntimeTemplate.js
CHANGED
|
@@ -9,14 +9,7 @@ const { CachedSource, ReplaceSource } = require("webpack-sources");
|
|
|
9
9
|
const APIPlugin = require("./APIPlugin");
|
|
10
10
|
|
|
11
11
|
const InitFragment = require("./InitFragment");
|
|
12
|
-
const {
|
|
13
|
-
ASSET_TYPE,
|
|
14
|
-
ASSET_URL_TYPE,
|
|
15
|
-
CSS_TYPE,
|
|
16
|
-
HTML_TYPE,
|
|
17
|
-
JAVASCRIPT_TYPE,
|
|
18
|
-
RUNTIME_TYPE
|
|
19
|
-
} = require("./ModuleSourceTypeConstants");
|
|
12
|
+
const { CSS_TYPE, JAVASCRIPT_TYPE } = require("./ModuleSourceTypeConstants");
|
|
20
13
|
const { WEBASSEMBLY_MODULE_TYPE_ASYNC } = require("./ModuleTypeConstants");
|
|
21
14
|
const RuntimeGlobals = require("./RuntimeGlobals");
|
|
22
15
|
const Template = require("./Template");
|
|
@@ -31,6 +24,7 @@ const { InlinedUsedName } = require("./optimize/InlineExports");
|
|
|
31
24
|
const {
|
|
32
25
|
getDeferredCycleModuleIds,
|
|
33
26
|
getDeferredCycleModules,
|
|
27
|
+
getKnownExportNames,
|
|
34
28
|
getMakeDeferredNamespaceModeFromExportsType,
|
|
35
29
|
getOptimizedDeferredModule
|
|
36
30
|
} = require("./runtime/MakeDeferredNamespaceObjectRuntime");
|
|
@@ -42,7 +36,11 @@ const { equals } = require("./util/ArrayHelpers");
|
|
|
42
36
|
const { getScheme } = require("./util/URLAbsoluteSpecifier");
|
|
43
37
|
const { compareIds } = require("./util/comparators");
|
|
44
38
|
const compileBooleanMatcher = require("./util/compileBooleanMatcher");
|
|
45
|
-
const {
|
|
39
|
+
const {
|
|
40
|
+
RESOLVABLE_SPECIFIER_REGEXP,
|
|
41
|
+
getUndoPath,
|
|
42
|
+
toJsStringLiteral
|
|
43
|
+
} = require("./util/identifier");
|
|
46
44
|
const memoize = require("./util/memoize");
|
|
47
45
|
const { propertyAccess, propertyName } = require("./util/property");
|
|
48
46
|
const {
|
|
@@ -55,6 +53,7 @@ const {
|
|
|
55
53
|
const getCssModulesPlugin = memoize(() => require("./css/CssModulesPlugin"));
|
|
56
54
|
// `Compilation` requires this module, so its stage constants are read lazily.
|
|
57
55
|
const getCompilation = memoize(() => require("./Compilation"));
|
|
56
|
+
const getExternalModule = memoize(() => require("./ExternalModule"));
|
|
58
57
|
|
|
59
58
|
/**
|
|
60
59
|
* @typedef {object} ChunkAssetNaming
|
|
@@ -91,6 +90,20 @@ const getTemplatedPathPlugin = memoize(() => require("./TemplatedPathPlugin"));
|
|
|
91
90
|
const getConcatenatedModule = memoize(() =>
|
|
92
91
|
require("./optimize/ConcatenatedModule")
|
|
93
92
|
);
|
|
93
|
+
const getNormalModule = memoize(() => require("./NormalModule"));
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Whether a hot update can re-run the module a reference is emitted into: the HMR
|
|
97
|
+
* plugin marks every normal module, and a concatenated one is read through its root.
|
|
98
|
+
* @param {Module | undefined} module the module a reference is emitted into
|
|
99
|
+
* @returns {boolean} true under HMR
|
|
100
|
+
*/
|
|
101
|
+
const isHotModule = (module) => {
|
|
102
|
+
if (module === undefined) return false;
|
|
103
|
+
const normal =
|
|
104
|
+
module instanceof getConcatenatedModule() ? module.rootModule : module;
|
|
105
|
+
return normal instanceof getNormalModule() && normal.hot;
|
|
106
|
+
};
|
|
94
107
|
|
|
95
108
|
// Any `[hash]`/`[fullhash]`/`[chunkhash]`/`[contenthash]` token, incl. a `:<length>`
|
|
96
109
|
// or `:<digest>[:<length>]` suffix (e.g. `[contenthash:base64:8]`). Its value is only
|
|
@@ -103,6 +116,9 @@ const HASH_PROBE = "0123456789abcdef0123";
|
|
|
103
116
|
const HASH_PROBE_ALTERNATE = "3210fedcba9876543210";
|
|
104
117
|
const HASH_IN_FILENAME_GLOBAL = /\[(?:full|chunk|content)?hash(?::[^\]]+)?\]/g;
|
|
105
118
|
|
|
119
|
+
// What a recorded reason is prefixed with in `stats.optimizationBailout`.
|
|
120
|
+
const ANALYZABLE_BAILOUT_PREFIX = "Analyzable ESM bailout: ";
|
|
121
|
+
|
|
106
122
|
/**
|
|
107
123
|
* @param {SpecifierPart} part one piece of a reserved name
|
|
108
124
|
* @returns {boolean} true when it is text the deferred pass adds nothing to
|
|
@@ -155,21 +171,6 @@ const rootedParts = (parts) =>
|
|
|
155
171
|
]
|
|
156
172
|
: parts;
|
|
157
173
|
|
|
158
|
-
// Types that ride the chunk itself or render their own asset, so no `.f` handler
|
|
159
|
-
// fetches them; every other type may install one, so the map has to exist for it.
|
|
160
|
-
/** @type {Set<string>} */
|
|
161
|
-
const TYPES_WITHOUT_CHUNK_HANDLER = new Set([
|
|
162
|
-
JAVASCRIPT_TYPE,
|
|
163
|
-
RUNTIME_TYPE,
|
|
164
|
-
ASSET_TYPE,
|
|
165
|
-
ASSET_URL_TYPE,
|
|
166
|
-
HTML_TYPE
|
|
167
|
-
]);
|
|
168
|
-
|
|
169
|
-
// Why a name only the deferred pass could settle was not deferred.
|
|
170
|
-
const DEFER_BAILOUT =
|
|
171
|
-
"a hashed name needs optimization.realContentHash, or no emitted javascript named by its content";
|
|
172
|
-
|
|
173
174
|
/**
|
|
174
175
|
* Where a literal is read from — the `../` path back to the output root, and whether
|
|
175
176
|
* the chunk loader fetched the chunk it sits in through `output.publicPath`.
|
|
@@ -178,13 +179,6 @@ const DEFER_BAILOUT =
|
|
|
178
179
|
* @property {boolean | null} loaded whether the chunk loader fetched the chunk
|
|
179
180
|
*/
|
|
180
181
|
|
|
181
|
-
/**
|
|
182
|
-
* @typedef {object} AnalyzableChunkUrls
|
|
183
|
-
* @property {Map<ChunkId, string>} urls the urls that could be written, by chunk id
|
|
184
|
-
* @property {boolean} complete false when some chunk kept the runtime form, whose
|
|
185
|
-
* ids the consumer then still resolves through the runtime name lookup
|
|
186
|
-
*/
|
|
187
|
-
|
|
188
182
|
/**
|
|
189
183
|
* @typedef {object} WasmGroups
|
|
190
184
|
* @property {(key: string) => string} groupOf the group a runtime key answers with
|
|
@@ -216,7 +210,12 @@ const RUNTIME_HASH_ROUND = 2;
|
|
|
216
210
|
|
|
217
211
|
// Why a public path needing a base could not be spelled from the chunk holding it.
|
|
218
212
|
const SERVED_BAILOUT =
|
|
219
|
-
|
|
213
|
+
'this module is in a chunk webpack loads through output.publicPath and in one it does not, so no one path back to the output root fits both (a root-absolute or absolute output.publicPath, or "auto", is read the same from both)';
|
|
214
|
+
|
|
215
|
+
// Why a runtime's url map kept the runtime form under HMR: an update re-ships the
|
|
216
|
+
// runtime module only when its own code changes.
|
|
217
|
+
const HOT_NAME_BAILOUT =
|
|
218
|
+
"a hot update can move this name without changing the runtime module that spells it, so the update would not carry the new one";
|
|
220
219
|
|
|
221
220
|
/**
|
|
222
221
|
* @import {
|
|
@@ -237,8 +236,9 @@ const SERVED_BAILOUT =
|
|
|
237
236
|
* One piece of a name only the deferred pass can spell: text as it stands, the `../`
|
|
238
237
|
* path from the asset it sits in to the output root, a template or `output.publicPath`
|
|
239
238
|
* resolved once the hashes exist, one of the assets the chunk with this id emits, or
|
|
240
|
-
* the base everything else is resolved against once it is spelled.
|
|
241
|
-
*
|
|
239
|
+
* the base everything else is resolved against once it is spelled. A `repair` part
|
|
240
|
+
* spells nothing: it marks a name the repair pass has to bring back in line.
|
|
241
|
+
* @typedef {"literal" | "undo" | "template" | "publicPath" | "unserved" | "chunk" | "cssChunk" | "base" | "repair"} SpecifierPartKind
|
|
242
242
|
*/
|
|
243
243
|
/** @typedef {[SpecifierPartKind, string | number]} SpecifierPart */
|
|
244
244
|
|
|
@@ -250,7 +250,8 @@ const SPECIFIER_PART_KINDS = new Set([
|
|
|
250
250
|
"unserved",
|
|
251
251
|
"base",
|
|
252
252
|
"chunk",
|
|
253
|
-
"cssChunk"
|
|
253
|
+
"cssChunk",
|
|
254
|
+
"repair"
|
|
254
255
|
]);
|
|
255
256
|
|
|
256
257
|
// Only these carry a chunk id, which is the one part value that may be a number.
|
|
@@ -261,7 +262,10 @@ const CHUNK_SPECIFIER_PART_KINDS = new Set(["chunk", "cssChunk"]);
|
|
|
261
262
|
const FULL_HASH_PART_KINDS = new Set(["publicPath", "template", "unserved"]);
|
|
262
263
|
|
|
263
264
|
// What the deferred pass scans for — the other half of what the class spells.
|
|
265
|
+
const ANALYZABLE_TOKEN_PREFIX = "./@@webpackAnalyzableChunk:";
|
|
264
266
|
const ANALYZABLE_TOKEN_REGEXP = /\.\/@@webpackAnalyzableChunk:([\w-]+)@@/g;
|
|
267
|
+
// The same token read back out of one quoted specifier.
|
|
268
|
+
const ANALYZABLE_TOKEN_PAYLOAD = /@@webpackAnalyzableChunk:([\w-]+)@@/;
|
|
265
269
|
|
|
266
270
|
// Stands in for the compilation hash inside an otherwise resolved filename, with the
|
|
267
271
|
// requested length when the placeholder asked for one.
|
|
@@ -304,8 +308,7 @@ const PASS_NAME = "analyzableChunkNaming";
|
|
|
304
308
|
/** @import { Source } from "webpack-sources" */
|
|
305
309
|
/** @import Compiler from "./Compiler" */
|
|
306
310
|
/** @import Chunk, { ChunkFilenameTemplate, ChunkId } from "./Chunk" */
|
|
307
|
-
/** @import
|
|
308
|
-
/** @import ChunkGraph from "./ChunkGraph" */
|
|
311
|
+
/** @import ChunkGraph, { ModuleId } from "./ChunkGraph" */
|
|
309
312
|
/** @import Compilation from "./Compilation" */
|
|
310
313
|
/** @import Dependency from "./Dependency" */
|
|
311
314
|
/** @import ModuleGraph from "./ModuleGraph" */
|
|
@@ -422,6 +425,48 @@ function getGlobalObject(definition) {
|
|
|
422
425
|
return `Object(${trimmed})`;
|
|
423
426
|
}
|
|
424
427
|
|
|
428
|
+
// An async external is a promise, not a module record with an evaluating state.
|
|
429
|
+
const isAsyncExternal = (/** @type {Module} */ module) =>
|
|
430
|
+
Boolean(/** @type {BuildMeta} */ (module.buildMeta).async) &&
|
|
431
|
+
module instanceof getExternalModule();
|
|
432
|
+
|
|
433
|
+
// `createFakeNamespaceObject`'s "merge all properties" bit, the only one that
|
|
434
|
+
// changes which names the namespace it builds carries.
|
|
435
|
+
const MERGE_PROPERTIES_MODE = 2;
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* The imported module decides, never the importer: two importers of one
|
|
439
|
+
* module have to be handed the same namespace object.
|
|
440
|
+
* @param {Module} module the imported module
|
|
441
|
+
* @returns {boolean} true when its namespace has to be a spec exotic object
|
|
442
|
+
*/
|
|
443
|
+
const usesSpecNamespaceObject = (module) =>
|
|
444
|
+
Boolean(module.buildInfo && module.buildInfo.specNamespaceObject);
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* A module with no ESM namespace of its own — JSON, text, CommonJS — has one
|
|
448
|
+
* synthesized at each import site, so there the importer decides.
|
|
449
|
+
* @param {Module=} originModule the module the import is emitted into
|
|
450
|
+
* @returns {boolean} true when a namespace synthesized here has to be a spec object
|
|
451
|
+
*/
|
|
452
|
+
const synthesizesSpecNamespaceObject = (originModule) =>
|
|
453
|
+
originModule !== undefined && usesSpecNamespaceObject(originModule);
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Names the record a synthesized namespace belongs to and the shape it is built in,
|
|
457
|
+
* so every importer of one module reaches the same object and a reloaded module is
|
|
458
|
+
* not handed the namespace of the exports it replaced.
|
|
459
|
+
* @param {ModuleId | null} moduleId id of the imported module
|
|
460
|
+
* @param {number} mode the createFakeNamespaceObject mode the namespace is built with
|
|
461
|
+
* @returns {string} the arguments identifying it, ready to append to the call
|
|
462
|
+
*/
|
|
463
|
+
const synthesizedNamespaceOwner = (moduleId, mode) =>
|
|
464
|
+
moduleId === null
|
|
465
|
+
? ""
|
|
466
|
+
: `, ${RuntimeGlobals.moduleCache}[${JSON.stringify(moduleId)}], ${
|
|
467
|
+
mode & MERGE_PROPERTIES_MODE
|
|
468
|
+
}`;
|
|
469
|
+
|
|
425
470
|
class RuntimeTemplate {
|
|
426
471
|
/**
|
|
427
472
|
* Creates an instance of RuntimeTemplate.
|
|
@@ -441,8 +486,8 @@ class RuntimeTemplate {
|
|
|
441
486
|
(getGlobalObject(outputOptions.globalObject));
|
|
442
487
|
/** @type {string} */
|
|
443
488
|
this.contentHashReplacement = "X".repeat(outputOptions.hashDigestLength);
|
|
444
|
-
/** @type {
|
|
445
|
-
this.
|
|
489
|
+
/** @type {Set<string>} */
|
|
490
|
+
this._analyzableRepairedAssets = new Set();
|
|
446
491
|
/** @type {WeakMap<Chunk, boolean>} */
|
|
447
492
|
this._chunkNamedWithoutContent = new WeakMap();
|
|
448
493
|
/** @type {WeakMap<Chunk, string>} */
|
|
@@ -461,10 +506,18 @@ class RuntimeTemplate {
|
|
|
461
506
|
this._publicPathClimbText = undefined;
|
|
462
507
|
/** @type {WeakMap<Chunk, Placement>} */
|
|
463
508
|
this._placementByChunk = new WeakMap();
|
|
509
|
+
/** @type {WeakMap<Chunk, string>} */
|
|
510
|
+
this._hotUpdateUndoByChunk = new WeakMap();
|
|
511
|
+
/** @type {string | undefined} */
|
|
512
|
+
this._hotUpdateShapeText = undefined;
|
|
464
513
|
/** @type {Map<string, string | null | undefined>} */
|
|
465
514
|
this._entryBaseUriByRuntime = new Map();
|
|
466
515
|
/** @type {WasmGroups | undefined} */
|
|
467
516
|
this._wasmGroupsValue = undefined;
|
|
517
|
+
/** @type {string[] | undefined} */
|
|
518
|
+
this._analyzableBailoutSink = undefined;
|
|
519
|
+
/** @type {Module | undefined} */
|
|
520
|
+
this._analyzableGeneratingModule = undefined;
|
|
468
521
|
/** @type {Map<string, boolean> | undefined} */
|
|
469
522
|
this._wasmAnchorKnownByGroup = undefined;
|
|
470
523
|
}
|
|
@@ -563,6 +616,10 @@ class RuntimeTemplate {
|
|
|
563
616
|
return this.outputOptions.environment.generator;
|
|
564
617
|
}
|
|
565
618
|
|
|
619
|
+
supportsTopLevelAwait() {
|
|
620
|
+
return this.outputOptions.environment.topLevelAwait;
|
|
621
|
+
}
|
|
622
|
+
|
|
566
623
|
supportsOptionalChaining() {
|
|
567
624
|
return this.outputOptions.environment.optionalChaining;
|
|
568
625
|
}
|
|
@@ -611,6 +668,41 @@ class RuntimeTemplate {
|
|
|
611
668
|
return this.outputOptions.environment.modulePreload;
|
|
612
669
|
}
|
|
613
670
|
|
|
671
|
+
/**
|
|
672
|
+
* Whether the deferred fill rewrote a chunk whose hashed name would otherwise go
|
|
673
|
+
* stale, which `RealContentHashPlugin` reads to run — and to repair `[chunkhash]`
|
|
674
|
+
* names — where `optimization.realContentHash` did not ask for it.
|
|
675
|
+
* @returns {boolean} true once the fill has marked such a chunk
|
|
676
|
+
*/
|
|
677
|
+
needsAnalyzableRepair() {
|
|
678
|
+
return this._analyzableRepairedAssets.size > 0;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* The assets the deferred fill rewrote under a name that has to be repaired: an
|
|
683
|
+
* on-demand repair renames only these and whatever names them.
|
|
684
|
+
* @returns {ReadonlySet<string>} their names
|
|
685
|
+
*/
|
|
686
|
+
analyzableRepairedAssets() {
|
|
687
|
+
return this._analyzableRepairedAssets;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* The `devtool` value wrapping a javascript module in `eval(...)`, read through both
|
|
692
|
+
* spellings — a plain string, and the per-asset-type array.
|
|
693
|
+
* @returns {string | undefined} the value, or undefined when no devtool wraps modules
|
|
694
|
+
*/
|
|
695
|
+
_evalWrappingDevtool() {
|
|
696
|
+
const { devtool } = this.compilation.options;
|
|
697
|
+
const items = Array.isArray(devtool)
|
|
698
|
+
? devtool
|
|
699
|
+
: [{ type: "all", use: devtool }];
|
|
700
|
+
for (const { type, use } of items) {
|
|
701
|
+
if (type !== "all" && type !== "javascript") continue;
|
|
702
|
+
if (typeof use === "string" && use.includes("eval")) return use;
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
|
|
614
706
|
/**
|
|
615
707
|
* Whether a reference a foreign bundler can follow without running webpack's runtime
|
|
616
708
|
* may be emitted — the one question every caller asks, in the form it is asking for:
|
|
@@ -660,7 +752,8 @@ class RuntimeTemplate {
|
|
|
660
752
|
APIPlugin.runtimeUsesPublicPathOverride(
|
|
661
753
|
this.compilation,
|
|
662
754
|
scoped ? chunkGraph : undefined,
|
|
663
|
-
placedModule
|
|
755
|
+
placedModule,
|
|
756
|
+
runtime
|
|
664
757
|
)
|
|
665
758
|
) {
|
|
666
759
|
return this._analyzableBailout(
|
|
@@ -672,36 +765,12 @@ class RuntimeTemplate {
|
|
|
672
765
|
|
|
673
766
|
if (form === "import") {
|
|
674
767
|
// Read through a native `import()`, or it is not this feature at all.
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
`output.chunkFormat is ${JSON.stringify(outputOptions.chunkFormat)}, so chunks are not read through a native import()`,
|
|
679
|
-
false
|
|
680
|
-
);
|
|
681
|
-
}
|
|
682
|
-
if (outputOptions.importFunctionName !== "import") {
|
|
683
|
-
return this._analyzableBailout(
|
|
684
|
-
module,
|
|
685
|
-
`output.importFunctionName is ${JSON.stringify(outputOptions.importFunctionName)}, so the call site is not a native import()`,
|
|
686
|
-
false
|
|
687
|
-
);
|
|
688
|
-
}
|
|
689
|
-
// A worker loading its own chunks some other way keeps that runtime; one on
|
|
690
|
-
// `import` uses the same ESM loader as the main graph, so it can be analyzable.
|
|
691
|
-
for (const originChunk of /** @type {ChunkGraph} */ (
|
|
692
|
-
chunkGraph
|
|
693
|
-
).getModuleChunksIterable(/** @type {Module} */ (placedModule))) {
|
|
694
|
-
const entryOptions = originChunk.getEntryOptions();
|
|
695
|
-
if (!entryOptions || !entryOptions.worker) continue;
|
|
696
|
-
// `WorkerAndWorkletPlugin` always seeds this from `output.workerChunkLoading`.
|
|
697
|
-
if (entryOptions.chunkLoading !== "import") {
|
|
698
|
-
return this._analyzableBailout(
|
|
699
|
-
module,
|
|
700
|
-
`this worker loads its chunks with ${JSON.stringify(entryOptions.chunkLoading)}, not "import"`,
|
|
701
|
-
false
|
|
702
|
-
);
|
|
703
|
-
}
|
|
768
|
+
const outputReason = this._chunkImportOutputReason();
|
|
769
|
+
if (outputReason !== null) {
|
|
770
|
+
return this._analyzableBailout(module, outputReason, false);
|
|
704
771
|
}
|
|
772
|
+
// A worker loading its own chunks some other way needs no answer here: it gets
|
|
773
|
+
// a chunk loader of its own, and only the ESM one asks this.
|
|
705
774
|
return true;
|
|
706
775
|
}
|
|
707
776
|
|
|
@@ -714,15 +783,12 @@ class RuntimeTemplate {
|
|
|
714
783
|
if (form === "url-inline") return true;
|
|
715
784
|
// `eval` devtool wraps each module in `eval(...)`, where `import.meta` is a
|
|
716
785
|
// syntax error. Runtime modules are emitted beside them, never wrapped.
|
|
717
|
-
const
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
typeof devtool === "string" &&
|
|
721
|
-
devtool.includes("eval")
|
|
722
|
-
) {
|
|
786
|
+
const evalDevtool =
|
|
787
|
+
form === "url-runtime" ? undefined : this._evalWrappingDevtool();
|
|
788
|
+
if (evalDevtool !== undefined) {
|
|
723
789
|
return this._analyzableBailout(
|
|
724
790
|
module,
|
|
725
|
-
`devtool ${JSON.stringify(
|
|
791
|
+
`devtool ${JSON.stringify(evalDevtool)} wraps the module in eval(), where import.meta does not parse`,
|
|
726
792
|
false
|
|
727
793
|
);
|
|
728
794
|
}
|
|
@@ -740,14 +806,14 @@ class RuntimeTemplate {
|
|
|
740
806
|
|
|
741
807
|
// The rest is the `"wasm"` form: whether the whole binary url can be spelled
|
|
742
808
|
// here, rather than built at runtime under an `import.meta.url` base.
|
|
743
|
-
const { publicPath
|
|
809
|
+
const { publicPath } = outputOptions;
|
|
744
810
|
if (publicPath !== "auto") {
|
|
745
811
|
// A public path that needs no base names the same place from the chunk as from
|
|
746
812
|
// the document, so a literal spells what `fetch` would have reached.
|
|
747
813
|
if (this._publicPathNeedsNoBase()) {
|
|
748
814
|
// Settled no earlier than the hash it reads or is called with, so it is
|
|
749
815
|
// baked only where the deferred pass may finish it.
|
|
750
|
-
if (this._resolvePublicPathPrefix(publicPath
|
|
816
|
+
if (this._resolvePublicPathPrefix(publicPath) === null) {
|
|
751
817
|
return false;
|
|
752
818
|
}
|
|
753
819
|
} else if (
|
|
@@ -761,17 +827,6 @@ class RuntimeTemplate {
|
|
|
761
827
|
);
|
|
762
828
|
}
|
|
763
829
|
}
|
|
764
|
-
// The compilation hash is settled after code generation, so a name carrying one
|
|
765
|
-
// is baked only where the deferred pass can fill it in. `[hash]` is the module's
|
|
766
|
-
// own here, which code generation already knows.
|
|
767
|
-
if (
|
|
768
|
-
getTemplatedPathPlugin()
|
|
769
|
-
.getPresentKinds(/** @type {string} */ (webassemblyModuleFilename))
|
|
770
|
-
.has("fullhash") &&
|
|
771
|
-
!this._canDeferOrBakeFullHash(true, undefined, module)
|
|
772
|
-
) {
|
|
773
|
-
return false;
|
|
774
|
-
}
|
|
775
830
|
return true;
|
|
776
831
|
}
|
|
777
832
|
|
|
@@ -790,38 +845,97 @@ class RuntimeTemplate {
|
|
|
790
845
|
*/
|
|
791
846
|
_analyzableBailout(module, reason, answer) {
|
|
792
847
|
if (module !== undefined && this.outputOptions.module) {
|
|
793
|
-
|
|
848
|
+
// Recorded on the module whose code is being generated, which is the one a
|
|
849
|
+
// cached result is restored for — an inner module of a concatenation is not.
|
|
850
|
+
const target = this._analyzableGeneratingModule || module;
|
|
851
|
+
const text = `${ANALYZABLE_BAILOUT_PREFIX}${reason}`;
|
|
794
852
|
const bailouts =
|
|
795
|
-
this.compilation.moduleGraph.getOptimizationBailout(
|
|
853
|
+
this.compilation.moduleGraph.getOptimizationBailout(target);
|
|
796
854
|
if (!bailouts.includes(text)) bailouts.push(text);
|
|
855
|
+
// Each generation records its own: another runtime's result may be all the
|
|
856
|
+
// cache restores later, so what the graph holds must not hide a reason.
|
|
857
|
+
if (this._analyzableGeneratingModule !== undefined) {
|
|
858
|
+
// The sink exists only once a reason is recorded, so a module that
|
|
859
|
+
// bakes every reference — nearly all of them — allocates nothing here.
|
|
860
|
+
const sink =
|
|
861
|
+
this._analyzableBailoutSink || (this._analyzableBailoutSink = []);
|
|
862
|
+
if (!sink.includes(reason)) sink.push(reason);
|
|
863
|
+
}
|
|
797
864
|
}
|
|
798
865
|
return answer;
|
|
799
866
|
}
|
|
800
867
|
|
|
801
868
|
/**
|
|
802
|
-
*
|
|
803
|
-
*
|
|
804
|
-
*
|
|
805
|
-
*
|
|
806
|
-
* place — with a name like `[name].js` there is nothing to go stale. Asked of the
|
|
807
|
-
* names the chunks actually carry rather than of `output`, so a template nothing is
|
|
808
|
-
* emitted under does not rule the rewrite out and a `chunk.filenameTemplate` does
|
|
809
|
-
* not slip past it.
|
|
810
|
-
* @param {Iterable<Chunk>=} chunks the chunks the stand-in is written into; omit
|
|
811
|
-
* where the answer has to hold for the whole compilation, as it does for a gate a
|
|
812
|
-
* runtime module asks from the other end
|
|
813
|
-
* @returns {boolean} true when deferring is safe
|
|
869
|
+
* Names the module whose code generation starts, so the reasons its references
|
|
870
|
+
* record are handed back by `finishAnalyzableBailouts` and attributed to it.
|
|
871
|
+
* @param {Module} module the module being generated
|
|
872
|
+
* @returns {void}
|
|
814
873
|
*/
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
874
|
+
beginAnalyzableBailouts(module) {
|
|
875
|
+
this._analyzableGeneratingModule = module;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
/**
|
|
879
|
+
* Ends the collection `beginAnalyzableBailouts` started, so the reasons can be
|
|
880
|
+
* stored beside the result and reapplied when the cache restores it.
|
|
881
|
+
* @returns {string[] | undefined} the reasons recorded since, or undefined for none
|
|
882
|
+
*/
|
|
883
|
+
finishAnalyzableBailouts() {
|
|
884
|
+
const sink = this._analyzableBailoutSink;
|
|
885
|
+
this._analyzableGeneratingModule = undefined;
|
|
886
|
+
this._analyzableBailoutSink = undefined;
|
|
887
|
+
return sink;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
/**
|
|
891
|
+
* Reapplies the bailouts a cached code generation result was stored with, so a
|
|
892
|
+
* restored module reports the same reasons a generated one does.
|
|
893
|
+
* @param {Module} module the module the result was restored for
|
|
894
|
+
* @param {string[]} reasons the reasons stored beside it
|
|
895
|
+
* @returns {void}
|
|
896
|
+
*/
|
|
897
|
+
restoreAnalyzableBailouts(module, reasons) {
|
|
898
|
+
const bailouts =
|
|
899
|
+
this.compilation.moduleGraph.getOptimizationBailout(module);
|
|
900
|
+
for (const reason of reasons) {
|
|
901
|
+
const text = `${ANALYZABLE_BAILOUT_PREFIX}${reason}`;
|
|
902
|
+
if (!bailouts.includes(text)) bailouts.push(text);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
/**
|
|
907
|
+
* The reasons a module's references keep the runtime form, as recorded while its
|
|
908
|
+
* code was generated.
|
|
909
|
+
* @param {Module} module the module, a runtime module included
|
|
910
|
+
* @returns {string[]} the reasons, none where every reference bakes
|
|
911
|
+
*/
|
|
912
|
+
analyzableBailoutsOf(module) {
|
|
913
|
+
/** @type {string[]} */
|
|
914
|
+
const reasons = [];
|
|
915
|
+
for (const text of this.compilation.moduleGraph.getOptimizationBailout(
|
|
916
|
+
module
|
|
917
|
+
)) {
|
|
918
|
+
if (
|
|
919
|
+
typeof text === "string" &&
|
|
920
|
+
text.startsWith(ANALYZABLE_BAILOUT_PREFIX)
|
|
921
|
+
) {
|
|
922
|
+
reasons.push(text.slice(ANALYZABLE_BAILOUT_PREFIX.length));
|
|
822
923
|
}
|
|
823
|
-
return this._javascriptNamedWithoutContent;
|
|
824
924
|
}
|
|
925
|
+
return reasons;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
/**
|
|
929
|
+
* Whether a name that code generation cannot settle may be reserved as a stand-in
|
|
930
|
+
* and filled in once the hashes exist without a repair behind it. Substituting
|
|
931
|
+
* rewrites a chunk after its own content hash was taken, so either no emitted
|
|
932
|
+
* javascript may be named by its content — with a name like `[name].js` there is
|
|
933
|
+
* nothing to go stale — or `RealContentHashPlugin` has to bring the two back in
|
|
934
|
+
* line, which is what a name this says no to gets: see `_needsRepair`.
|
|
935
|
+
* @param {Iterable<Chunk>} chunks the chunks the stand-in is written into
|
|
936
|
+
* @returns {boolean} true when no name moves with the bytes the fill leaves
|
|
937
|
+
*/
|
|
938
|
+
_canDeferAnalyzableName(chunks) {
|
|
825
939
|
let found = false;
|
|
826
940
|
for (const chunk of chunks) {
|
|
827
941
|
found = true;
|
|
@@ -832,15 +946,15 @@ class RuntimeTemplate {
|
|
|
832
946
|
}
|
|
833
947
|
|
|
834
948
|
/**
|
|
835
|
-
*
|
|
836
|
-
*
|
|
837
|
-
*
|
|
838
|
-
*
|
|
839
|
-
* @
|
|
949
|
+
* Whether a stand-in written into `chunks` needs the repair pass behind it: their
|
|
950
|
+
* hashed names would otherwise go stale once the fill moves their bytes. The pass
|
|
951
|
+
* is `RealContentHashPlugin`, run on demand where `optimization.realContentHash`
|
|
952
|
+
* did not ask for it, and repairing `[chunkhash]` names too while it is at it.
|
|
953
|
+
* @param {Iterable<Chunk>} chunks the chunks the stand-in is written into
|
|
954
|
+
* @returns {boolean} true when the fill has to mark the name for repair
|
|
840
955
|
*/
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
return this._analyzableBailout(module, DEFER_BAILOUT, false);
|
|
956
|
+
_needsRepair(chunks) {
|
|
957
|
+
return !this._canDeferAnalyzableName(chunks);
|
|
844
958
|
}
|
|
845
959
|
|
|
846
960
|
/**
|
|
@@ -848,37 +962,28 @@ class RuntimeTemplate {
|
|
|
848
962
|
* and a stand-in for the deferred pass where they do not.
|
|
849
963
|
* @param {SpecifierPart[]} parts the whole specifier
|
|
850
964
|
* @param {Iterable<Chunk>} chunks the chunks it is written into
|
|
851
|
-
* @
|
|
852
|
-
* @returns {string | null} it already quoted, or `null` when no stand-in may be
|
|
853
|
-
* reserved
|
|
965
|
+
* @returns {string} it already quoted
|
|
854
966
|
*/
|
|
855
|
-
_specifierOf(parts, chunks
|
|
967
|
+
_specifierOf(parts, chunks) {
|
|
856
968
|
const text = literalText(parts);
|
|
857
969
|
if (text !== null) return toJsStringLiteral(text);
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
) {
|
|
865
|
-
return null;
|
|
866
|
-
}
|
|
867
|
-
return toJsStringLiteral(this._reserveAnalyzableSpecifier(parts));
|
|
970
|
+
// One built out of the compilation hash moves its chunk into the round after
|
|
971
|
+
// that hash, where the name is taken from the filled bytes anyway.
|
|
972
|
+
const repair = !this._partsBakeFullHash(parts) && this._needsRepair(chunks);
|
|
973
|
+
return toJsStringLiteral(
|
|
974
|
+
this._reserveAnalyzableSpecifier(this._markedForRepair(repair, parts))
|
|
975
|
+
);
|
|
868
976
|
}
|
|
869
977
|
|
|
870
978
|
/**
|
|
871
|
-
*
|
|
872
|
-
*
|
|
873
|
-
*
|
|
874
|
-
*
|
|
875
|
-
* @
|
|
876
|
-
* @param {Iterable<Chunk>=} chunks the chunks the stand-in is written into
|
|
877
|
-
* @param {Module=} module the module the reference is emitted into
|
|
878
|
-
* @returns {boolean} true when deferring is safe
|
|
979
|
+
* The parts a stand-in is reserved with, marked where the name it lands in has to
|
|
980
|
+
* be repaired after the fill.
|
|
981
|
+
* @param {boolean} repair what `_needsRepair` answered
|
|
982
|
+
* @param {SpecifierPart[]} parts what the stand-in resolves to
|
|
983
|
+
* @returns {SpecifierPart[]} the parts, marked where the repair is needed
|
|
879
984
|
*/
|
|
880
|
-
|
|
881
|
-
return
|
|
985
|
+
_markedForRepair(repair, parts) {
|
|
986
|
+
return repair ? [["repair", ""], ...parts] : parts;
|
|
882
987
|
}
|
|
883
988
|
|
|
884
989
|
/**
|
|
@@ -1017,7 +1122,7 @@ class RuntimeTemplate {
|
|
|
1017
1122
|
);
|
|
1018
1123
|
}
|
|
1019
1124
|
const chunks = this._moduleChunks(module, chunkGraph);
|
|
1020
|
-
const parts = this._resolvePublicPathPrefix(publicPath
|
|
1125
|
+
const parts = this._resolvePublicPathPrefix(publicPath);
|
|
1021
1126
|
if (parts === null) return null;
|
|
1022
1127
|
// A protocol-relative base names a host but no scheme, and the runtime reads it
|
|
1023
1128
|
// against the chunk's own url to get one — the very url this literal is
|
|
@@ -1026,8 +1131,7 @@ class RuntimeTemplate {
|
|
|
1026
1131
|
if (base.startsWith("//")) {
|
|
1027
1132
|
return this._specifierOf(
|
|
1028
1133
|
[["literal", base], ...rootedParts(parts), ["literal", filename]],
|
|
1029
|
-
chunks
|
|
1030
|
-
module
|
|
1134
|
+
chunks
|
|
1031
1135
|
);
|
|
1032
1136
|
}
|
|
1033
1137
|
if (!isAbsoluteBaseUri(base)) {
|
|
@@ -1059,13 +1163,14 @@ class RuntimeTemplate {
|
|
|
1059
1163
|
);
|
|
1060
1164
|
}
|
|
1061
1165
|
if (text !== null) return toJsStringLiteral(resolved.href);
|
|
1062
|
-
if (!this._canDeferOrBail(chunks, module)) return null;
|
|
1063
1166
|
return toJsStringLiteral(
|
|
1064
|
-
this._reserveAnalyzableSpecifier(
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1167
|
+
this._reserveAnalyzableSpecifier(
|
|
1168
|
+
this._markedForRepair(this._needsRepair(chunks), [
|
|
1169
|
+
["base", base],
|
|
1170
|
+
...parts,
|
|
1171
|
+
["literal", filename]
|
|
1172
|
+
])
|
|
1173
|
+
)
|
|
1069
1174
|
);
|
|
1070
1175
|
}
|
|
1071
1176
|
|
|
@@ -1862,14 +1967,21 @@ class RuntimeTemplate {
|
|
|
1862
1967
|
});
|
|
1863
1968
|
const exportsType = module.getExportsType(chunkGraph.moduleGraph, strict);
|
|
1864
1969
|
switch (exportsType) {
|
|
1865
|
-
case "namespace":
|
|
1866
|
-
|
|
1970
|
+
case "namespace": {
|
|
1971
|
+
const raw = this.moduleRaw({
|
|
1867
1972
|
module,
|
|
1868
1973
|
chunkGraph,
|
|
1869
1974
|
request,
|
|
1870
1975
|
weak,
|
|
1871
1976
|
runtimeRequirements
|
|
1872
1977
|
});
|
|
1978
|
+
|
|
1979
|
+
if (!usesSpecNamespaceObject(module)) return raw;
|
|
1980
|
+
|
|
1981
|
+
runtimeRequirements.add(RuntimeGlobals.specNamespaceObject);
|
|
1982
|
+
|
|
1983
|
+
return `${RuntimeGlobals.specNamespaceObject}(${raw})`;
|
|
1984
|
+
}
|
|
1873
1985
|
case "default-with-named":
|
|
1874
1986
|
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
|
1875
1987
|
return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 3)`;
|
|
@@ -1978,12 +2090,30 @@ class RuntimeTemplate {
|
|
|
1978
2090
|
|
|
1979
2091
|
let mode = getMakeDeferredNamespaceModeFromExportsType(exportsType);
|
|
1980
2092
|
if (mode) mode = `${mode} | 16`;
|
|
2093
|
+
// The spec's namespace keys are the sorted exports, so hand them over
|
|
2094
|
+
// when they are fully known; otherwise the runtime stays permissive.
|
|
2095
|
+
const deferredExportNames = getKnownExportNames(
|
|
2096
|
+
chunkGraph.moduleGraph,
|
|
2097
|
+
module,
|
|
2098
|
+
exportsType
|
|
2099
|
+
);
|
|
2100
|
+
runtimeRequirements.add(
|
|
2101
|
+
deferredExportNames
|
|
2102
|
+
? RuntimeGlobals.hasSealedDeferredNamespace
|
|
2103
|
+
: RuntimeGlobals.hasSynthesizedDeferredNamespace
|
|
2104
|
+
);
|
|
2105
|
+
mode += deferredExportNames
|
|
2106
|
+
? `, ${JSON.stringify(deferredExportNames)}`
|
|
2107
|
+
: "";
|
|
1981
2108
|
|
|
1982
2109
|
const asyncDeps = Array.from(
|
|
1983
2110
|
getOutgoingAsyncModules(chunkGraph.moduleGraph, module),
|
|
1984
2111
|
(m) => chunkGraph.getModuleId(m)
|
|
1985
2112
|
).filter((id) => id !== null);
|
|
1986
2113
|
if (asyncDeps.length) {
|
|
2114
|
+
runtimeRequirements.add(
|
|
2115
|
+
RuntimeGlobals.deferredModuleAsyncTransitiveDependencies
|
|
2116
|
+
);
|
|
1987
2117
|
if (header) {
|
|
1988
2118
|
appending = `.then(${this.basicFunction(
|
|
1989
2119
|
"",
|
|
@@ -2018,15 +2148,22 @@ class RuntimeTemplate {
|
|
|
2018
2148
|
} else {
|
|
2019
2149
|
let fakeType = 16;
|
|
2020
2150
|
switch (exportsType) {
|
|
2021
|
-
case "namespace":
|
|
2022
|
-
|
|
2023
|
-
|
|
2151
|
+
case "namespace": {
|
|
2152
|
+
const specNamespace = usesSpecNamespaceObject(module);
|
|
2153
|
+
const asyncModule = chunkGraph.moduleGraph.isAsync(module);
|
|
2154
|
+
if (header || (specNamespace && !asyncModule)) {
|
|
2155
|
+
let rawModule = this.moduleRaw({
|
|
2024
2156
|
module,
|
|
2025
2157
|
chunkGraph,
|
|
2026
2158
|
request,
|
|
2027
2159
|
weak,
|
|
2028
2160
|
runtimeRequirements
|
|
2029
2161
|
});
|
|
2162
|
+
if (specNamespace && !asyncModule) {
|
|
2163
|
+
runtimeRequirements.add(RuntimeGlobals.specNamespaceObject);
|
|
2164
|
+
// Wrap before promise resolution assimilates an exported `then`.
|
|
2165
|
+
rawModule = `${RuntimeGlobals.specNamespaceObject}(${rawModule})`;
|
|
2166
|
+
}
|
|
2030
2167
|
appending = `.then(${this.basicFunction(
|
|
2031
2168
|
"",
|
|
2032
2169
|
`${header}return ${rawModule};`
|
|
@@ -2038,7 +2175,14 @@ class RuntimeTemplate {
|
|
|
2038
2175
|
`${comment}${idExpr}`
|
|
2039
2176
|
)})`;
|
|
2040
2177
|
}
|
|
2178
|
+
|
|
2179
|
+
if (specNamespace && asyncModule) {
|
|
2180
|
+
runtimeRequirements.add(RuntimeGlobals.specNamespaceObject);
|
|
2181
|
+
appending += `.then(${RuntimeGlobals.specNamespaceObject})`;
|
|
2182
|
+
}
|
|
2183
|
+
|
|
2041
2184
|
break;
|
|
2185
|
+
}
|
|
2042
2186
|
case "dynamic":
|
|
2043
2187
|
fakeType |= 4;
|
|
2044
2188
|
/* fall through */
|
|
@@ -2092,6 +2236,15 @@ class RuntimeTemplate {
|
|
|
2092
2236
|
)})`;
|
|
2093
2237
|
}
|
|
2094
2238
|
}
|
|
2239
|
+
if (synthesizesSpecNamespaceObject(originModule)) {
|
|
2240
|
+
runtimeRequirements.add(RuntimeGlobals.specNamespaceObject);
|
|
2241
|
+
runtimeRequirements.add(RuntimeGlobals.moduleCache);
|
|
2242
|
+
const owner = synthesizedNamespaceOwner(moduleId, fakeType);
|
|
2243
|
+
appending += `.then(${this.returningFunction(
|
|
2244
|
+
`${RuntimeGlobals.specNamespaceObject}(m${owner})`,
|
|
2245
|
+
"m"
|
|
2246
|
+
)})`;
|
|
2247
|
+
}
|
|
2095
2248
|
break;
|
|
2096
2249
|
}
|
|
2097
2250
|
}
|
|
@@ -2220,11 +2373,14 @@ class RuntimeTemplate {
|
|
|
2220
2373
|
(dependency instanceof HarmonyImportDependency ||
|
|
2221
2374
|
dependency instanceof ImportDependency) &&
|
|
2222
2375
|
ImportPhaseUtils.isDefer(dependency.phase) &&
|
|
2223
|
-
!(
|
|
2376
|
+
!isAsyncExternal(module);
|
|
2224
2377
|
|
|
2225
2378
|
if (isModuleDeferred) {
|
|
2226
2379
|
/** @type {Set<Module>} */
|
|
2227
2380
|
const outgoingAsyncModules = getOutgoingAsyncModules(moduleGraph, module);
|
|
2381
|
+
// A module deferring itself is already evaluating, so awaiting it here
|
|
2382
|
+
// would deadlock; forcing the namespace throws instead.
|
|
2383
|
+
outgoingAsyncModules.delete(originModule);
|
|
2228
2384
|
|
|
2229
2385
|
importContent = `/* deferred harmony import */ ${optDeclaration}${importVar} = ${getOptimizedDeferredModule(
|
|
2230
2386
|
moduleId,
|
|
@@ -2309,7 +2465,7 @@ class RuntimeTemplate {
|
|
|
2309
2465
|
(dependency instanceof HarmonyImportDependency ||
|
|
2310
2466
|
dependency instanceof ImportDependency) &&
|
|
2311
2467
|
ImportPhaseUtils.isDefer(dependency.phase) &&
|
|
2312
|
-
!(
|
|
2468
|
+
!isAsyncExternal(module);
|
|
2313
2469
|
|
|
2314
2470
|
if (defaultInterop) {
|
|
2315
2471
|
// when the defaultInterop is used (when a ESM imports a CJS module),
|
|
@@ -2395,16 +2551,38 @@ class RuntimeTemplate {
|
|
|
2395
2551
|
`${importVar}_namespace_cache`
|
|
2396
2552
|
)
|
|
2397
2553
|
);
|
|
2554
|
+
const fakeMode = exportsType === "default-only" ? 0 : 2;
|
|
2555
|
+
const fakeArguments = fakeMode === 0 ? "" : ", 2";
|
|
2556
|
+
let fakeNamespace = `${RuntimeGlobals.createFakeNamespaceObject}(${importVar}${fakeArguments})`;
|
|
2557
|
+
if (synthesizesSpecNamespaceObject(originModule)) {
|
|
2558
|
+
runtimeRequirements.add(RuntimeGlobals.specNamespaceObject);
|
|
2559
|
+
runtimeRequirements.add(RuntimeGlobals.moduleCache);
|
|
2560
|
+
const owner = synthesizedNamespaceOwner(
|
|
2561
|
+
chunkGraph.getModuleId(module),
|
|
2562
|
+
fakeMode
|
|
2563
|
+
);
|
|
2564
|
+
fakeNamespace = `${RuntimeGlobals.specNamespaceObject}(${fakeNamespace}${owner})`;
|
|
2565
|
+
}
|
|
2398
2566
|
return `/*#__PURE__*/ ${
|
|
2399
2567
|
asiSafe ? "" : asiSafe === false ? ";" : "Object"
|
|
2400
|
-
}(${importVar}_namespace_cache || (${importVar}_namespace_cache = ${
|
|
2401
|
-
RuntimeGlobals.createFakeNamespaceObject
|
|
2402
|
-
}(${importVar}${exportsType === "default-only" ? "" : ", 2"})))`;
|
|
2568
|
+
}(${importVar}_namespace_cache || (${importVar}_namespace_cache = ${fakeNamespace}))`;
|
|
2403
2569
|
}
|
|
2404
2570
|
}
|
|
2405
2571
|
|
|
2406
2572
|
if (exportName.length > 0) {
|
|
2407
2573
|
const exportsInfo = moduleGraph.getExportsInfo(module);
|
|
2574
|
+
// A name the module does not export is the namespace's to answer — reading
|
|
2575
|
+
// it is undefined and writing it fails — not the exports object's.
|
|
2576
|
+
if (
|
|
2577
|
+
!isModuleDeferred &&
|
|
2578
|
+
usesSpecNamespaceObject(module) &&
|
|
2579
|
+
exportsInfo.isExportProvided(exportName) === false
|
|
2580
|
+
) {
|
|
2581
|
+
runtimeRequirements.add(RuntimeGlobals.specNamespaceObject);
|
|
2582
|
+
const ns = `${RuntimeGlobals.specNamespaceObject}(${importVar})`;
|
|
2583
|
+
|
|
2584
|
+
return `${ns}${propertyAccess(exportName)}`;
|
|
2585
|
+
}
|
|
2408
2586
|
// in some case the exported item is renamed (get this by getUsedName). for example,
|
|
2409
2587
|
// x.default might be emitted as x.Z (default is renamed to Z)
|
|
2410
2588
|
const used = exportsInfo.getUsedName(exportName, runtime);
|
|
@@ -2449,9 +2627,19 @@ class RuntimeTemplate {
|
|
|
2449
2627
|
runtimeRequirements.add(RuntimeGlobals.makeDeferredNamespaceObject);
|
|
2450
2628
|
const id = chunkGraph.getModuleId(module);
|
|
2451
2629
|
const type = getMakeDeferredNamespaceModeFromExportsType(exportsType);
|
|
2452
|
-
const
|
|
2453
|
-
|
|
2454
|
-
|
|
2630
|
+
const names = getKnownExportNames(
|
|
2631
|
+
chunkGraph.moduleGraph,
|
|
2632
|
+
module,
|
|
2633
|
+
exportsType
|
|
2634
|
+
);
|
|
2635
|
+
runtimeRequirements.add(
|
|
2636
|
+
names
|
|
2637
|
+
? RuntimeGlobals.hasSealedDeferredNamespace
|
|
2638
|
+
: RuntimeGlobals.hasSynthesizedDeferredNamespace
|
|
2639
|
+
);
|
|
2640
|
+
const init = `${RuntimeGlobals.makeDeferredNamespaceObject}(${JSON.stringify(
|
|
2641
|
+
id
|
|
2642
|
+
)}, ${type}${names ? `, ${JSON.stringify(names)}` : ""})`;
|
|
2455
2643
|
|
|
2456
2644
|
return `/*#__PURE__*/ ${
|
|
2457
2645
|
asiSafe ? "" : asiSafe === false ? ";" : "Object"
|
|
@@ -2478,6 +2666,16 @@ class RuntimeTemplate {
|
|
|
2478
2666
|
// if we hit here, the importVar is either
|
|
2479
2667
|
// - already a ES module namespace object
|
|
2480
2668
|
// - or imported by a way that does not need interop.
|
|
2669
|
+
if (
|
|
2670
|
+
exportsType === "namespace" &&
|
|
2671
|
+
exportName.length === 0 &&
|
|
2672
|
+
usesSpecNamespaceObject(module)
|
|
2673
|
+
) {
|
|
2674
|
+
runtimeRequirements.add(RuntimeGlobals.specNamespaceObject);
|
|
2675
|
+
|
|
2676
|
+
return `${RuntimeGlobals.specNamespaceObject}(${importVar})`;
|
|
2677
|
+
}
|
|
2678
|
+
|
|
2481
2679
|
return importVar;
|
|
2482
2680
|
}
|
|
2483
2681
|
|
|
@@ -2558,7 +2756,7 @@ class RuntimeTemplate {
|
|
|
2558
2756
|
* @param {string} options.message the message
|
|
2559
2757
|
* @param {ChunkGraph} options.chunkGraph the chunk graph
|
|
2560
2758
|
* @param {RuntimeRequirements} options.runtimeRequirements if set, will be filled with runtime requirements
|
|
2561
|
-
* @param {Module=} options.originModule the module the `import()` is emitted into
|
|
2759
|
+
* @param {Module=} options.originModule the module the `import()` is emitted into, to report against
|
|
2562
2760
|
* @returns {string} expression
|
|
2563
2761
|
*/
|
|
2564
2762
|
blockPromise({
|
|
@@ -2588,156 +2786,32 @@ class RuntimeTemplate {
|
|
|
2588
2786
|
message,
|
|
2589
2787
|
chunkName: block.chunkName
|
|
2590
2788
|
});
|
|
2591
|
-
//
|
|
2592
|
-
//
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
if (chunks.length === 1) {
|
|
2598
|
-
const analyzable = this.analyzableChunkImport(
|
|
2599
|
-
chunks[0],
|
|
2600
|
-
comment,
|
|
2601
|
-
runtimeRequirements,
|
|
2602
|
-
originModule,
|
|
2603
|
-
chunkGraph
|
|
2604
|
-
);
|
|
2605
|
-
if (analyzable !== null) {
|
|
2606
|
-
return analyzable;
|
|
2607
|
-
}
|
|
2608
|
-
const chunkId = JSON.stringify(chunks[0].id);
|
|
2609
|
-
runtimeRequirements.add(RuntimeGlobals.ensureChunk);
|
|
2610
|
-
|
|
2611
|
-
if (fetchPriority) {
|
|
2612
|
-
runtimeRequirements.add(RuntimeGlobals.hasFetchPriority);
|
|
2613
|
-
}
|
|
2614
|
-
|
|
2615
|
-
return `${RuntimeGlobals.ensureChunk}(${comment}${chunkId}${
|
|
2616
|
-
fetchPriority ? `, ${JSON.stringify(fetchPriority)}` : ""
|
|
2617
|
-
})`;
|
|
2618
|
-
} else if (chunks.length > 0) {
|
|
2619
|
-
let needEnsureChunk = false;
|
|
2620
|
-
/**
|
|
2621
|
-
* Analyzable `import()` for a solely-owned JS chunk, else runtime ensureChunk.
|
|
2622
|
-
* @param {Chunk} chunk chunk
|
|
2623
|
-
* @returns {string} require chunk id code
|
|
2624
|
-
*/
|
|
2625
|
-
const requireChunkId = (chunk) => {
|
|
2626
|
-
const analyzable = this.analyzableChunkImport(
|
|
2627
|
-
chunk,
|
|
2628
|
-
"",
|
|
2629
|
-
runtimeRequirements,
|
|
2630
|
-
originModule,
|
|
2631
|
-
chunkGraph
|
|
2632
|
-
);
|
|
2633
|
-
if (analyzable !== null) return analyzable;
|
|
2634
|
-
needEnsureChunk = true;
|
|
2635
|
-
return `${RuntimeGlobals.ensureChunk}(${JSON.stringify(chunk.id)}${
|
|
2636
|
-
fetchPriority ? `, ${JSON.stringify(fetchPriority)}` : ""
|
|
2637
|
-
})`;
|
|
2638
|
-
};
|
|
2639
|
-
const items = chunks.map(requireChunkId);
|
|
2640
|
-
if (needEnsureChunk) {
|
|
2641
|
-
runtimeRequirements.add(RuntimeGlobals.ensureChunk);
|
|
2642
|
-
// Only needed when an `ensureChunk(id, priority)` call is actually emitted.
|
|
2643
|
-
if (fetchPriority) {
|
|
2644
|
-
runtimeRequirements.add(RuntimeGlobals.hasFetchPriority);
|
|
2645
|
-
}
|
|
2646
|
-
}
|
|
2647
|
-
return `Promise.all(${comment.trim()}[${items.join(", ")}])`;
|
|
2648
|
-
}
|
|
2649
|
-
return `Promise.resolve(${comment.trim()})`;
|
|
2650
|
-
}
|
|
2651
|
-
|
|
2652
|
-
/**
|
|
2653
|
-
* Whether any module of `chunk` carries a source type with a chunk handler of its
|
|
2654
|
-
* own, which `.ei` dispatches alongside the javascript one.
|
|
2655
|
-
* @param {Chunk} chunk the chunk being imported
|
|
2656
|
-
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
2657
|
-
* @returns {boolean} true when a handler beyond the javascript one is reached
|
|
2658
|
-
*/
|
|
2659
|
-
_chunkLoadsBeyondJs(chunk, chunkGraph) {
|
|
2660
|
-
for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
|
|
2661
|
-
for (const type of chunkGraph.getModuleSourceTypes(module)) {
|
|
2662
|
-
if (!TYPES_WITHOUT_CHUNK_HANDLER.has(type)) return true;
|
|
2789
|
+
// An output that cannot use a native `import()` gets no ESM chunk loader to ask,
|
|
2790
|
+
// so the reason is recorded here, where any build generates its imports.
|
|
2791
|
+
if (this.outputOptions.module && originModule !== undefined) {
|
|
2792
|
+
const outputReason = this._chunkImportOutputReason();
|
|
2793
|
+
if (outputReason !== null) {
|
|
2794
|
+
this._analyzableBailout(originModule, outputReason, false);
|
|
2663
2795
|
}
|
|
2664
2796
|
}
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
* @param {Chunk} chunk the chunk to load
|
|
2674
|
-
* @param {string} comment leading comment (chunk name / message)
|
|
2675
|
-
* @param {RuntimeRequirements} runtimeRequirements runtime requirements
|
|
2676
|
-
* @param {Module | undefined} originModule the module the `import()` is emitted into
|
|
2677
|
-
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
2678
|
-
* @returns {string | null} the import expression, or `null`
|
|
2679
|
-
*/
|
|
2680
|
-
analyzableChunkImport(
|
|
2681
|
-
chunk,
|
|
2682
|
-
comment,
|
|
2683
|
-
runtimeRequirements,
|
|
2684
|
-
originModule,
|
|
2685
|
-
chunkGraph
|
|
2686
|
-
) {
|
|
2687
|
-
// `blockPromise` has already dropped any chunk without an id. Without an origin
|
|
2688
|
-
// there is nothing the specifier could be relative to.
|
|
2689
|
-
if (
|
|
2690
|
-
!originModule ||
|
|
2691
|
-
!this.supportsAnalyzable("import", chunkGraph, originModule)
|
|
2692
|
-
) {
|
|
2693
|
-
return null;
|
|
2797
|
+
const fetchPriority = chunkGroup.options.fetchPriority;
|
|
2798
|
+
const priorityArg = fetchPriority
|
|
2799
|
+
? `, ${JSON.stringify(fetchPriority)}`
|
|
2800
|
+
: "";
|
|
2801
|
+
if (chunks.length === 0) return `Promise.resolve(${comment.trim()})`;
|
|
2802
|
+
runtimeRequirements.add(RuntimeGlobals.ensureChunk);
|
|
2803
|
+
if (fetchPriority) {
|
|
2804
|
+
runtimeRequirements.add(RuntimeGlobals.hasFetchPriority);
|
|
2694
2805
|
}
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
if (!JavascriptModulesPlugin.chunkHasJs(chunk, chunkGraph)) {
|
|
2699
|
-
return this._analyzableBailout(
|
|
2700
|
-
originModule,
|
|
2701
|
-
"this compilation emits no javascript for the chunk, so there is nothing to import",
|
|
2702
|
-
null
|
|
2703
|
-
);
|
|
2806
|
+
if (chunks.length === 1) {
|
|
2807
|
+
const chunkId = JSON.stringify(chunks[0].id);
|
|
2808
|
+
return `${RuntimeGlobals.ensureChunk}(${comment}${chunkId}${priorityArg})`;
|
|
2704
2809
|
}
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
undefined,
|
|
2709
|
-
chunk,
|
|
2710
|
-
originModule,
|
|
2711
|
-
chunkGraph
|
|
2810
|
+
const items = chunks.map(
|
|
2811
|
+
(chunk) =>
|
|
2812
|
+
`${RuntimeGlobals.ensureChunk}(${JSON.stringify(chunk.id)}${priorityArg})`
|
|
2712
2813
|
);
|
|
2713
|
-
|
|
2714
|
-
return null;
|
|
2715
|
-
}
|
|
2716
|
-
// `import()` needs a resolvable specifier — relative (`./`, `../`), absolute (`/`)
|
|
2717
|
-
// or a URL scheme. A bare one is a package name, so make it explicitly relative
|
|
2718
|
-
// the way the chunk loader does. (`new URL(...)` callers accept bare vs their base.)
|
|
2719
|
-
const resolvableSpecifier = /^"(?:\.{0,2}\/|[a-zA-Z][\w+.-]*:)/.test(
|
|
2720
|
-
specifier
|
|
2721
|
-
)
|
|
2722
|
-
? specifier
|
|
2723
|
-
: `"./${specifier.slice(1)}`;
|
|
2724
|
-
runtimeRequirements.add(RuntimeGlobals.analyzableChunkImport);
|
|
2725
|
-
// Prefetch/preload children and every non-javascript source type are loaded by a
|
|
2726
|
-
// `.f` handler, which `.ei` dispatches — but they attach to `.f`, so it has to
|
|
2727
|
-
// exist. The runtime `ensureChunk` around it does not.
|
|
2728
|
-
if (
|
|
2729
|
-
chunk.hasChildByOrder(chunkGraph, "prefetch", true) ||
|
|
2730
|
-
chunk.hasChildByOrder(chunkGraph, "preload", true) ||
|
|
2731
|
-
chunk.hasChildByOrder(chunkGraph, "cssPreload", true) ||
|
|
2732
|
-
this._chunkLoadsBeyondJs(chunk, chunkGraph)
|
|
2733
|
-
) {
|
|
2734
|
-
runtimeRequirements.add(RuntimeGlobals.ensureChunkHandlers);
|
|
2735
|
-
}
|
|
2736
|
-
// Drop-in for `ensureChunk(id)`: the literal `import()` can be statically
|
|
2737
|
-
// followed, the helper keeps webpack's install timing and deduplication.
|
|
2738
|
-
return `${RuntimeGlobals.analyzableChunkImport}(${JSON.stringify(
|
|
2739
|
-
chunk.id
|
|
2740
|
-
)}, ${this.returningFunction(`import(${comment}${resolvableSpecifier})`)})`;
|
|
2814
|
+
return `Promise.all(${comment.trim()}[${items.join(", ")}])`;
|
|
2741
2815
|
}
|
|
2742
2816
|
|
|
2743
2817
|
/**
|
|
@@ -2773,6 +2847,17 @@ class RuntimeTemplate {
|
|
|
2773
2847
|
const late = this._settlesLate(chunk);
|
|
2774
2848
|
if (late !== this._settlesLate(target)) return !late;
|
|
2775
2849
|
}
|
|
2850
|
+
return this._hashRoundBefore(chunk, target);
|
|
2851
|
+
}
|
|
2852
|
+
|
|
2853
|
+
/**
|
|
2854
|
+
* Whether the four rounds alone settle `chunk` before `target`, leaving out what the
|
|
2855
|
+
* full-hash marks move: the order a runtime module generated in its chunk's round sees.
|
|
2856
|
+
* @param {Chunk} chunk the chunk whose hash would be read
|
|
2857
|
+
* @param {Chunk} target the chunk reading it
|
|
2858
|
+
* @returns {boolean} true when the hash exists by the time the target is hashed
|
|
2859
|
+
*/
|
|
2860
|
+
_hashRoundBefore(chunk, target) {
|
|
2776
2861
|
const chunkGraph = /** @type {ChunkGraph} */ (this.compilation.chunkGraph);
|
|
2777
2862
|
const round = hashRound(chunk, chunkGraph);
|
|
2778
2863
|
const targetRound = hashRound(target, chunkGraph);
|
|
@@ -2795,6 +2880,42 @@ class RuntimeTemplate {
|
|
|
2795
2880
|
);
|
|
2796
2881
|
}
|
|
2797
2882
|
|
|
2883
|
+
/**
|
|
2884
|
+
* Whether a `[chunkhash]`/`[contenthash]` name is settled before every chunk it is
|
|
2885
|
+
* written into, so a runtime module generated in its chunk's round can spell it.
|
|
2886
|
+
* @param {Chunk} chunk the chunk named
|
|
2887
|
+
* @param {string} template what names it
|
|
2888
|
+
* @param {Iterable<Chunk>} targets the chunks the name is written into
|
|
2889
|
+
* @returns {boolean} true when the hashes it reads exist by then
|
|
2890
|
+
*/
|
|
2891
|
+
_hashedNameSettledBefore(chunk, template, targets) {
|
|
2892
|
+
const kinds = getTemplatedPathPlugin().getPresentKinds(template);
|
|
2893
|
+
// The compilation hash exists in no round a chunk is hashed in.
|
|
2894
|
+
if (kinds.has("fullhash") || kinds.has("hash")) return false;
|
|
2895
|
+
for (const target of targets) {
|
|
2896
|
+
if (!this._hashRoundBefore(chunk, target)) return false;
|
|
2897
|
+
}
|
|
2898
|
+
return true;
|
|
2899
|
+
}
|
|
2900
|
+
|
|
2901
|
+
/**
|
|
2902
|
+
* Whether the hashes a name reads are on the chunk now, which they are only once its
|
|
2903
|
+
* round of `createHash` has run — never while modules are being generated.
|
|
2904
|
+
* @param {Chunk} chunk the chunk named
|
|
2905
|
+
* @param {string} template what names it
|
|
2906
|
+
* @param {string} sourceType which asset of the chunk it names
|
|
2907
|
+
* @returns {boolean} true when the name can be resolved here
|
|
2908
|
+
*/
|
|
2909
|
+
_hashedNamePresent(chunk, template, sourceType) {
|
|
2910
|
+
const kinds = getTemplatedPathPlugin().getPresentKinds(template);
|
|
2911
|
+
return (
|
|
2912
|
+
!kinds.has("fullhash") &&
|
|
2913
|
+
!kinds.has("hash") &&
|
|
2914
|
+
(!kinds.has("chunkhash") || chunk.hash !== undefined) &&
|
|
2915
|
+
(!kinds.has("contenthash") || chunk.contentHash[sourceType] !== undefined)
|
|
2916
|
+
);
|
|
2917
|
+
}
|
|
2918
|
+
|
|
2798
2919
|
/**
|
|
2799
2920
|
* Whether `createHash` settles this chunk's hash in the round that runs after the
|
|
2800
2921
|
* compilation hash rather than in one of the four before it. Asked of the chunk
|
|
@@ -3056,35 +3177,6 @@ class RuntimeTemplate {
|
|
|
3056
3177
|
this._chunksByIdForFold = undefined;
|
|
3057
3178
|
}
|
|
3058
3179
|
|
|
3059
|
-
/**
|
|
3060
|
-
* Whether `chunk` can reach any of `targets` by following chunk groups, which is
|
|
3061
|
-
* what turns a baked hashed name into a hash that depends on itself.
|
|
3062
|
-
* @param {Chunk} chunk the referenced chunk
|
|
3063
|
-
* @param {Iterable<Chunk>} targets the chunks the reference is written into
|
|
3064
|
-
* @returns {boolean} true when one of them is reachable from `chunk`
|
|
3065
|
-
*/
|
|
3066
|
-
_reachesAny(chunk, targets) {
|
|
3067
|
-
const wanted = new Set(targets);
|
|
3068
|
-
if (wanted.size === 0) return false;
|
|
3069
|
-
if (wanted.has(chunk)) return true;
|
|
3070
|
-
/** @type {Set<ChunkGroup>} */
|
|
3071
|
-
const seen = new Set();
|
|
3072
|
-
/** @type {ChunkGroup[]} */
|
|
3073
|
-
const queue = [...chunk.groupsIterable];
|
|
3074
|
-
for (const group of queue) seen.add(group);
|
|
3075
|
-
for (let i = 0; i < queue.length; i++) {
|
|
3076
|
-
for (const child of queue[i].childrenIterable) {
|
|
3077
|
-
if (seen.has(child)) continue;
|
|
3078
|
-
seen.add(child);
|
|
3079
|
-
for (const candidate of child.chunks) {
|
|
3080
|
-
if (wanted.has(candidate)) return true;
|
|
3081
|
-
}
|
|
3082
|
-
queue.push(child);
|
|
3083
|
-
}
|
|
3084
|
-
}
|
|
3085
|
-
return false;
|
|
3086
|
-
}
|
|
3087
|
-
|
|
3088
3180
|
/**
|
|
3089
3181
|
* The chunks a reference emitted into `module` is written into — the assets a
|
|
3090
3182
|
* stand-in of ours would land in, and so the only ones a deferred fill could go
|
|
@@ -3200,7 +3292,7 @@ class RuntimeTemplate {
|
|
|
3200
3292
|
* The `../` path from a chunk's own asset back to the output root. Hashes are
|
|
3201
3293
|
* neutralized first: a runtime module is generated once to be hashed, before any
|
|
3202
3294
|
* hash exists, so resolving one there throws — and `RuntimeModule.updateHash`
|
|
3203
|
-
*
|
|
3295
|
+
* lets that throw fail the build rather than hashing it.
|
|
3204
3296
|
* @param {Chunk} chunk the chunk whose asset holds the reference
|
|
3205
3297
|
* @param {boolean} enforceRelative whether the answer keeps a leading `./`
|
|
3206
3298
|
* @returns {string} the path back to the output root
|
|
@@ -3231,7 +3323,10 @@ class RuntimeTemplate {
|
|
|
3231
3323
|
* @returns {Placement} where a literal in it is read from
|
|
3232
3324
|
*/
|
|
3233
3325
|
_modulePlacement(module, chunkGraph) {
|
|
3234
|
-
return this._placementOf(
|
|
3326
|
+
return this._placementOf(
|
|
3327
|
+
this._moduleChunks(module, chunkGraph),
|
|
3328
|
+
isHotModule(module)
|
|
3329
|
+
);
|
|
3235
3330
|
}
|
|
3236
3331
|
|
|
3237
3332
|
/**
|
|
@@ -3250,11 +3345,12 @@ class RuntimeTemplate {
|
|
|
3250
3345
|
|
|
3251
3346
|
/**
|
|
3252
3347
|
* The one answer every chunk in `chunks` agrees on, with either half `null` where
|
|
3253
|
-
* they do not.
|
|
3348
|
+
* they do not — under HMR the update chunk, which re-runs the module, has a say too.
|
|
3254
3349
|
* @param {Iterable<Chunk>} chunks the chunks a literal is written into
|
|
3350
|
+
* @param {boolean=} hot whether a hot update can re-run what is written
|
|
3255
3351
|
* @returns {Placement} where a literal in them is read from
|
|
3256
3352
|
*/
|
|
3257
|
-
_placementOf(chunks) {
|
|
3353
|
+
_placementOf(chunks, hot = false) {
|
|
3258
3354
|
/** @type {Placement | undefined} */
|
|
3259
3355
|
let first;
|
|
3260
3356
|
/** @type {string | null} */
|
|
@@ -3263,13 +3359,17 @@ class RuntimeTemplate {
|
|
|
3263
3359
|
let loaded = null;
|
|
3264
3360
|
for (const chunk of chunks) {
|
|
3265
3361
|
const own = this._chunkPlacement(chunk);
|
|
3362
|
+
const ownUndo =
|
|
3363
|
+
hot && own.undo !== null && own.undo !== this._hotUpdateUndo(chunk)
|
|
3364
|
+
? null
|
|
3365
|
+
: own.undo;
|
|
3266
3366
|
if (first === undefined) {
|
|
3267
3367
|
first = own;
|
|
3268
|
-
undo =
|
|
3368
|
+
undo = ownUndo;
|
|
3269
3369
|
loaded = own.loaded;
|
|
3270
3370
|
continue;
|
|
3271
3371
|
}
|
|
3272
|
-
if (undo !==
|
|
3372
|
+
if (undo !== ownUndo) undo = null;
|
|
3273
3373
|
if (loaded !== own.loaded) loaded = null;
|
|
3274
3374
|
}
|
|
3275
3375
|
if (first === undefined) return NO_PLACEMENT;
|
|
@@ -3289,16 +3389,9 @@ class RuntimeTemplate {
|
|
|
3289
3389
|
* @param {Chunk} chunk the worker's entry chunk
|
|
3290
3390
|
* @param {Module} module the module the reference is emitted into
|
|
3291
3391
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3292
|
-
* @param {RuntimeRequirements} runtimeRequirements what the consuming chunk needs
|
|
3293
3392
|
* @returns {string | null} a quoted literal, or `null` to fall back
|
|
3294
3393
|
*/
|
|
3295
|
-
getAnalyzableWorkerUrl(
|
|
3296
|
-
overridePublicPath,
|
|
3297
|
-
chunk,
|
|
3298
|
-
module,
|
|
3299
|
-
chunkGraph,
|
|
3300
|
-
runtimeRequirements
|
|
3301
|
-
) {
|
|
3394
|
+
getAnalyzableWorkerUrl(overridePublicPath, chunk, module, chunkGraph) {
|
|
3302
3395
|
// Without an id nothing can name the chunk in a stand-in.
|
|
3303
3396
|
if (
|
|
3304
3397
|
chunk.id === null ||
|
|
@@ -3310,8 +3403,7 @@ class RuntimeTemplate {
|
|
|
3310
3403
|
overridePublicPath,
|
|
3311
3404
|
chunk,
|
|
3312
3405
|
module,
|
|
3313
|
-
chunkGraph
|
|
3314
|
-
runtimeRequirements
|
|
3406
|
+
chunkGraph
|
|
3315
3407
|
);
|
|
3316
3408
|
}
|
|
3317
3409
|
|
|
@@ -3324,12 +3416,11 @@ class RuntimeTemplate {
|
|
|
3324
3416
|
* @param {Module | undefined} consumingModule the module the reference is emitted
|
|
3325
3417
|
* into, or `undefined` when `consumingChunks` names where it goes instead
|
|
3326
3418
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3327
|
-
* @param {RuntimeRequirements=} runtimeRequirements set when the caller wraps the result in
|
|
3328
|
-
* `new URL(...)` and so accepts a runtime public path prefix around the literal filename
|
|
3329
3419
|
* @param {Chunk[]=} consumingChunks the chunks the reference is written into, where
|
|
3330
3420
|
* they are known without a module to read them from
|
|
3331
3421
|
* @param {string=} sourceType which half of the chunk is named — its javascript by
|
|
3332
3422
|
* default, or its stylesheet
|
|
3423
|
+
* @param {boolean=} hot whether a hot update can re-run what is written
|
|
3333
3424
|
* @returns {string | null} a JS string literal or expression, or `null` to fall back to the runtime form
|
|
3334
3425
|
*/
|
|
3335
3426
|
_getAnalyzableChunkSpecifier(
|
|
@@ -3337,20 +3428,16 @@ class RuntimeTemplate {
|
|
|
3337
3428
|
chunk,
|
|
3338
3429
|
consumingModule,
|
|
3339
3430
|
chunkGraph,
|
|
3340
|
-
runtimeRequirements,
|
|
3341
3431
|
consumingChunks,
|
|
3342
|
-
sourceType = JAVASCRIPT_TYPE
|
|
3432
|
+
sourceType = JAVASCRIPT_TYPE,
|
|
3433
|
+
hot = isHotModule(consumingModule)
|
|
3343
3434
|
) {
|
|
3344
3435
|
const { compilation } = this;
|
|
3345
3436
|
const { outputOptions } = compilation;
|
|
3346
3437
|
const naming = CHUNK_ASSET_NAMING.get(sourceType);
|
|
3347
3438
|
// Nothing here names this type's asset, so nothing can spell where it will be.
|
|
3348
3439
|
if (naming === undefined) return null;
|
|
3349
|
-
const template = this.
|
|
3350
|
-
naming.template(chunk, outputOptions),
|
|
3351
|
-
chunk,
|
|
3352
|
-
sourceType
|
|
3353
|
-
);
|
|
3440
|
+
const template = this._chunkAssetTemplate(chunk, sourceType);
|
|
3354
3441
|
if (template === null) return null;
|
|
3355
3442
|
// A hashed name is settled long after this code is generated, so a stand-in is
|
|
3356
3443
|
// emitted and filled in once the hash exists.
|
|
@@ -3362,92 +3449,93 @@ class RuntimeTemplate {
|
|
|
3362
3449
|
const chunks =
|
|
3363
3450
|
consumingChunks ||
|
|
3364
3451
|
this._moduleChunks(/** @type {Module} */ (consumingModule), chunkGraph);
|
|
3365
|
-
|
|
3366
|
-
//
|
|
3367
|
-
|
|
3368
|
-
//
|
|
3369
|
-
//
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
chunk
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
//
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
if (deferred && !canReserve && !canFold) return cannotReserve();
|
|
3390
|
-
const filename = deferred
|
|
3391
|
-
? ""
|
|
3392
|
-
: compilation.getPath(/** @type {string} */ (template), {
|
|
3393
|
-
chunk,
|
|
3394
|
-
// Matches what names the asset, or a placeholder resolved here would
|
|
3395
|
-
// not be the one on disk.
|
|
3396
|
-
runtime: chunk.runtime,
|
|
3397
|
-
contentHashType: sourceType
|
|
3398
|
-
});
|
|
3452
|
+
// An id names the chunk in the stand-in; `blockPromise` drops an id-less chunk
|
|
3453
|
+
// before asking, so the guard only keeps `null` out of a name.
|
|
3454
|
+
if (chunk.id === null) return null;
|
|
3455
|
+
// A runtime module is generated in its chunk's round of `createHash`, where a
|
|
3456
|
+
// hashed name settled earlier exists: spelled, so a hot update carries the new one.
|
|
3457
|
+
const settled =
|
|
3458
|
+
deferred &&
|
|
3459
|
+
template !== undefined &&
|
|
3460
|
+
this._hashedNamePresent(chunk, template, sourceType) &&
|
|
3461
|
+
this._namesBeforeAll(chunk, chunks);
|
|
3462
|
+
const canReserve = this._canDeferAnalyzableName(chunks);
|
|
3463
|
+
// A content-named consumer folds this name into its hash when it settles first;
|
|
3464
|
+
// what the fold cannot cover is repaired instead.
|
|
3465
|
+
const canFold = !canReserve && this._namesBeforeAll(chunk, chunks);
|
|
3466
|
+
const filename =
|
|
3467
|
+
deferred && !settled
|
|
3468
|
+
? ""
|
|
3469
|
+
: compilation.getPath(/** @type {string} */ (template), {
|
|
3470
|
+
chunk,
|
|
3471
|
+
// Matches what names the asset, or a placeholder resolved here would
|
|
3472
|
+
// not be the one on disk.
|
|
3473
|
+
runtime: chunk.runtime,
|
|
3474
|
+
contentHashType: sourceType
|
|
3475
|
+
});
|
|
3399
3476
|
/**
|
|
3400
3477
|
* @param {SpecifierPart[]} prefix what goes in front of the chunk's filename
|
|
3401
|
-
* @returns {string
|
|
3402
|
-
* recipe needs a stand-in that cannot be reserved
|
|
3478
|
+
* @returns {string} the specifier already quoted
|
|
3403
3479
|
*/
|
|
3404
3480
|
const specifier = (prefix) => {
|
|
3405
|
-
if (!deferred) {
|
|
3481
|
+
if (!deferred || settled) {
|
|
3406
3482
|
const text = literalText(prefix);
|
|
3407
3483
|
if (text !== null) return toJsStringLiteral(text + filename);
|
|
3408
3484
|
}
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
}
|
|
3485
|
+
const repair =
|
|
3486
|
+
!canReserve && !(canFold && this._foldsWholeName(prefix, chunks));
|
|
3412
3487
|
return toJsStringLiteral(
|
|
3413
|
-
this._reserveAnalyzableSpecifier(
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3488
|
+
this._reserveAnalyzableSpecifier(
|
|
3489
|
+
this._markedForRepair(repair, [
|
|
3490
|
+
...prefix,
|
|
3491
|
+
// A settled name is carried as text: the fill would spell the same,
|
|
3492
|
+
// but only text of its own moves the runtime module's hash.
|
|
3493
|
+
settled
|
|
3494
|
+
? ["literal", filename]
|
|
3495
|
+
: [naming.standIn, /** @type {ChunkId} */ (chunk.id)]
|
|
3496
|
+
])
|
|
3497
|
+
)
|
|
3417
3498
|
);
|
|
3418
3499
|
};
|
|
3419
3500
|
if (overridePublicPath) {
|
|
3420
|
-
const resolved = this._resolvePublicPathPrefix(
|
|
3421
|
-
overridePublicPath,
|
|
3422
|
-
consumingModule,
|
|
3423
|
-
chunks
|
|
3424
|
-
);
|
|
3501
|
+
const resolved = this._resolvePublicPathPrefix(overridePublicPath);
|
|
3425
3502
|
return resolved === null ? null : specifier(resolved);
|
|
3426
3503
|
}
|
|
3427
3504
|
const { publicPath } = outputOptions;
|
|
3428
3505
|
if (publicPath === "auto") {
|
|
3429
|
-
const { undo } = this._placementOf(chunks);
|
|
3506
|
+
const { undo } = this._placementOf(chunks, hot);
|
|
3430
3507
|
if (undo !== null) return specifier([["literal", undo]]);
|
|
3431
3508
|
// Different depths — no one `../` path is right for every asset the reference
|
|
3432
3509
|
// lands in, so the deferred pass builds each asset's own.
|
|
3433
|
-
|
|
3434
|
-
if (perAsset !== null) return perAsset;
|
|
3435
|
-
// Only a stand-in that could not be reserved reaches here, and `specifier`
|
|
3436
|
-
// has already recorded why.
|
|
3437
|
-
if (deferred || !runtimeRequirements) return null;
|
|
3438
|
-
// No bundler follows a concatenation, but a `new URL(...)` caller still sheds
|
|
3439
|
-
// the `.u(id)` lookup this way; `import()` needs a static specifier.
|
|
3440
|
-
runtimeRequirements.add(RuntimeGlobals.publicPath);
|
|
3441
|
-
return `${RuntimeGlobals.publicPath} + ${toJsStringLiteral(filename)}`;
|
|
3510
|
+
return specifier([["undo", ""]]);
|
|
3442
3511
|
}
|
|
3443
3512
|
const prefix = this._analyzablePathPrefix(
|
|
3444
3513
|
consumingModule,
|
|
3445
3514
|
chunkGraph,
|
|
3446
|
-
chunks
|
|
3515
|
+
chunks,
|
|
3516
|
+
undefined,
|
|
3517
|
+
hot
|
|
3447
3518
|
);
|
|
3448
3519
|
return prefix === null ? null : specifier(prefix);
|
|
3449
3520
|
}
|
|
3450
3521
|
|
|
3522
|
+
/**
|
|
3523
|
+
* The template this chunk's asset of `sourceType` is named by: `undefined` where a
|
|
3524
|
+
* function reads a hash, `null` where nothing here names that type or it answers nothing.
|
|
3525
|
+
* @param {Chunk} chunk the chunk
|
|
3526
|
+
* @param {string} sourceType which asset of the chunk
|
|
3527
|
+
* @returns {string | undefined | null} the template
|
|
3528
|
+
*/
|
|
3529
|
+
_chunkAssetTemplate(chunk, sourceType) {
|
|
3530
|
+
const naming = CHUNK_ASSET_NAMING.get(sourceType);
|
|
3531
|
+
if (naming === undefined) return null;
|
|
3532
|
+
return this._resolveChunkFilenameTemplate(
|
|
3533
|
+
naming.template(chunk, this.outputOptions),
|
|
3534
|
+
chunk,
|
|
3535
|
+
sourceType
|
|
3536
|
+
);
|
|
3537
|
+
}
|
|
3538
|
+
|
|
3451
3539
|
/**
|
|
3452
3540
|
* The parts that go in front of a name so a literal read from the chunk holding it
|
|
3453
3541
|
* reaches what the runtime would. A public path needing no base is the whole answer.
|
|
@@ -3461,18 +3549,24 @@ class RuntimeTemplate {
|
|
|
3461
3549
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3462
3550
|
* @param {Iterable<Chunk>} chunks the chunks a stand-in would be written into
|
|
3463
3551
|
* @param {string=} relativeBase an entry `baseUri` read against the output root
|
|
3552
|
+
* @param {boolean=} hot whether a hot update can re-run what is written
|
|
3464
3553
|
* @returns {SpecifierPart[] | null} the parts, or `null` having recorded why not
|
|
3465
3554
|
*/
|
|
3466
|
-
_analyzablePathPrefix(
|
|
3555
|
+
_analyzablePathPrefix(
|
|
3556
|
+
module,
|
|
3557
|
+
chunkGraph,
|
|
3558
|
+
chunks,
|
|
3559
|
+
relativeBase,
|
|
3560
|
+
hot = isHotModule(module)
|
|
3561
|
+
) {
|
|
3467
3562
|
const publicPath = /** @type {PublicPath} */ (
|
|
3468
3563
|
this.outputOptions.publicPath
|
|
3469
3564
|
);
|
|
3470
3565
|
const shape = this._publicPathShape();
|
|
3471
3566
|
if (shape === undefined) return null;
|
|
3472
|
-
const resolve = () =>
|
|
3473
|
-
this._resolvePublicPathPrefix(publicPath, module, chunks);
|
|
3567
|
+
const resolve = () => this._resolvePublicPathPrefix(publicPath);
|
|
3474
3568
|
if (isBaseIndependent(shape)) return resolve();
|
|
3475
|
-
const { undo, loaded } = this._placementOf(chunks);
|
|
3569
|
+
const { undo, loaded } = this._placementOf(chunks, hot);
|
|
3476
3570
|
// What a chunk the loader fetched climbs back out of. One of no depth leaves
|
|
3477
3571
|
// nothing to climb, and then both answers put the same text in front.
|
|
3478
3572
|
const served = this._publicPathClimb();
|
|
@@ -3506,12 +3600,9 @@ class RuntimeTemplate {
|
|
|
3506
3600
|
* the deferred pass whole instead. A function is called for its value rather than
|
|
3507
3601
|
* read as a template, so one whose answer moves with the hash is called again there.
|
|
3508
3602
|
* @param {PublicPath} publicPath the configured public path
|
|
3509
|
-
* @param {Module=} module the module the reference is emitted into, to record why
|
|
3510
|
-
* a name no stand-in may be reserved for kept the runtime form
|
|
3511
|
-
* @param {Iterable<Chunk>=} chunks the chunks a stand-in would be written into
|
|
3512
3603
|
* @returns {SpecifierPart[] | null} the parts, or `null` when it cannot be known
|
|
3513
3604
|
*/
|
|
3514
|
-
_resolvePublicPathPrefix(publicPath
|
|
3605
|
+
_resolvePublicPathPrefix(publicPath) {
|
|
3515
3606
|
if (typeof publicPath === "function") {
|
|
3516
3607
|
// One that answers nothing to a probe cannot be placed, absolute or not.
|
|
3517
3608
|
if (this._publicPathShape() === undefined) return null;
|
|
@@ -3522,28 +3613,18 @@ class RuntimeTemplate {
|
|
|
3522
3613
|
if (resolved !== null) return [["literal", resolved]];
|
|
3523
3614
|
// Called again by the fill against the compilation hash, so what it answers
|
|
3524
3615
|
// there is that hash by another name.
|
|
3525
|
-
return
|
|
3526
|
-
? [["publicPath", ""]]
|
|
3527
|
-
: null;
|
|
3616
|
+
return [["publicPath", ""]];
|
|
3528
3617
|
}
|
|
3529
3618
|
if (!publicPath.includes("[")) return [["literal", publicPath]];
|
|
3530
3619
|
// A re-encoded digest cannot be spelled by a stand-in, so it stays a template.
|
|
3531
3620
|
if (getTemplatedPathPlugin().usesFullHashDigest(publicPath)) {
|
|
3532
|
-
return
|
|
3533
|
-
? [["template", publicPath]]
|
|
3534
|
-
: null;
|
|
3621
|
+
return [["template", publicPath]];
|
|
3535
3622
|
}
|
|
3536
3623
|
const literal = this.compilation.getPath(
|
|
3537
3624
|
publicPath,
|
|
3538
3625
|
this._deferredFullHashPathData()
|
|
3539
3626
|
);
|
|
3540
|
-
return
|
|
3541
|
-
this._hasReservedFullHash(literal),
|
|
3542
|
-
chunks,
|
|
3543
|
-
module
|
|
3544
|
-
)
|
|
3545
|
-
? [["literal", literal]]
|
|
3546
|
-
: null;
|
|
3627
|
+
return [["literal", literal]];
|
|
3547
3628
|
}
|
|
3548
3629
|
|
|
3549
3630
|
/**
|
|
@@ -3628,7 +3709,7 @@ class RuntimeTemplate {
|
|
|
3628
3709
|
relativeBase
|
|
3629
3710
|
);
|
|
3630
3711
|
if (prefix === null) return null;
|
|
3631
|
-
return this._specifierOf([...prefix, ...file], chunks
|
|
3712
|
+
return this._specifierOf([...prefix, ...file], chunks);
|
|
3632
3713
|
}
|
|
3633
3714
|
// No public path to place it against, so the `../` path back to the output root
|
|
3634
3715
|
// is the whole prefix. Different depths — no one is right for every asset the
|
|
@@ -3638,23 +3719,22 @@ class RuntimeTemplate {
|
|
|
3638
3719
|
const parts = [undo === null ? ["undo", ""] : ["literal", undo]];
|
|
3639
3720
|
if (relativeBase !== undefined) parts.push(["literal", relativeBase]);
|
|
3640
3721
|
parts.push(...file);
|
|
3641
|
-
return this._specifierOf(parts, chunks
|
|
3722
|
+
return this._specifierOf(parts, chunks);
|
|
3642
3723
|
}
|
|
3643
3724
|
|
|
3644
3725
|
/**
|
|
3645
3726
|
* Static `new URL(<file>, import.meta.url)` for every stylesheet a runtime can load,
|
|
3646
|
-
* keyed by chunk id
|
|
3647
|
-
*
|
|
3727
|
+
* keyed by chunk id, or `null` when they have to keep the runtime
|
|
3728
|
+
* `publicPath + getChunkCssFilename(id)` form. Both the runtime module reading them
|
|
3648
3729
|
* and the plugin declaring what it needs ask this, so the two always agree. The
|
|
3649
3730
|
* runtime hands an absolute url string to `link.href`, and so does this — the browser
|
|
3650
3731
|
* resolves the element against the document, which is not where the chunk sits, and
|
|
3651
|
-
* the loader reads the url as text either way.
|
|
3652
|
-
* that also carries the hot handler; see below.
|
|
3732
|
+
* the loader reads the url as text either way.
|
|
3653
3733
|
* @param {Chunk} runtimeChunk the chunk holding the stylesheet loader
|
|
3654
3734
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3655
3735
|
* @param {ReadOnlyRuntimeRequirements} runtimeRequirements what that chunk needs
|
|
3656
3736
|
* @param {Module=} consumingModule the runtime module, where one exists to report against
|
|
3657
|
-
* @returns {
|
|
3737
|
+
* @returns {Map<ChunkId, string> | null} the urls, or `null` to keep the runtime form
|
|
3658
3738
|
*/
|
|
3659
3739
|
analyzableCssChunkUrls(
|
|
3660
3740
|
runtimeChunk,
|
|
@@ -3686,14 +3766,14 @@ class RuntimeTemplate {
|
|
|
3686
3766
|
/**
|
|
3687
3767
|
* Static `new URL(<file>, import.meta.url).href` for every javascript chunk a
|
|
3688
3768
|
* runtime can hint at with `<link rel="prefetch"/"modulepreload">`, keyed by chunk
|
|
3689
|
-
* id
|
|
3690
|
-
*
|
|
3769
|
+
* id, or `null` when they have to keep the runtime
|
|
3770
|
+
* `publicPath + getChunkScriptFilename(id)` form. Both the runtime module reading
|
|
3691
3771
|
* them and the plugin declaring what it needs ask this, so the two always agree.
|
|
3692
3772
|
* @param {Chunk} runtimeChunk the chunk holding the hint handlers
|
|
3693
3773
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3694
3774
|
* @param {ReadOnlyRuntimeRequirements} runtimeRequirements what that chunk needs
|
|
3695
3775
|
* @param {Module=} consumingModule the runtime module, where one exists to report against
|
|
3696
|
-
* @returns {
|
|
3776
|
+
* @returns {Map<ChunkId, string> | null} the urls, or `null` to keep the runtime form
|
|
3697
3777
|
*/
|
|
3698
3778
|
analyzableChunkScriptUrls(
|
|
3699
3779
|
runtimeChunk,
|
|
@@ -3730,17 +3810,156 @@ class RuntimeTemplate {
|
|
|
3730
3810
|
);
|
|
3731
3811
|
}
|
|
3732
3812
|
|
|
3813
|
+
/**
|
|
3814
|
+
* Why no chunk import of this build can be a native `import()`, read from the
|
|
3815
|
+
* output configuration alone, or `null` when nothing in it rules one out.
|
|
3816
|
+
* @returns {string | null} the reason
|
|
3817
|
+
*/
|
|
3818
|
+
_chunkImportOutputReason() {
|
|
3819
|
+
const { chunkFormat, importFunctionName } = this.outputOptions;
|
|
3820
|
+
if (chunkFormat !== "module") {
|
|
3821
|
+
return `output.chunkFormat is ${JSON.stringify(chunkFormat)}, so chunks are not read through a native import()`;
|
|
3822
|
+
}
|
|
3823
|
+
if (importFunctionName !== "import") {
|
|
3824
|
+
return `output.importFunctionName is ${JSON.stringify(importFunctionName)}, so the call site is not a native import()`;
|
|
3825
|
+
}
|
|
3826
|
+
return null;
|
|
3827
|
+
}
|
|
3828
|
+
|
|
3829
|
+
/**
|
|
3830
|
+
* Records that this runtime reads its chunks some way other than a native
|
|
3831
|
+
* `import()`, so no literal can name what it loads. Recorded on the entries that
|
|
3832
|
+
* chose it, which is where the setting behind it lives.
|
|
3833
|
+
* @param {Chunk} chunk the runtime chunk
|
|
3834
|
+
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3835
|
+
* @returns {void}
|
|
3836
|
+
*/
|
|
3837
|
+
reportChunkImportBailout(chunk, chunkGraph) {
|
|
3838
|
+
if (!this.outputOptions.module) return;
|
|
3839
|
+
const entryOptions = chunk.getEntryOptions();
|
|
3840
|
+
const chunkLoading =
|
|
3841
|
+
entryOptions && entryOptions.chunkLoading !== undefined
|
|
3842
|
+
? entryOptions.chunkLoading
|
|
3843
|
+
: this.outputOptions.chunkLoading;
|
|
3844
|
+
if (chunkLoading === "import") return;
|
|
3845
|
+
const subject = entryOptions && entryOptions.worker ? "worker" : "runtime";
|
|
3846
|
+
const reason = `this ${subject} loads its chunks with ${JSON.stringify(chunkLoading)}, not "import"`;
|
|
3847
|
+
for (const module of chunkGraph.getChunkEntryModulesIterable(chunk)) {
|
|
3848
|
+
this._analyzableBailout(module, reason, false);
|
|
3849
|
+
}
|
|
3850
|
+
}
|
|
3851
|
+
|
|
3852
|
+
/**
|
|
3853
|
+
* The chunks this loader can be handed an id for: the ones held by a group outside
|
|
3854
|
+
* the initial wave, which is what an `import()` or a context map turns into an id.
|
|
3855
|
+
* @param {Chunk} runtimeChunk the chunk holding the chunk loader
|
|
3856
|
+
* @returns {Set<Chunk>} the chunks reachable from here through a non-initial group
|
|
3857
|
+
*/
|
|
3858
|
+
_loadableChunks(runtimeChunk) {
|
|
3859
|
+
const queue = new Set(runtimeChunk.groupsIterable);
|
|
3860
|
+
/** @type {Set<Chunk>} */
|
|
3861
|
+
const chunks = new Set();
|
|
3862
|
+
for (const group of queue) {
|
|
3863
|
+
if (!group.isInitial()) {
|
|
3864
|
+
for (const chunk of group.chunks) chunks.add(chunk);
|
|
3865
|
+
}
|
|
3866
|
+
for (const child of group.childrenIterable) queue.add(child);
|
|
3867
|
+
}
|
|
3868
|
+
return chunks;
|
|
3869
|
+
}
|
|
3870
|
+
|
|
3871
|
+
/**
|
|
3872
|
+
* Whether the loader still needs to build a url from a chunk id, which is the case
|
|
3873
|
+
* for a chunk it can be asked for that `analyzableChunkImports` leaves unnamed: one
|
|
3874
|
+
* carrying a runtime of its own, or one a second entrypoint has at startup.
|
|
3875
|
+
* @param {Chunk} runtimeChunk the chunk holding the chunk loader
|
|
3876
|
+
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3877
|
+
* @returns {boolean} true when an id the map does not hold can reach the loader
|
|
3878
|
+
*/
|
|
3879
|
+
chunkImportsNeedRuntimeUrl(runtimeChunk, chunkGraph) {
|
|
3880
|
+
const installed = new Set(runtimeChunk.getAllInitialChunks());
|
|
3881
|
+
for (const chunk of this._loadableChunks(runtimeChunk)) {
|
|
3882
|
+
if (chunk === runtimeChunk) continue;
|
|
3883
|
+
if (!chunk.hasRuntime() && !installed.has(chunk)) continue;
|
|
3884
|
+
if (JavascriptModulesPlugin.chunkHasJs(chunk, chunkGraph)) return true;
|
|
3885
|
+
}
|
|
3886
|
+
return false;
|
|
3887
|
+
}
|
|
3888
|
+
|
|
3889
|
+
/**
|
|
3890
|
+
* A literal `import()` specifier for every javascript chunk a runtime loads on
|
|
3891
|
+
* demand, keyed by chunk id, or `null` when one of them cannot be named here. The
|
|
3892
|
+
* map is written into the runtime chunk rather than at each import site, so a
|
|
3893
|
+
* hashed chunk name reaches no module that imports it.
|
|
3894
|
+
* @param {Chunk} runtimeChunk the chunk holding the chunk loader
|
|
3895
|
+
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3896
|
+
* @param {ReadOnlyRuntimeRequirements} runtimeRequirements what that chunk needs
|
|
3897
|
+
* @param {Module=} consumingModule the runtime module, where one exists to report against
|
|
3898
|
+
* @returns {Map<ChunkId, string> | null} the specifiers, or `null` to keep the runtime form
|
|
3899
|
+
*/
|
|
3900
|
+
analyzableChunkImports(
|
|
3901
|
+
runtimeChunk,
|
|
3902
|
+
chunkGraph,
|
|
3903
|
+
runtimeRequirements,
|
|
3904
|
+
consumingModule
|
|
3905
|
+
) {
|
|
3906
|
+
// The runtime names the scope `__webpack_public_path__` belongs to, so the
|
|
3907
|
+
// answer holds whether or not a runtime module is there to ask about.
|
|
3908
|
+
if (
|
|
3909
|
+
!this.supportsAnalyzable(
|
|
3910
|
+
"import",
|
|
3911
|
+
chunkGraph,
|
|
3912
|
+
consumingModule,
|
|
3913
|
+
runtimeChunk.runtime
|
|
3914
|
+
)
|
|
3915
|
+
) {
|
|
3916
|
+
return null;
|
|
3917
|
+
}
|
|
3918
|
+
// An initial chunk and one carrying a runtime are both reached by a static
|
|
3919
|
+
// import, so naming either here would only make two hashes chase each other.
|
|
3920
|
+
const installed = new Set(runtimeChunk.getAllInitialChunks());
|
|
3921
|
+
/** @type {Chunk[]} */
|
|
3922
|
+
const chunks = [];
|
|
3923
|
+
for (const chunk of runtimeChunk.getAllReferencedChunks()) {
|
|
3924
|
+
if (
|
|
3925
|
+
chunk === runtimeChunk ||
|
|
3926
|
+
chunk.hasRuntime() ||
|
|
3927
|
+
installed.has(chunk) ||
|
|
3928
|
+
!JavascriptModulesPlugin.chunkHasJs(chunk, chunkGraph)
|
|
3929
|
+
) {
|
|
3930
|
+
continue;
|
|
3931
|
+
}
|
|
3932
|
+
chunks.push(chunk);
|
|
3933
|
+
}
|
|
3934
|
+
const specifiers = this._analyzableChunkSpecifiers(
|
|
3935
|
+
chunks,
|
|
3936
|
+
chunkGraph,
|
|
3937
|
+
consumingModule,
|
|
3938
|
+
[runtimeChunk],
|
|
3939
|
+
JAVASCRIPT_TYPE,
|
|
3940
|
+
runtimeRequirements
|
|
3941
|
+
);
|
|
3942
|
+
if (specifiers === null) return null;
|
|
3943
|
+
for (const [id, specifier] of specifiers) {
|
|
3944
|
+
// A bare specifier is a package name, so spell it relative the way the
|
|
3945
|
+
// runtime form's `.p + <file>` would have resolved it.
|
|
3946
|
+
if (!RESOLVABLE_SPECIFIER_REGEXP.test(specifier.slice(1))) {
|
|
3947
|
+
specifiers.set(id, `"./${specifier.slice(1)}`);
|
|
3948
|
+
}
|
|
3949
|
+
}
|
|
3950
|
+
return specifiers;
|
|
3951
|
+
}
|
|
3952
|
+
|
|
3733
3953
|
/**
|
|
3734
3954
|
* The urls of one asset of each of `chunks`, written out so they can be read by
|
|
3735
|
-
* chunk id
|
|
3736
|
-
* than losing it — the consumer keeps the runtime form for the ids the map lacks.
|
|
3955
|
+
* chunk id, or `null` as soon as one of them cannot be named here.
|
|
3737
3956
|
* @param {Iterable<Chunk>} chunks the chunks whose asset is wanted
|
|
3738
3957
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3739
3958
|
* @param {Module | undefined} consumingModule the runtime module, where one exists to report against
|
|
3740
3959
|
* @param {Chunk[]} consumingChunks the chunks the urls are written into
|
|
3741
3960
|
* @param {string} sourceType which asset of each chunk to name
|
|
3742
3961
|
* @param {ReadOnlyRuntimeRequirements} runtimeRequirements what the runtime chunk needs
|
|
3743
|
-
* @returns {
|
|
3962
|
+
* @returns {Map<ChunkId, string> | null} the urls, or `null` to keep the runtime form
|
|
3744
3963
|
*/
|
|
3745
3964
|
_analyzableChunkUrls(
|
|
3746
3965
|
chunks,
|
|
@@ -3750,17 +3969,51 @@ class RuntimeTemplate {
|
|
|
3750
3969
|
sourceType,
|
|
3751
3970
|
runtimeRequirements
|
|
3752
3971
|
) {
|
|
3753
|
-
|
|
3754
|
-
// to HMR — analyzable output is what ships.
|
|
3755
|
-
if (
|
|
3756
|
-
runtimeRequirements.has(RuntimeGlobals.hmrDownloadUpdateHandlers) ||
|
|
3757
|
-
!this.supportsAnalyzable("url-runtime", chunkGraph, consumingModule)
|
|
3758
|
-
) {
|
|
3972
|
+
if (!this.supportsAnalyzable("url-runtime", chunkGraph, consumingModule)) {
|
|
3759
3973
|
return null;
|
|
3760
3974
|
}
|
|
3975
|
+
const urls = this._analyzableChunkSpecifiers(
|
|
3976
|
+
chunks,
|
|
3977
|
+
chunkGraph,
|
|
3978
|
+
consumingModule,
|
|
3979
|
+
consumingChunks,
|
|
3980
|
+
sourceType,
|
|
3981
|
+
runtimeRequirements
|
|
3982
|
+
);
|
|
3983
|
+
if (urls === null) return null;
|
|
3984
|
+
for (const [id, specifier] of urls) {
|
|
3985
|
+
urls.set(id, `${this.importMetaUrl(specifier)}.href`);
|
|
3986
|
+
}
|
|
3987
|
+
return urls;
|
|
3988
|
+
}
|
|
3989
|
+
|
|
3990
|
+
/**
|
|
3991
|
+
* The quoted specifier naming one asset of each of `chunks`, keyed by chunk id, or
|
|
3992
|
+
* `null` as soon as one of them cannot be named here. What the name is read against
|
|
3993
|
+
* is the caller's: a url resolves it, an `import()` hands it to the loader.
|
|
3994
|
+
* @param {Iterable<Chunk>} chunks the chunks whose asset is wanted
|
|
3995
|
+
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3996
|
+
* @param {Module | undefined} consumingModule the runtime module, where one exists to report against
|
|
3997
|
+
* @param {Chunk[]} consumingChunks the chunks the specifiers are written into
|
|
3998
|
+
* @param {string} sourceType which asset of each chunk to name
|
|
3999
|
+
* @param {ReadOnlyRuntimeRequirements} runtimeRequirements what the runtime chunk needs
|
|
4000
|
+
* @returns {Map<ChunkId, string> | null} the specifiers, or `null` to keep the runtime form
|
|
4001
|
+
*/
|
|
4002
|
+
_analyzableChunkSpecifiers(
|
|
4003
|
+
chunks,
|
|
4004
|
+
chunkGraph,
|
|
4005
|
+
consumingModule,
|
|
4006
|
+
consumingChunks,
|
|
4007
|
+
sourceType,
|
|
4008
|
+
runtimeRequirements
|
|
4009
|
+
) {
|
|
4010
|
+
// A hot update re-ships the runtime module only when its own code changes, so
|
|
4011
|
+
// each name has to be text nothing but an id joining or leaving the map can move.
|
|
4012
|
+
const hot = runtimeRequirements.has(
|
|
4013
|
+
RuntimeGlobals.hmrDownloadUpdateHandlers
|
|
4014
|
+
);
|
|
3761
4015
|
/** @type {Map<ChunkId, string>} */
|
|
3762
|
-
const
|
|
3763
|
-
let complete = true;
|
|
4016
|
+
const specifiers = new Map();
|
|
3764
4017
|
for (const chunk of chunks) {
|
|
3765
4018
|
if (chunk.id === null) continue;
|
|
3766
4019
|
const specifier = this._getAnalyzableChunkSpecifier(
|
|
@@ -3768,18 +4021,74 @@ class RuntimeTemplate {
|
|
|
3768
4021
|
chunk,
|
|
3769
4022
|
consumingModule,
|
|
3770
4023
|
chunkGraph,
|
|
3771
|
-
undefined,
|
|
3772
4024
|
consumingChunks,
|
|
3773
|
-
sourceType
|
|
4025
|
+
sourceType,
|
|
4026
|
+
hot
|
|
3774
4027
|
);
|
|
3775
|
-
|
|
3776
|
-
if (
|
|
3777
|
-
|
|
4028
|
+
if (specifier === null) return null;
|
|
4029
|
+
if (
|
|
4030
|
+
hot &&
|
|
4031
|
+
!this._settledUnderHot(specifier, chunk, sourceType, consumingChunks)
|
|
4032
|
+
) {
|
|
4033
|
+
return this._analyzableBailout(consumingModule, HOT_NAME_BAILOUT, null);
|
|
4034
|
+
}
|
|
4035
|
+
specifiers.set(chunk.id, specifier);
|
|
4036
|
+
}
|
|
4037
|
+
return specifiers.size > 0 ? specifiers : null;
|
|
4038
|
+
}
|
|
4039
|
+
|
|
4040
|
+
/**
|
|
4041
|
+
* Whether a url a hot update re-ships moves only with the runtime module's own text:
|
|
4042
|
+
* spelled here, or a stand-in of each asset's depth and a hash-free or settled name.
|
|
4043
|
+
* @param {string} specifier the specifier already quoted
|
|
4044
|
+
* @param {Chunk} chunk the chunk it names
|
|
4045
|
+
* @param {string} sourceType which asset of the chunk it names
|
|
4046
|
+
* @param {Chunk[]} consumingChunks the chunks the map is written into
|
|
4047
|
+
* @returns {boolean} true when no update moves what the fill spells
|
|
4048
|
+
*/
|
|
4049
|
+
_settledUnderHot(specifier, chunk, sourceType, consumingChunks) {
|
|
4050
|
+
const match = ANALYZABLE_TOKEN_PAYLOAD.exec(specifier);
|
|
4051
|
+
if (match === null) return true;
|
|
4052
|
+
const parts = RuntimeTemplate._readAnalyzableSpecifier(match[1]);
|
|
4053
|
+
if (parts === null) return false;
|
|
4054
|
+
for (const [kind, value] of parts) {
|
|
4055
|
+
if (kind === "undo") continue;
|
|
4056
|
+
if (kind === "literal" && !this._hasReservedFullHash(String(value))) {
|
|
3778
4057
|
continue;
|
|
3779
4058
|
}
|
|
3780
|
-
|
|
4059
|
+
if (!CHUNK_SPECIFIER_PART_KINDS.has(kind)) return false;
|
|
3781
4060
|
}
|
|
3782
|
-
|
|
4061
|
+
const template = this._chunkAssetTemplate(chunk, sourceType);
|
|
4062
|
+
return (
|
|
4063
|
+
typeof template === "string" &&
|
|
4064
|
+
(!HASH_IN_FILENAME.test(template) ||
|
|
4065
|
+
this._hashedNameSettledBefore(chunk, template, consumingChunks))
|
|
4066
|
+
);
|
|
4067
|
+
}
|
|
4068
|
+
|
|
4069
|
+
/**
|
|
4070
|
+
* The `../` path from a chunk's hot update file, which re-runs its modules, back to
|
|
4071
|
+
* the output root. Hashes are neutralized; the chunk's own id may add a directory.
|
|
4072
|
+
* @param {Chunk} chunk the chunk being updated
|
|
4073
|
+
* @returns {string} the path back to the output root
|
|
4074
|
+
*/
|
|
4075
|
+
_hotUpdateUndo(chunk) {
|
|
4076
|
+
const cached = this._hotUpdateUndoByChunk.get(chunk);
|
|
4077
|
+
if (cached !== undefined) return cached;
|
|
4078
|
+
const { outputOptions } = this;
|
|
4079
|
+
if (this._hotUpdateShapeText === undefined) {
|
|
4080
|
+
this._hotUpdateShapeText = outputOptions.hotUpdateChunkFilename.replace(
|
|
4081
|
+
HASH_IN_FILENAME_GLOBAL,
|
|
4082
|
+
"x"
|
|
4083
|
+
);
|
|
4084
|
+
}
|
|
4085
|
+
const undo = getUndoPath(
|
|
4086
|
+
this.compilation.getPath(this._hotUpdateShapeText, { chunk }),
|
|
4087
|
+
/** @type {string} */ (outputOptions.path),
|
|
4088
|
+
true
|
|
4089
|
+
);
|
|
4090
|
+
this._hotUpdateUndoByChunk.set(chunk, undo);
|
|
4091
|
+
return undo;
|
|
3783
4092
|
}
|
|
3784
4093
|
|
|
3785
4094
|
/**
|
|
@@ -3985,7 +4294,7 @@ class RuntimeTemplate {
|
|
|
3985
4294
|
* @returns {string} the stand-in to emit
|
|
3986
4295
|
*/
|
|
3987
4296
|
_reserveAnalyzableSpecifier(parts) {
|
|
3988
|
-
return
|
|
4297
|
+
return `${ANALYZABLE_TOKEN_PREFIX}${Buffer.from(JSON.stringify(parts))
|
|
3989
4298
|
.toString("base64")
|
|
3990
4299
|
.replace(/\+/g, "-")
|
|
3991
4300
|
.replace(/\//g, "_")
|
|
@@ -4056,6 +4365,10 @@ class RuntimeTemplate {
|
|
|
4056
4365
|
async () => {
|
|
4057
4366
|
const { outputOptions } = compilation;
|
|
4058
4367
|
const fullHash = compilation.hash;
|
|
4368
|
+
// The assets a stand-in landed in whose hashed name has to be brought
|
|
4369
|
+
// back in line, which `RealContentHashPlugin` then does.
|
|
4370
|
+
/** @type {Set<string>} */
|
|
4371
|
+
const repairedAssets = new Set();
|
|
4059
4372
|
/** @type {Map<string, Chunk> | undefined} */
|
|
4060
4373
|
let chunksById;
|
|
4061
4374
|
/** @type {Map<string, Chunk> | undefined} */
|
|
@@ -4110,7 +4423,9 @@ class RuntimeTemplate {
|
|
|
4110
4423
|
let base;
|
|
4111
4424
|
let specifier = "";
|
|
4112
4425
|
for (const [kind, value] of parts) {
|
|
4113
|
-
if (kind === "
|
|
4426
|
+
if (kind === "repair") {
|
|
4427
|
+
repairedAssets.add(assetName);
|
|
4428
|
+
} else if (kind === "base") {
|
|
4114
4429
|
base = /** @type {string} */ (value);
|
|
4115
4430
|
} else if (kind === "literal") {
|
|
4116
4431
|
specifier += value;
|
|
@@ -4181,7 +4496,7 @@ class RuntimeTemplate {
|
|
|
4181
4496
|
// the chunk loader does. A literal part may still carry a stand-in of its own,
|
|
4182
4497
|
// so finish those here rather than scanning again.
|
|
4183
4498
|
return fillFullHash(
|
|
4184
|
-
|
|
4499
|
+
RESOLVABLE_SPECIFIER_REGEXP.test(specifier)
|
|
4185
4500
|
? specifier
|
|
4186
4501
|
: `./${specifier}`
|
|
4187
4502
|
);
|
|
@@ -4234,6 +4549,8 @@ class RuntimeTemplate {
|
|
|
4234
4549
|
|
|
4235
4550
|
tasks.push({ name, source, replacements });
|
|
4236
4551
|
}
|
|
4552
|
+
compilation.runtimeTemplate._analyzableRepairedAssets =
|
|
4553
|
+
repairedAssets;
|
|
4237
4554
|
if (tasks.length === 0) return;
|
|
4238
4555
|
|
|
4239
4556
|
await Promise.all(
|