webpack 5.110.3 → 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 -0
- 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/CircularModulesPlugin.js +157 -55
- package/lib/CleanPlugin.js +2 -2
- package/lib/Compilation.js +320 -302
- package/lib/Compiler.js +209 -46
- 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/ExternalModule.js +41 -14
- package/lib/FileSystemInfo.js +17 -14
- package/lib/FlagDependencyExportsPlugin.js +45 -21
- 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 +45 -12
- package/lib/NormalModuleFactory.js +1 -1
- package/lib/RuntimeGlobals.js +21 -7
- package/lib/RuntimeModule.js +28 -12
- package/lib/RuntimePlugin.js +30 -3
- package/lib/RuntimeTemplate.js +780 -475
- 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/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 +86 -50
- package/lib/config/normalization.js +82 -12
- 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 +14 -5
- 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 +71 -13
- 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 +6 -1
- package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +8 -1
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +24 -1
- package/lib/dependencies/HarmonyModulesPlugin.js +20 -0
- package/lib/dependencies/HtmlEntryDependency.js +50 -0
- package/lib/dependencies/ImportMetaMainDependency.js +104 -0
- package/lib/dependencies/ImportMetaPlugin.js +59 -15
- package/lib/dependencies/SystemRuntimeModule.js +9 -0
- package/lib/dependencies/WorkerDependency.js +1 -2
- package/lib/dependencies/WorkletDependency.js +1 -2
- 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/DuplicateModulesWarning.js +12 -7
- package/lib/errors/EmptyCopyPatternWarning.js +26 -0
- package/lib/errors/ExternalStarReexportError.js +44 -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 +331 -62
- 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 +763 -426
- 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 -24
- 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 +97 -20
- 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 +1 -2
- 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 +100 -66
- 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 +330 -219
- 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/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/SourceProcessor.js +76 -69
- package/lib/util/async.js +292 -0
- package/lib/util/buildDiagnostics.js +69 -0
- 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 +4 -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 +379 -66
- 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 +1414 -314
- 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 {
|
|
@@ -92,6 +90,20 @@ const getTemplatedPathPlugin = memoize(() => require("./TemplatedPathPlugin"));
|
|
|
92
90
|
const getConcatenatedModule = memoize(() =>
|
|
93
91
|
require("./optimize/ConcatenatedModule")
|
|
94
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
|
+
};
|
|
95
107
|
|
|
96
108
|
// Any `[hash]`/`[fullhash]`/`[chunkhash]`/`[contenthash]` token, incl. a `:<length>`
|
|
97
109
|
// or `:<digest>[:<length>]` suffix (e.g. `[contenthash:base64:8]`). Its value is only
|
|
@@ -104,6 +116,9 @@ const HASH_PROBE = "0123456789abcdef0123";
|
|
|
104
116
|
const HASH_PROBE_ALTERNATE = "3210fedcba9876543210";
|
|
105
117
|
const HASH_IN_FILENAME_GLOBAL = /\[(?:full|chunk|content)?hash(?::[^\]]+)?\]/g;
|
|
106
118
|
|
|
119
|
+
// What a recorded reason is prefixed with in `stats.optimizationBailout`.
|
|
120
|
+
const ANALYZABLE_BAILOUT_PREFIX = "Analyzable ESM bailout: ";
|
|
121
|
+
|
|
107
122
|
/**
|
|
108
123
|
* @param {SpecifierPart} part one piece of a reserved name
|
|
109
124
|
* @returns {boolean} true when it is text the deferred pass adds nothing to
|
|
@@ -156,21 +171,6 @@ const rootedParts = (parts) =>
|
|
|
156
171
|
]
|
|
157
172
|
: parts;
|
|
158
173
|
|
|
159
|
-
// Types that ride the chunk itself or render their own asset, so no `.f` handler
|
|
160
|
-
// fetches them; every other type may install one, so the map has to exist for it.
|
|
161
|
-
/** @type {Set<string>} */
|
|
162
|
-
const TYPES_WITHOUT_CHUNK_HANDLER = new Set([
|
|
163
|
-
JAVASCRIPT_TYPE,
|
|
164
|
-
RUNTIME_TYPE,
|
|
165
|
-
ASSET_TYPE,
|
|
166
|
-
ASSET_URL_TYPE,
|
|
167
|
-
HTML_TYPE
|
|
168
|
-
]);
|
|
169
|
-
|
|
170
|
-
// Why a name only the deferred pass could settle was not deferred.
|
|
171
|
-
const DEFER_BAILOUT =
|
|
172
|
-
"a hashed name needs optimization.realContentHash, or no emitted javascript named by its content";
|
|
173
|
-
|
|
174
174
|
/**
|
|
175
175
|
* Where a literal is read from — the `../` path back to the output root, and whether
|
|
176
176
|
* the chunk loader fetched the chunk it sits in through `output.publicPath`.
|
|
@@ -179,13 +179,6 @@ const DEFER_BAILOUT =
|
|
|
179
179
|
* @property {boolean | null} loaded whether the chunk loader fetched the chunk
|
|
180
180
|
*/
|
|
181
181
|
|
|
182
|
-
/**
|
|
183
|
-
* @typedef {object} AnalyzableChunkUrls
|
|
184
|
-
* @property {Map<ChunkId, string>} urls the urls that could be written, by chunk id
|
|
185
|
-
* @property {boolean} complete false when some chunk kept the runtime form, whose
|
|
186
|
-
* ids the consumer then still resolves through the runtime name lookup
|
|
187
|
-
*/
|
|
188
|
-
|
|
189
182
|
/**
|
|
190
183
|
* @typedef {object} WasmGroups
|
|
191
184
|
* @property {(key: string) => string} groupOf the group a runtime key answers with
|
|
@@ -217,7 +210,12 @@ const RUNTIME_HASH_ROUND = 2;
|
|
|
217
210
|
|
|
218
211
|
// Why a public path needing a base could not be spelled from the chunk holding it.
|
|
219
212
|
const SERVED_BAILOUT =
|
|
220
|
-
|
|
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";
|
|
221
219
|
|
|
222
220
|
/**
|
|
223
221
|
* @import {
|
|
@@ -238,8 +236,9 @@ const SERVED_BAILOUT =
|
|
|
238
236
|
* One piece of a name only the deferred pass can spell: text as it stands, the `../`
|
|
239
237
|
* path from the asset it sits in to the output root, a template or `output.publicPath`
|
|
240
238
|
* resolved once the hashes exist, one of the assets the chunk with this id emits, or
|
|
241
|
-
* the base everything else is resolved against once it is spelled.
|
|
242
|
-
*
|
|
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
|
|
243
242
|
*/
|
|
244
243
|
/** @typedef {[SpecifierPartKind, string | number]} SpecifierPart */
|
|
245
244
|
|
|
@@ -251,7 +250,8 @@ const SPECIFIER_PART_KINDS = new Set([
|
|
|
251
250
|
"unserved",
|
|
252
251
|
"base",
|
|
253
252
|
"chunk",
|
|
254
|
-
"cssChunk"
|
|
253
|
+
"cssChunk",
|
|
254
|
+
"repair"
|
|
255
255
|
]);
|
|
256
256
|
|
|
257
257
|
// Only these carry a chunk id, which is the one part value that may be a number.
|
|
@@ -262,7 +262,10 @@ const CHUNK_SPECIFIER_PART_KINDS = new Set(["chunk", "cssChunk"]);
|
|
|
262
262
|
const FULL_HASH_PART_KINDS = new Set(["publicPath", "template", "unserved"]);
|
|
263
263
|
|
|
264
264
|
// What the deferred pass scans for — the other half of what the class spells.
|
|
265
|
+
const ANALYZABLE_TOKEN_PREFIX = "./@@webpackAnalyzableChunk:";
|
|
265
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-]+)@@/;
|
|
266
269
|
|
|
267
270
|
// Stands in for the compilation hash inside an otherwise resolved filename, with the
|
|
268
271
|
// requested length when the placeholder asked for one.
|
|
@@ -305,8 +308,7 @@ const PASS_NAME = "analyzableChunkNaming";
|
|
|
305
308
|
/** @import { Source } from "webpack-sources" */
|
|
306
309
|
/** @import Compiler from "./Compiler" */
|
|
307
310
|
/** @import Chunk, { ChunkFilenameTemplate, ChunkId } from "./Chunk" */
|
|
308
|
-
/** @import
|
|
309
|
-
/** @import ChunkGraph from "./ChunkGraph" */
|
|
311
|
+
/** @import ChunkGraph, { ModuleId } from "./ChunkGraph" */
|
|
310
312
|
/** @import Compilation from "./Compilation" */
|
|
311
313
|
/** @import Dependency from "./Dependency" */
|
|
312
314
|
/** @import ModuleGraph from "./ModuleGraph" */
|
|
@@ -428,6 +430,43 @@ const isAsyncExternal = (/** @type {Module} */ module) =>
|
|
|
428
430
|
Boolean(/** @type {BuildMeta} */ (module.buildMeta).async) &&
|
|
429
431
|
module instanceof getExternalModule();
|
|
430
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
|
+
|
|
431
470
|
class RuntimeTemplate {
|
|
432
471
|
/**
|
|
433
472
|
* Creates an instance of RuntimeTemplate.
|
|
@@ -447,8 +486,8 @@ class RuntimeTemplate {
|
|
|
447
486
|
(getGlobalObject(outputOptions.globalObject));
|
|
448
487
|
/** @type {string} */
|
|
449
488
|
this.contentHashReplacement = "X".repeat(outputOptions.hashDigestLength);
|
|
450
|
-
/** @type {
|
|
451
|
-
this.
|
|
489
|
+
/** @type {Set<string>} */
|
|
490
|
+
this._analyzableRepairedAssets = new Set();
|
|
452
491
|
/** @type {WeakMap<Chunk, boolean>} */
|
|
453
492
|
this._chunkNamedWithoutContent = new WeakMap();
|
|
454
493
|
/** @type {WeakMap<Chunk, string>} */
|
|
@@ -467,10 +506,18 @@ class RuntimeTemplate {
|
|
|
467
506
|
this._publicPathClimbText = undefined;
|
|
468
507
|
/** @type {WeakMap<Chunk, Placement>} */
|
|
469
508
|
this._placementByChunk = new WeakMap();
|
|
509
|
+
/** @type {WeakMap<Chunk, string>} */
|
|
510
|
+
this._hotUpdateUndoByChunk = new WeakMap();
|
|
511
|
+
/** @type {string | undefined} */
|
|
512
|
+
this._hotUpdateShapeText = undefined;
|
|
470
513
|
/** @type {Map<string, string | null | undefined>} */
|
|
471
514
|
this._entryBaseUriByRuntime = new Map();
|
|
472
515
|
/** @type {WasmGroups | undefined} */
|
|
473
516
|
this._wasmGroupsValue = undefined;
|
|
517
|
+
/** @type {string[] | undefined} */
|
|
518
|
+
this._analyzableBailoutSink = undefined;
|
|
519
|
+
/** @type {Module | undefined} */
|
|
520
|
+
this._analyzableGeneratingModule = undefined;
|
|
474
521
|
/** @type {Map<string, boolean> | undefined} */
|
|
475
522
|
this._wasmAnchorKnownByGroup = undefined;
|
|
476
523
|
}
|
|
@@ -569,6 +616,10 @@ class RuntimeTemplate {
|
|
|
569
616
|
return this.outputOptions.environment.generator;
|
|
570
617
|
}
|
|
571
618
|
|
|
619
|
+
supportsTopLevelAwait() {
|
|
620
|
+
return this.outputOptions.environment.topLevelAwait;
|
|
621
|
+
}
|
|
622
|
+
|
|
572
623
|
supportsOptionalChaining() {
|
|
573
624
|
return this.outputOptions.environment.optionalChaining;
|
|
574
625
|
}
|
|
@@ -617,6 +668,41 @@ class RuntimeTemplate {
|
|
|
617
668
|
return this.outputOptions.environment.modulePreload;
|
|
618
669
|
}
|
|
619
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
|
+
|
|
620
706
|
/**
|
|
621
707
|
* Whether a reference a foreign bundler can follow without running webpack's runtime
|
|
622
708
|
* may be emitted — the one question every caller asks, in the form it is asking for:
|
|
@@ -666,7 +752,8 @@ class RuntimeTemplate {
|
|
|
666
752
|
APIPlugin.runtimeUsesPublicPathOverride(
|
|
667
753
|
this.compilation,
|
|
668
754
|
scoped ? chunkGraph : undefined,
|
|
669
|
-
placedModule
|
|
755
|
+
placedModule,
|
|
756
|
+
runtime
|
|
670
757
|
)
|
|
671
758
|
) {
|
|
672
759
|
return this._analyzableBailout(
|
|
@@ -678,36 +765,12 @@ class RuntimeTemplate {
|
|
|
678
765
|
|
|
679
766
|
if (form === "import") {
|
|
680
767
|
// Read through a native `import()`, or it is not this feature at all.
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
`output.chunkFormat is ${JSON.stringify(outputOptions.chunkFormat)}, so chunks are not read through a native import()`,
|
|
685
|
-
false
|
|
686
|
-
);
|
|
687
|
-
}
|
|
688
|
-
if (outputOptions.importFunctionName !== "import") {
|
|
689
|
-
return this._analyzableBailout(
|
|
690
|
-
module,
|
|
691
|
-
`output.importFunctionName is ${JSON.stringify(outputOptions.importFunctionName)}, so the call site is not a native import()`,
|
|
692
|
-
false
|
|
693
|
-
);
|
|
694
|
-
}
|
|
695
|
-
// A worker loading its own chunks some other way keeps that runtime; one on
|
|
696
|
-
// `import` uses the same ESM loader as the main graph, so it can be analyzable.
|
|
697
|
-
for (const originChunk of /** @type {ChunkGraph} */ (
|
|
698
|
-
chunkGraph
|
|
699
|
-
).getModuleChunksIterable(/** @type {Module} */ (placedModule))) {
|
|
700
|
-
const entryOptions = originChunk.getEntryOptions();
|
|
701
|
-
if (!entryOptions || !entryOptions.worker) continue;
|
|
702
|
-
// `WorkerAndWorkletPlugin` always seeds this from `output.workerChunkLoading`.
|
|
703
|
-
if (entryOptions.chunkLoading !== "import") {
|
|
704
|
-
return this._analyzableBailout(
|
|
705
|
-
module,
|
|
706
|
-
`this worker loads its chunks with ${JSON.stringify(entryOptions.chunkLoading)}, not "import"`,
|
|
707
|
-
false
|
|
708
|
-
);
|
|
709
|
-
}
|
|
768
|
+
const outputReason = this._chunkImportOutputReason();
|
|
769
|
+
if (outputReason !== null) {
|
|
770
|
+
return this._analyzableBailout(module, outputReason, false);
|
|
710
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.
|
|
711
774
|
return true;
|
|
712
775
|
}
|
|
713
776
|
|
|
@@ -720,15 +783,12 @@ class RuntimeTemplate {
|
|
|
720
783
|
if (form === "url-inline") return true;
|
|
721
784
|
// `eval` devtool wraps each module in `eval(...)`, where `import.meta` is a
|
|
722
785
|
// syntax error. Runtime modules are emitted beside them, never wrapped.
|
|
723
|
-
const
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
typeof devtool === "string" &&
|
|
727
|
-
devtool.includes("eval")
|
|
728
|
-
) {
|
|
786
|
+
const evalDevtool =
|
|
787
|
+
form === "url-runtime" ? undefined : this._evalWrappingDevtool();
|
|
788
|
+
if (evalDevtool !== undefined) {
|
|
729
789
|
return this._analyzableBailout(
|
|
730
790
|
module,
|
|
731
|
-
`devtool ${JSON.stringify(
|
|
791
|
+
`devtool ${JSON.stringify(evalDevtool)} wraps the module in eval(), where import.meta does not parse`,
|
|
732
792
|
false
|
|
733
793
|
);
|
|
734
794
|
}
|
|
@@ -746,14 +806,14 @@ class RuntimeTemplate {
|
|
|
746
806
|
|
|
747
807
|
// The rest is the `"wasm"` form: whether the whole binary url can be spelled
|
|
748
808
|
// here, rather than built at runtime under an `import.meta.url` base.
|
|
749
|
-
const { publicPath
|
|
809
|
+
const { publicPath } = outputOptions;
|
|
750
810
|
if (publicPath !== "auto") {
|
|
751
811
|
// A public path that needs no base names the same place from the chunk as from
|
|
752
812
|
// the document, so a literal spells what `fetch` would have reached.
|
|
753
813
|
if (this._publicPathNeedsNoBase()) {
|
|
754
814
|
// Settled no earlier than the hash it reads or is called with, so it is
|
|
755
815
|
// baked only where the deferred pass may finish it.
|
|
756
|
-
if (this._resolvePublicPathPrefix(publicPath
|
|
816
|
+
if (this._resolvePublicPathPrefix(publicPath) === null) {
|
|
757
817
|
return false;
|
|
758
818
|
}
|
|
759
819
|
} else if (
|
|
@@ -767,17 +827,6 @@ class RuntimeTemplate {
|
|
|
767
827
|
);
|
|
768
828
|
}
|
|
769
829
|
}
|
|
770
|
-
// The compilation hash is settled after code generation, so a name carrying one
|
|
771
|
-
// is baked only where the deferred pass can fill it in. `[hash]` is the module's
|
|
772
|
-
// own here, which code generation already knows.
|
|
773
|
-
if (
|
|
774
|
-
getTemplatedPathPlugin()
|
|
775
|
-
.getPresentKinds(/** @type {string} */ (webassemblyModuleFilename))
|
|
776
|
-
.has("fullhash") &&
|
|
777
|
-
!this._canDeferOrBakeFullHash(true, undefined, module)
|
|
778
|
-
) {
|
|
779
|
-
return false;
|
|
780
|
-
}
|
|
781
830
|
return true;
|
|
782
831
|
}
|
|
783
832
|
|
|
@@ -796,38 +845,97 @@ class RuntimeTemplate {
|
|
|
796
845
|
*/
|
|
797
846
|
_analyzableBailout(module, reason, answer) {
|
|
798
847
|
if (module !== undefined && this.outputOptions.module) {
|
|
799
|
-
|
|
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}`;
|
|
800
852
|
const bailouts =
|
|
801
|
-
this.compilation.moduleGraph.getOptimizationBailout(
|
|
853
|
+
this.compilation.moduleGraph.getOptimizationBailout(target);
|
|
802
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
|
+
}
|
|
803
864
|
}
|
|
804
865
|
return answer;
|
|
805
866
|
}
|
|
806
867
|
|
|
807
868
|
/**
|
|
808
|
-
*
|
|
809
|
-
*
|
|
810
|
-
*
|
|
811
|
-
*
|
|
812
|
-
* place — with a name like `[name].js` there is nothing to go stale. Asked of the
|
|
813
|
-
* names the chunks actually carry rather than of `output`, so a template nothing is
|
|
814
|
-
* emitted under does not rule the rewrite out and a `chunk.filenameTemplate` does
|
|
815
|
-
* not slip past it.
|
|
816
|
-
* @param {Iterable<Chunk>=} chunks the chunks the stand-in is written into; omit
|
|
817
|
-
* where the answer has to hold for the whole compilation, as it does for a gate a
|
|
818
|
-
* runtime module asks from the other end
|
|
819
|
-
* @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}
|
|
820
873
|
*/
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
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));
|
|
828
923
|
}
|
|
829
|
-
return this._javascriptNamedWithoutContent;
|
|
830
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) {
|
|
831
939
|
let found = false;
|
|
832
940
|
for (const chunk of chunks) {
|
|
833
941
|
found = true;
|
|
@@ -838,15 +946,15 @@ class RuntimeTemplate {
|
|
|
838
946
|
}
|
|
839
947
|
|
|
840
948
|
/**
|
|
841
|
-
*
|
|
842
|
-
*
|
|
843
|
-
*
|
|
844
|
-
*
|
|
845
|
-
* @
|
|
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
|
|
846
955
|
*/
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
return this._analyzableBailout(module, DEFER_BAILOUT, false);
|
|
956
|
+
_needsRepair(chunks) {
|
|
957
|
+
return !this._canDeferAnalyzableName(chunks);
|
|
850
958
|
}
|
|
851
959
|
|
|
852
960
|
/**
|
|
@@ -854,37 +962,28 @@ class RuntimeTemplate {
|
|
|
854
962
|
* and a stand-in for the deferred pass where they do not.
|
|
855
963
|
* @param {SpecifierPart[]} parts the whole specifier
|
|
856
964
|
* @param {Iterable<Chunk>} chunks the chunks it is written into
|
|
857
|
-
* @
|
|
858
|
-
* @returns {string | null} it already quoted, or `null` when no stand-in may be
|
|
859
|
-
* reserved
|
|
965
|
+
* @returns {string} it already quoted
|
|
860
966
|
*/
|
|
861
|
-
_specifierOf(parts, chunks
|
|
967
|
+
_specifierOf(parts, chunks) {
|
|
862
968
|
const text = literalText(parts);
|
|
863
969
|
if (text !== null) return toJsStringLiteral(text);
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
) {
|
|
871
|
-
return null;
|
|
872
|
-
}
|
|
873
|
-
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
|
+
);
|
|
874
976
|
}
|
|
875
977
|
|
|
876
978
|
/**
|
|
877
|
-
*
|
|
878
|
-
*
|
|
879
|
-
*
|
|
880
|
-
*
|
|
881
|
-
* @
|
|
882
|
-
* @param {Iterable<Chunk>=} chunks the chunks the stand-in is written into
|
|
883
|
-
* @param {Module=} module the module the reference is emitted into
|
|
884
|
-
* @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
|
|
885
984
|
*/
|
|
886
|
-
|
|
887
|
-
return
|
|
985
|
+
_markedForRepair(repair, parts) {
|
|
986
|
+
return repair ? [["repair", ""], ...parts] : parts;
|
|
888
987
|
}
|
|
889
988
|
|
|
890
989
|
/**
|
|
@@ -1023,7 +1122,7 @@ class RuntimeTemplate {
|
|
|
1023
1122
|
);
|
|
1024
1123
|
}
|
|
1025
1124
|
const chunks = this._moduleChunks(module, chunkGraph);
|
|
1026
|
-
const parts = this._resolvePublicPathPrefix(publicPath
|
|
1125
|
+
const parts = this._resolvePublicPathPrefix(publicPath);
|
|
1027
1126
|
if (parts === null) return null;
|
|
1028
1127
|
// A protocol-relative base names a host but no scheme, and the runtime reads it
|
|
1029
1128
|
// against the chunk's own url to get one — the very url this literal is
|
|
@@ -1032,8 +1131,7 @@ class RuntimeTemplate {
|
|
|
1032
1131
|
if (base.startsWith("//")) {
|
|
1033
1132
|
return this._specifierOf(
|
|
1034
1133
|
[["literal", base], ...rootedParts(parts), ["literal", filename]],
|
|
1035
|
-
chunks
|
|
1036
|
-
module
|
|
1134
|
+
chunks
|
|
1037
1135
|
);
|
|
1038
1136
|
}
|
|
1039
1137
|
if (!isAbsoluteBaseUri(base)) {
|
|
@@ -1065,13 +1163,14 @@ class RuntimeTemplate {
|
|
|
1065
1163
|
);
|
|
1066
1164
|
}
|
|
1067
1165
|
if (text !== null) return toJsStringLiteral(resolved.href);
|
|
1068
|
-
if (!this._canDeferOrBail(chunks, module)) return null;
|
|
1069
1166
|
return toJsStringLiteral(
|
|
1070
|
-
this._reserveAnalyzableSpecifier(
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1167
|
+
this._reserveAnalyzableSpecifier(
|
|
1168
|
+
this._markedForRepair(this._needsRepair(chunks), [
|
|
1169
|
+
["base", base],
|
|
1170
|
+
...parts,
|
|
1171
|
+
["literal", filename]
|
|
1172
|
+
])
|
|
1173
|
+
)
|
|
1075
1174
|
);
|
|
1076
1175
|
}
|
|
1077
1176
|
|
|
@@ -1868,14 +1967,21 @@ class RuntimeTemplate {
|
|
|
1868
1967
|
});
|
|
1869
1968
|
const exportsType = module.getExportsType(chunkGraph.moduleGraph, strict);
|
|
1870
1969
|
switch (exportsType) {
|
|
1871
|
-
case "namespace":
|
|
1872
|
-
|
|
1970
|
+
case "namespace": {
|
|
1971
|
+
const raw = this.moduleRaw({
|
|
1873
1972
|
module,
|
|
1874
1973
|
chunkGraph,
|
|
1875
1974
|
request,
|
|
1876
1975
|
weak,
|
|
1877
1976
|
runtimeRequirements
|
|
1878
1977
|
});
|
|
1978
|
+
|
|
1979
|
+
if (!usesSpecNamespaceObject(module)) return raw;
|
|
1980
|
+
|
|
1981
|
+
runtimeRequirements.add(RuntimeGlobals.specNamespaceObject);
|
|
1982
|
+
|
|
1983
|
+
return `${RuntimeGlobals.specNamespaceObject}(${raw})`;
|
|
1984
|
+
}
|
|
1879
1985
|
case "default-with-named":
|
|
1880
1986
|
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
|
1881
1987
|
return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 3)`;
|
|
@@ -1984,6 +2090,21 @@ class RuntimeTemplate {
|
|
|
1984
2090
|
|
|
1985
2091
|
let mode = getMakeDeferredNamespaceModeFromExportsType(exportsType);
|
|
1986
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
|
+
: "";
|
|
1987
2108
|
|
|
1988
2109
|
const asyncDeps = Array.from(
|
|
1989
2110
|
getOutgoingAsyncModules(chunkGraph.moduleGraph, module),
|
|
@@ -2027,15 +2148,22 @@ class RuntimeTemplate {
|
|
|
2027
2148
|
} else {
|
|
2028
2149
|
let fakeType = 16;
|
|
2029
2150
|
switch (exportsType) {
|
|
2030
|
-
case "namespace":
|
|
2031
|
-
|
|
2032
|
-
|
|
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({
|
|
2033
2156
|
module,
|
|
2034
2157
|
chunkGraph,
|
|
2035
2158
|
request,
|
|
2036
2159
|
weak,
|
|
2037
2160
|
runtimeRequirements
|
|
2038
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
|
+
}
|
|
2039
2167
|
appending = `.then(${this.basicFunction(
|
|
2040
2168
|
"",
|
|
2041
2169
|
`${header}return ${rawModule};`
|
|
@@ -2047,7 +2175,14 @@ class RuntimeTemplate {
|
|
|
2047
2175
|
`${comment}${idExpr}`
|
|
2048
2176
|
)})`;
|
|
2049
2177
|
}
|
|
2178
|
+
|
|
2179
|
+
if (specNamespace && asyncModule) {
|
|
2180
|
+
runtimeRequirements.add(RuntimeGlobals.specNamespaceObject);
|
|
2181
|
+
appending += `.then(${RuntimeGlobals.specNamespaceObject})`;
|
|
2182
|
+
}
|
|
2183
|
+
|
|
2050
2184
|
break;
|
|
2185
|
+
}
|
|
2051
2186
|
case "dynamic":
|
|
2052
2187
|
fakeType |= 4;
|
|
2053
2188
|
/* fall through */
|
|
@@ -2101,6 +2236,15 @@ class RuntimeTemplate {
|
|
|
2101
2236
|
)})`;
|
|
2102
2237
|
}
|
|
2103
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
|
+
}
|
|
2104
2248
|
break;
|
|
2105
2249
|
}
|
|
2106
2250
|
}
|
|
@@ -2407,16 +2551,38 @@ class RuntimeTemplate {
|
|
|
2407
2551
|
`${importVar}_namespace_cache`
|
|
2408
2552
|
)
|
|
2409
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
|
+
}
|
|
2410
2566
|
return `/*#__PURE__*/ ${
|
|
2411
2567
|
asiSafe ? "" : asiSafe === false ? ";" : "Object"
|
|
2412
|
-
}(${importVar}_namespace_cache || (${importVar}_namespace_cache = ${
|
|
2413
|
-
RuntimeGlobals.createFakeNamespaceObject
|
|
2414
|
-
}(${importVar}${exportsType === "default-only" ? "" : ", 2"})))`;
|
|
2568
|
+
}(${importVar}_namespace_cache || (${importVar}_namespace_cache = ${fakeNamespace}))`;
|
|
2415
2569
|
}
|
|
2416
2570
|
}
|
|
2417
2571
|
|
|
2418
2572
|
if (exportName.length > 0) {
|
|
2419
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
|
+
}
|
|
2420
2586
|
// in some case the exported item is renamed (get this by getUsedName). for example,
|
|
2421
2587
|
// x.default might be emitted as x.Z (default is renamed to Z)
|
|
2422
2588
|
const used = exportsInfo.getUsedName(exportName, runtime);
|
|
@@ -2461,9 +2627,19 @@ class RuntimeTemplate {
|
|
|
2461
2627
|
runtimeRequirements.add(RuntimeGlobals.makeDeferredNamespaceObject);
|
|
2462
2628
|
const id = chunkGraph.getModuleId(module);
|
|
2463
2629
|
const type = getMakeDeferredNamespaceModeFromExportsType(exportsType);
|
|
2464
|
-
const
|
|
2465
|
-
|
|
2466
|
-
|
|
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)}` : ""})`;
|
|
2467
2643
|
|
|
2468
2644
|
return `/*#__PURE__*/ ${
|
|
2469
2645
|
asiSafe ? "" : asiSafe === false ? ";" : "Object"
|
|
@@ -2490,6 +2666,16 @@ class RuntimeTemplate {
|
|
|
2490
2666
|
// if we hit here, the importVar is either
|
|
2491
2667
|
// - already a ES module namespace object
|
|
2492
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
|
+
|
|
2493
2679
|
return importVar;
|
|
2494
2680
|
}
|
|
2495
2681
|
|
|
@@ -2570,7 +2756,7 @@ class RuntimeTemplate {
|
|
|
2570
2756
|
* @param {string} options.message the message
|
|
2571
2757
|
* @param {ChunkGraph} options.chunkGraph the chunk graph
|
|
2572
2758
|
* @param {RuntimeRequirements} options.runtimeRequirements if set, will be filled with runtime requirements
|
|
2573
|
-
* @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
|
|
2574
2760
|
* @returns {string} expression
|
|
2575
2761
|
*/
|
|
2576
2762
|
blockPromise({
|
|
@@ -2600,156 +2786,32 @@ class RuntimeTemplate {
|
|
|
2600
2786
|
message,
|
|
2601
2787
|
chunkName: block.chunkName
|
|
2602
2788
|
});
|
|
2603
|
-
//
|
|
2604
|
-
//
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
if (chunks.length === 1) {
|
|
2610
|
-
const analyzable = this.analyzableChunkImport(
|
|
2611
|
-
chunks[0],
|
|
2612
|
-
comment,
|
|
2613
|
-
runtimeRequirements,
|
|
2614
|
-
originModule,
|
|
2615
|
-
chunkGraph
|
|
2616
|
-
);
|
|
2617
|
-
if (analyzable !== null) {
|
|
2618
|
-
return analyzable;
|
|
2619
|
-
}
|
|
2620
|
-
const chunkId = JSON.stringify(chunks[0].id);
|
|
2621
|
-
runtimeRequirements.add(RuntimeGlobals.ensureChunk);
|
|
2622
|
-
|
|
2623
|
-
if (fetchPriority) {
|
|
2624
|
-
runtimeRequirements.add(RuntimeGlobals.hasFetchPriority);
|
|
2625
|
-
}
|
|
2626
|
-
|
|
2627
|
-
return `${RuntimeGlobals.ensureChunk}(${comment}${chunkId}${
|
|
2628
|
-
fetchPriority ? `, ${JSON.stringify(fetchPriority)}` : ""
|
|
2629
|
-
})`;
|
|
2630
|
-
} else if (chunks.length > 0) {
|
|
2631
|
-
let needEnsureChunk = false;
|
|
2632
|
-
/**
|
|
2633
|
-
* Analyzable `import()` for a solely-owned JS chunk, else runtime ensureChunk.
|
|
2634
|
-
* @param {Chunk} chunk chunk
|
|
2635
|
-
* @returns {string} require chunk id code
|
|
2636
|
-
*/
|
|
2637
|
-
const requireChunkId = (chunk) => {
|
|
2638
|
-
const analyzable = this.analyzableChunkImport(
|
|
2639
|
-
chunk,
|
|
2640
|
-
"",
|
|
2641
|
-
runtimeRequirements,
|
|
2642
|
-
originModule,
|
|
2643
|
-
chunkGraph
|
|
2644
|
-
);
|
|
2645
|
-
if (analyzable !== null) return analyzable;
|
|
2646
|
-
needEnsureChunk = true;
|
|
2647
|
-
return `${RuntimeGlobals.ensureChunk}(${JSON.stringify(chunk.id)}${
|
|
2648
|
-
fetchPriority ? `, ${JSON.stringify(fetchPriority)}` : ""
|
|
2649
|
-
})`;
|
|
2650
|
-
};
|
|
2651
|
-
const items = chunks.map(requireChunkId);
|
|
2652
|
-
if (needEnsureChunk) {
|
|
2653
|
-
runtimeRequirements.add(RuntimeGlobals.ensureChunk);
|
|
2654
|
-
// Only needed when an `ensureChunk(id, priority)` call is actually emitted.
|
|
2655
|
-
if (fetchPriority) {
|
|
2656
|
-
runtimeRequirements.add(RuntimeGlobals.hasFetchPriority);
|
|
2657
|
-
}
|
|
2658
|
-
}
|
|
2659
|
-
return `Promise.all(${comment.trim()}[${items.join(", ")}])`;
|
|
2660
|
-
}
|
|
2661
|
-
return `Promise.resolve(${comment.trim()})`;
|
|
2662
|
-
}
|
|
2663
|
-
|
|
2664
|
-
/**
|
|
2665
|
-
* Whether any module of `chunk` carries a source type with a chunk handler of its
|
|
2666
|
-
* own, which `.ei` dispatches alongside the javascript one.
|
|
2667
|
-
* @param {Chunk} chunk the chunk being imported
|
|
2668
|
-
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
2669
|
-
* @returns {boolean} true when a handler beyond the javascript one is reached
|
|
2670
|
-
*/
|
|
2671
|
-
_chunkLoadsBeyondJs(chunk, chunkGraph) {
|
|
2672
|
-
for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
|
|
2673
|
-
for (const type of chunkGraph.getModuleSourceTypes(module)) {
|
|
2674
|
-
if (!TYPES_WITHOUT_CHUNK_HANDLER.has(type)) return true;
|
|
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);
|
|
2675
2795
|
}
|
|
2676
2796
|
}
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
* @param {Chunk} chunk the chunk to load
|
|
2686
|
-
* @param {string} comment leading comment (chunk name / message)
|
|
2687
|
-
* @param {RuntimeRequirements} runtimeRequirements runtime requirements
|
|
2688
|
-
* @param {Module | undefined} originModule the module the `import()` is emitted into
|
|
2689
|
-
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
2690
|
-
* @returns {string | null} the import expression, or `null`
|
|
2691
|
-
*/
|
|
2692
|
-
analyzableChunkImport(
|
|
2693
|
-
chunk,
|
|
2694
|
-
comment,
|
|
2695
|
-
runtimeRequirements,
|
|
2696
|
-
originModule,
|
|
2697
|
-
chunkGraph
|
|
2698
|
-
) {
|
|
2699
|
-
// `blockPromise` has already dropped any chunk without an id. Without an origin
|
|
2700
|
-
// there is nothing the specifier could be relative to.
|
|
2701
|
-
if (
|
|
2702
|
-
!originModule ||
|
|
2703
|
-
!this.supportsAnalyzable("import", chunkGraph, originModule)
|
|
2704
|
-
) {
|
|
2705
|
-
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);
|
|
2706
2805
|
}
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
if (!JavascriptModulesPlugin.chunkHasJs(chunk, chunkGraph)) {
|
|
2711
|
-
return this._analyzableBailout(
|
|
2712
|
-
originModule,
|
|
2713
|
-
"this compilation emits no javascript for the chunk, so there is nothing to import",
|
|
2714
|
-
null
|
|
2715
|
-
);
|
|
2806
|
+
if (chunks.length === 1) {
|
|
2807
|
+
const chunkId = JSON.stringify(chunks[0].id);
|
|
2808
|
+
return `${RuntimeGlobals.ensureChunk}(${comment}${chunkId}${priorityArg})`;
|
|
2716
2809
|
}
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
undefined,
|
|
2721
|
-
chunk,
|
|
2722
|
-
originModule,
|
|
2723
|
-
chunkGraph
|
|
2810
|
+
const items = chunks.map(
|
|
2811
|
+
(chunk) =>
|
|
2812
|
+
`${RuntimeGlobals.ensureChunk}(${JSON.stringify(chunk.id)}${priorityArg})`
|
|
2724
2813
|
);
|
|
2725
|
-
|
|
2726
|
-
return null;
|
|
2727
|
-
}
|
|
2728
|
-
// `import()` needs a resolvable specifier — relative (`./`, `../`), absolute (`/`)
|
|
2729
|
-
// or a URL scheme. A bare one is a package name, so make it explicitly relative
|
|
2730
|
-
// the way the chunk loader does. (`new URL(...)` callers accept bare vs their base.)
|
|
2731
|
-
const resolvableSpecifier = /^"(?:\.{0,2}\/|[a-zA-Z][\w+.-]*:)/.test(
|
|
2732
|
-
specifier
|
|
2733
|
-
)
|
|
2734
|
-
? specifier
|
|
2735
|
-
: `"./${specifier.slice(1)}`;
|
|
2736
|
-
runtimeRequirements.add(RuntimeGlobals.analyzableChunkImport);
|
|
2737
|
-
// Prefetch/preload children and every non-javascript source type are loaded by a
|
|
2738
|
-
// `.f` handler, which `.ei` dispatches — but they attach to `.f`, so it has to
|
|
2739
|
-
// exist. The runtime `ensureChunk` around it does not.
|
|
2740
|
-
if (
|
|
2741
|
-
chunk.hasChildByOrder(chunkGraph, "prefetch", true) ||
|
|
2742
|
-
chunk.hasChildByOrder(chunkGraph, "preload", true) ||
|
|
2743
|
-
chunk.hasChildByOrder(chunkGraph, "cssPreload", true) ||
|
|
2744
|
-
this._chunkLoadsBeyondJs(chunk, chunkGraph)
|
|
2745
|
-
) {
|
|
2746
|
-
runtimeRequirements.add(RuntimeGlobals.ensureChunkHandlers);
|
|
2747
|
-
}
|
|
2748
|
-
// Drop-in for `ensureChunk(id)`: the literal `import()` can be statically
|
|
2749
|
-
// followed, the helper keeps webpack's install timing and deduplication.
|
|
2750
|
-
return `${RuntimeGlobals.analyzableChunkImport}(${JSON.stringify(
|
|
2751
|
-
chunk.id
|
|
2752
|
-
)}, ${this.returningFunction(`import(${comment}${resolvableSpecifier})`)})`;
|
|
2814
|
+
return `Promise.all(${comment.trim()}[${items.join(", ")}])`;
|
|
2753
2815
|
}
|
|
2754
2816
|
|
|
2755
2817
|
/**
|
|
@@ -2785,6 +2847,17 @@ class RuntimeTemplate {
|
|
|
2785
2847
|
const late = this._settlesLate(chunk);
|
|
2786
2848
|
if (late !== this._settlesLate(target)) return !late;
|
|
2787
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) {
|
|
2788
2861
|
const chunkGraph = /** @type {ChunkGraph} */ (this.compilation.chunkGraph);
|
|
2789
2862
|
const round = hashRound(chunk, chunkGraph);
|
|
2790
2863
|
const targetRound = hashRound(target, chunkGraph);
|
|
@@ -2807,6 +2880,42 @@ class RuntimeTemplate {
|
|
|
2807
2880
|
);
|
|
2808
2881
|
}
|
|
2809
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
|
+
|
|
2810
2919
|
/**
|
|
2811
2920
|
* Whether `createHash` settles this chunk's hash in the round that runs after the
|
|
2812
2921
|
* compilation hash rather than in one of the four before it. Asked of the chunk
|
|
@@ -3068,35 +3177,6 @@ class RuntimeTemplate {
|
|
|
3068
3177
|
this._chunksByIdForFold = undefined;
|
|
3069
3178
|
}
|
|
3070
3179
|
|
|
3071
|
-
/**
|
|
3072
|
-
* Whether `chunk` can reach any of `targets` by following chunk groups, which is
|
|
3073
|
-
* what turns a baked hashed name into a hash that depends on itself.
|
|
3074
|
-
* @param {Chunk} chunk the referenced chunk
|
|
3075
|
-
* @param {Iterable<Chunk>} targets the chunks the reference is written into
|
|
3076
|
-
* @returns {boolean} true when one of them is reachable from `chunk`
|
|
3077
|
-
*/
|
|
3078
|
-
_reachesAny(chunk, targets) {
|
|
3079
|
-
const wanted = new Set(targets);
|
|
3080
|
-
if (wanted.size === 0) return false;
|
|
3081
|
-
if (wanted.has(chunk)) return true;
|
|
3082
|
-
/** @type {Set<ChunkGroup>} */
|
|
3083
|
-
const seen = new Set();
|
|
3084
|
-
/** @type {ChunkGroup[]} */
|
|
3085
|
-
const queue = [...chunk.groupsIterable];
|
|
3086
|
-
for (const group of queue) seen.add(group);
|
|
3087
|
-
for (let i = 0; i < queue.length; i++) {
|
|
3088
|
-
for (const child of queue[i].childrenIterable) {
|
|
3089
|
-
if (seen.has(child)) continue;
|
|
3090
|
-
seen.add(child);
|
|
3091
|
-
for (const candidate of child.chunks) {
|
|
3092
|
-
if (wanted.has(candidate)) return true;
|
|
3093
|
-
}
|
|
3094
|
-
queue.push(child);
|
|
3095
|
-
}
|
|
3096
|
-
}
|
|
3097
|
-
return false;
|
|
3098
|
-
}
|
|
3099
|
-
|
|
3100
3180
|
/**
|
|
3101
3181
|
* The chunks a reference emitted into `module` is written into — the assets a
|
|
3102
3182
|
* stand-in of ours would land in, and so the only ones a deferred fill could go
|
|
@@ -3212,7 +3292,7 @@ class RuntimeTemplate {
|
|
|
3212
3292
|
* The `../` path from a chunk's own asset back to the output root. Hashes are
|
|
3213
3293
|
* neutralized first: a runtime module is generated once to be hashed, before any
|
|
3214
3294
|
* hash exists, so resolving one there throws — and `RuntimeModule.updateHash`
|
|
3215
|
-
*
|
|
3295
|
+
* lets that throw fail the build rather than hashing it.
|
|
3216
3296
|
* @param {Chunk} chunk the chunk whose asset holds the reference
|
|
3217
3297
|
* @param {boolean} enforceRelative whether the answer keeps a leading `./`
|
|
3218
3298
|
* @returns {string} the path back to the output root
|
|
@@ -3243,7 +3323,10 @@ class RuntimeTemplate {
|
|
|
3243
3323
|
* @returns {Placement} where a literal in it is read from
|
|
3244
3324
|
*/
|
|
3245
3325
|
_modulePlacement(module, chunkGraph) {
|
|
3246
|
-
return this._placementOf(
|
|
3326
|
+
return this._placementOf(
|
|
3327
|
+
this._moduleChunks(module, chunkGraph),
|
|
3328
|
+
isHotModule(module)
|
|
3329
|
+
);
|
|
3247
3330
|
}
|
|
3248
3331
|
|
|
3249
3332
|
/**
|
|
@@ -3262,11 +3345,12 @@ class RuntimeTemplate {
|
|
|
3262
3345
|
|
|
3263
3346
|
/**
|
|
3264
3347
|
* The one answer every chunk in `chunks` agrees on, with either half `null` where
|
|
3265
|
-
* they do not.
|
|
3348
|
+
* they do not — under HMR the update chunk, which re-runs the module, has a say too.
|
|
3266
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
|
|
3267
3351
|
* @returns {Placement} where a literal in them is read from
|
|
3268
3352
|
*/
|
|
3269
|
-
_placementOf(chunks) {
|
|
3353
|
+
_placementOf(chunks, hot = false) {
|
|
3270
3354
|
/** @type {Placement | undefined} */
|
|
3271
3355
|
let first;
|
|
3272
3356
|
/** @type {string | null} */
|
|
@@ -3275,13 +3359,17 @@ class RuntimeTemplate {
|
|
|
3275
3359
|
let loaded = null;
|
|
3276
3360
|
for (const chunk of chunks) {
|
|
3277
3361
|
const own = this._chunkPlacement(chunk);
|
|
3362
|
+
const ownUndo =
|
|
3363
|
+
hot && own.undo !== null && own.undo !== this._hotUpdateUndo(chunk)
|
|
3364
|
+
? null
|
|
3365
|
+
: own.undo;
|
|
3278
3366
|
if (first === undefined) {
|
|
3279
3367
|
first = own;
|
|
3280
|
-
undo =
|
|
3368
|
+
undo = ownUndo;
|
|
3281
3369
|
loaded = own.loaded;
|
|
3282
3370
|
continue;
|
|
3283
3371
|
}
|
|
3284
|
-
if (undo !==
|
|
3372
|
+
if (undo !== ownUndo) undo = null;
|
|
3285
3373
|
if (loaded !== own.loaded) loaded = null;
|
|
3286
3374
|
}
|
|
3287
3375
|
if (first === undefined) return NO_PLACEMENT;
|
|
@@ -3301,16 +3389,9 @@ class RuntimeTemplate {
|
|
|
3301
3389
|
* @param {Chunk} chunk the worker's entry chunk
|
|
3302
3390
|
* @param {Module} module the module the reference is emitted into
|
|
3303
3391
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3304
|
-
* @param {RuntimeRequirements} runtimeRequirements what the consuming chunk needs
|
|
3305
3392
|
* @returns {string | null} a quoted literal, or `null` to fall back
|
|
3306
3393
|
*/
|
|
3307
|
-
getAnalyzableWorkerUrl(
|
|
3308
|
-
overridePublicPath,
|
|
3309
|
-
chunk,
|
|
3310
|
-
module,
|
|
3311
|
-
chunkGraph,
|
|
3312
|
-
runtimeRequirements
|
|
3313
|
-
) {
|
|
3394
|
+
getAnalyzableWorkerUrl(overridePublicPath, chunk, module, chunkGraph) {
|
|
3314
3395
|
// Without an id nothing can name the chunk in a stand-in.
|
|
3315
3396
|
if (
|
|
3316
3397
|
chunk.id === null ||
|
|
@@ -3322,8 +3403,7 @@ class RuntimeTemplate {
|
|
|
3322
3403
|
overridePublicPath,
|
|
3323
3404
|
chunk,
|
|
3324
3405
|
module,
|
|
3325
|
-
chunkGraph
|
|
3326
|
-
runtimeRequirements
|
|
3406
|
+
chunkGraph
|
|
3327
3407
|
);
|
|
3328
3408
|
}
|
|
3329
3409
|
|
|
@@ -3336,12 +3416,11 @@ class RuntimeTemplate {
|
|
|
3336
3416
|
* @param {Module | undefined} consumingModule the module the reference is emitted
|
|
3337
3417
|
* into, or `undefined` when `consumingChunks` names where it goes instead
|
|
3338
3418
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3339
|
-
* @param {RuntimeRequirements=} runtimeRequirements set when the caller wraps the result in
|
|
3340
|
-
* `new URL(...)` and so accepts a runtime public path prefix around the literal filename
|
|
3341
3419
|
* @param {Chunk[]=} consumingChunks the chunks the reference is written into, where
|
|
3342
3420
|
* they are known without a module to read them from
|
|
3343
3421
|
* @param {string=} sourceType which half of the chunk is named — its javascript by
|
|
3344
3422
|
* default, or its stylesheet
|
|
3423
|
+
* @param {boolean=} hot whether a hot update can re-run what is written
|
|
3345
3424
|
* @returns {string | null} a JS string literal or expression, or `null` to fall back to the runtime form
|
|
3346
3425
|
*/
|
|
3347
3426
|
_getAnalyzableChunkSpecifier(
|
|
@@ -3349,20 +3428,16 @@ class RuntimeTemplate {
|
|
|
3349
3428
|
chunk,
|
|
3350
3429
|
consumingModule,
|
|
3351
3430
|
chunkGraph,
|
|
3352
|
-
runtimeRequirements,
|
|
3353
3431
|
consumingChunks,
|
|
3354
|
-
sourceType = JAVASCRIPT_TYPE
|
|
3432
|
+
sourceType = JAVASCRIPT_TYPE,
|
|
3433
|
+
hot = isHotModule(consumingModule)
|
|
3355
3434
|
) {
|
|
3356
3435
|
const { compilation } = this;
|
|
3357
3436
|
const { outputOptions } = compilation;
|
|
3358
3437
|
const naming = CHUNK_ASSET_NAMING.get(sourceType);
|
|
3359
3438
|
// Nothing here names this type's asset, so nothing can spell where it will be.
|
|
3360
3439
|
if (naming === undefined) return null;
|
|
3361
|
-
const template = this.
|
|
3362
|
-
naming.template(chunk, outputOptions),
|
|
3363
|
-
chunk,
|
|
3364
|
-
sourceType
|
|
3365
|
-
);
|
|
3440
|
+
const template = this._chunkAssetTemplate(chunk, sourceType);
|
|
3366
3441
|
if (template === null) return null;
|
|
3367
3442
|
// A hashed name is settled long after this code is generated, so a stand-in is
|
|
3368
3443
|
// emitted and filled in once the hash exists.
|
|
@@ -3374,92 +3449,93 @@ class RuntimeTemplate {
|
|
|
3374
3449
|
const chunks =
|
|
3375
3450
|
consumingChunks ||
|
|
3376
3451
|
this._moduleChunks(/** @type {Module} */ (consumingModule), chunkGraph);
|
|
3377
|
-
|
|
3378
|
-
//
|
|
3379
|
-
|
|
3380
|
-
//
|
|
3381
|
-
//
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
chunk
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
//
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
if (deferred && !canReserve && !canFold) return cannotReserve();
|
|
3402
|
-
const filename = deferred
|
|
3403
|
-
? ""
|
|
3404
|
-
: compilation.getPath(/** @type {string} */ (template), {
|
|
3405
|
-
chunk,
|
|
3406
|
-
// Matches what names the asset, or a placeholder resolved here would
|
|
3407
|
-
// not be the one on disk.
|
|
3408
|
-
runtime: chunk.runtime,
|
|
3409
|
-
contentHashType: sourceType
|
|
3410
|
-
});
|
|
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
|
+
});
|
|
3411
3476
|
/**
|
|
3412
3477
|
* @param {SpecifierPart[]} prefix what goes in front of the chunk's filename
|
|
3413
|
-
* @returns {string
|
|
3414
|
-
* recipe needs a stand-in that cannot be reserved
|
|
3478
|
+
* @returns {string} the specifier already quoted
|
|
3415
3479
|
*/
|
|
3416
3480
|
const specifier = (prefix) => {
|
|
3417
|
-
if (!deferred) {
|
|
3481
|
+
if (!deferred || settled) {
|
|
3418
3482
|
const text = literalText(prefix);
|
|
3419
3483
|
if (text !== null) return toJsStringLiteral(text + filename);
|
|
3420
3484
|
}
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
}
|
|
3485
|
+
const repair =
|
|
3486
|
+
!canReserve && !(canFold && this._foldsWholeName(prefix, chunks));
|
|
3424
3487
|
return toJsStringLiteral(
|
|
3425
|
-
this._reserveAnalyzableSpecifier(
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
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
|
+
)
|
|
3429
3498
|
);
|
|
3430
3499
|
};
|
|
3431
3500
|
if (overridePublicPath) {
|
|
3432
|
-
const resolved = this._resolvePublicPathPrefix(
|
|
3433
|
-
overridePublicPath,
|
|
3434
|
-
consumingModule,
|
|
3435
|
-
chunks
|
|
3436
|
-
);
|
|
3501
|
+
const resolved = this._resolvePublicPathPrefix(overridePublicPath);
|
|
3437
3502
|
return resolved === null ? null : specifier(resolved);
|
|
3438
3503
|
}
|
|
3439
3504
|
const { publicPath } = outputOptions;
|
|
3440
3505
|
if (publicPath === "auto") {
|
|
3441
|
-
const { undo } = this._placementOf(chunks);
|
|
3506
|
+
const { undo } = this._placementOf(chunks, hot);
|
|
3442
3507
|
if (undo !== null) return specifier([["literal", undo]]);
|
|
3443
3508
|
// Different depths — no one `../` path is right for every asset the reference
|
|
3444
3509
|
// lands in, so the deferred pass builds each asset's own.
|
|
3445
|
-
|
|
3446
|
-
if (perAsset !== null) return perAsset;
|
|
3447
|
-
// Only a stand-in that could not be reserved reaches here, and `specifier`
|
|
3448
|
-
// has already recorded why.
|
|
3449
|
-
if (deferred || !runtimeRequirements) return null;
|
|
3450
|
-
// No bundler follows a concatenation, but a `new URL(...)` caller still sheds
|
|
3451
|
-
// the `.u(id)` lookup this way; `import()` needs a static specifier.
|
|
3452
|
-
runtimeRequirements.add(RuntimeGlobals.publicPath);
|
|
3453
|
-
return `${RuntimeGlobals.publicPath} + ${toJsStringLiteral(filename)}`;
|
|
3510
|
+
return specifier([["undo", ""]]);
|
|
3454
3511
|
}
|
|
3455
3512
|
const prefix = this._analyzablePathPrefix(
|
|
3456
3513
|
consumingModule,
|
|
3457
3514
|
chunkGraph,
|
|
3458
|
-
chunks
|
|
3515
|
+
chunks,
|
|
3516
|
+
undefined,
|
|
3517
|
+
hot
|
|
3459
3518
|
);
|
|
3460
3519
|
return prefix === null ? null : specifier(prefix);
|
|
3461
3520
|
}
|
|
3462
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
|
+
|
|
3463
3539
|
/**
|
|
3464
3540
|
* The parts that go in front of a name so a literal read from the chunk holding it
|
|
3465
3541
|
* reaches what the runtime would. A public path needing no base is the whole answer.
|
|
@@ -3473,18 +3549,24 @@ class RuntimeTemplate {
|
|
|
3473
3549
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3474
3550
|
* @param {Iterable<Chunk>} chunks the chunks a stand-in would be written into
|
|
3475
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
|
|
3476
3553
|
* @returns {SpecifierPart[] | null} the parts, or `null` having recorded why not
|
|
3477
3554
|
*/
|
|
3478
|
-
_analyzablePathPrefix(
|
|
3555
|
+
_analyzablePathPrefix(
|
|
3556
|
+
module,
|
|
3557
|
+
chunkGraph,
|
|
3558
|
+
chunks,
|
|
3559
|
+
relativeBase,
|
|
3560
|
+
hot = isHotModule(module)
|
|
3561
|
+
) {
|
|
3479
3562
|
const publicPath = /** @type {PublicPath} */ (
|
|
3480
3563
|
this.outputOptions.publicPath
|
|
3481
3564
|
);
|
|
3482
3565
|
const shape = this._publicPathShape();
|
|
3483
3566
|
if (shape === undefined) return null;
|
|
3484
|
-
const resolve = () =>
|
|
3485
|
-
this._resolvePublicPathPrefix(publicPath, module, chunks);
|
|
3567
|
+
const resolve = () => this._resolvePublicPathPrefix(publicPath);
|
|
3486
3568
|
if (isBaseIndependent(shape)) return resolve();
|
|
3487
|
-
const { undo, loaded } = this._placementOf(chunks);
|
|
3569
|
+
const { undo, loaded } = this._placementOf(chunks, hot);
|
|
3488
3570
|
// What a chunk the loader fetched climbs back out of. One of no depth leaves
|
|
3489
3571
|
// nothing to climb, and then both answers put the same text in front.
|
|
3490
3572
|
const served = this._publicPathClimb();
|
|
@@ -3518,12 +3600,9 @@ class RuntimeTemplate {
|
|
|
3518
3600
|
* the deferred pass whole instead. A function is called for its value rather than
|
|
3519
3601
|
* read as a template, so one whose answer moves with the hash is called again there.
|
|
3520
3602
|
* @param {PublicPath} publicPath the configured public path
|
|
3521
|
-
* @param {Module=} module the module the reference is emitted into, to record why
|
|
3522
|
-
* a name no stand-in may be reserved for kept the runtime form
|
|
3523
|
-
* @param {Iterable<Chunk>=} chunks the chunks a stand-in would be written into
|
|
3524
3603
|
* @returns {SpecifierPart[] | null} the parts, or `null` when it cannot be known
|
|
3525
3604
|
*/
|
|
3526
|
-
_resolvePublicPathPrefix(publicPath
|
|
3605
|
+
_resolvePublicPathPrefix(publicPath) {
|
|
3527
3606
|
if (typeof publicPath === "function") {
|
|
3528
3607
|
// One that answers nothing to a probe cannot be placed, absolute or not.
|
|
3529
3608
|
if (this._publicPathShape() === undefined) return null;
|
|
@@ -3534,28 +3613,18 @@ class RuntimeTemplate {
|
|
|
3534
3613
|
if (resolved !== null) return [["literal", resolved]];
|
|
3535
3614
|
// Called again by the fill against the compilation hash, so what it answers
|
|
3536
3615
|
// there is that hash by another name.
|
|
3537
|
-
return
|
|
3538
|
-
? [["publicPath", ""]]
|
|
3539
|
-
: null;
|
|
3616
|
+
return [["publicPath", ""]];
|
|
3540
3617
|
}
|
|
3541
3618
|
if (!publicPath.includes("[")) return [["literal", publicPath]];
|
|
3542
3619
|
// A re-encoded digest cannot be spelled by a stand-in, so it stays a template.
|
|
3543
3620
|
if (getTemplatedPathPlugin().usesFullHashDigest(publicPath)) {
|
|
3544
|
-
return
|
|
3545
|
-
? [["template", publicPath]]
|
|
3546
|
-
: null;
|
|
3621
|
+
return [["template", publicPath]];
|
|
3547
3622
|
}
|
|
3548
3623
|
const literal = this.compilation.getPath(
|
|
3549
3624
|
publicPath,
|
|
3550
3625
|
this._deferredFullHashPathData()
|
|
3551
3626
|
);
|
|
3552
|
-
return
|
|
3553
|
-
this._hasReservedFullHash(literal),
|
|
3554
|
-
chunks,
|
|
3555
|
-
module
|
|
3556
|
-
)
|
|
3557
|
-
? [["literal", literal]]
|
|
3558
|
-
: null;
|
|
3627
|
+
return [["literal", literal]];
|
|
3559
3628
|
}
|
|
3560
3629
|
|
|
3561
3630
|
/**
|
|
@@ -3640,7 +3709,7 @@ class RuntimeTemplate {
|
|
|
3640
3709
|
relativeBase
|
|
3641
3710
|
);
|
|
3642
3711
|
if (prefix === null) return null;
|
|
3643
|
-
return this._specifierOf([...prefix, ...file], chunks
|
|
3712
|
+
return this._specifierOf([...prefix, ...file], chunks);
|
|
3644
3713
|
}
|
|
3645
3714
|
// No public path to place it against, so the `../` path back to the output root
|
|
3646
3715
|
// is the whole prefix. Different depths — no one is right for every asset the
|
|
@@ -3650,23 +3719,22 @@ class RuntimeTemplate {
|
|
|
3650
3719
|
const parts = [undo === null ? ["undo", ""] : ["literal", undo]];
|
|
3651
3720
|
if (relativeBase !== undefined) parts.push(["literal", relativeBase]);
|
|
3652
3721
|
parts.push(...file);
|
|
3653
|
-
return this._specifierOf(parts, chunks
|
|
3722
|
+
return this._specifierOf(parts, chunks);
|
|
3654
3723
|
}
|
|
3655
3724
|
|
|
3656
3725
|
/**
|
|
3657
3726
|
* Static `new URL(<file>, import.meta.url)` for every stylesheet a runtime can load,
|
|
3658
|
-
* keyed by chunk id
|
|
3659
|
-
*
|
|
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
|
|
3660
3729
|
* and the plugin declaring what it needs ask this, so the two always agree. The
|
|
3661
3730
|
* runtime hands an absolute url string to `link.href`, and so does this — the browser
|
|
3662
3731
|
* resolves the element against the document, which is not where the chunk sits, and
|
|
3663
|
-
* the loader reads the url as text either way.
|
|
3664
|
-
* that also carries the hot handler; see below.
|
|
3732
|
+
* the loader reads the url as text either way.
|
|
3665
3733
|
* @param {Chunk} runtimeChunk the chunk holding the stylesheet loader
|
|
3666
3734
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3667
3735
|
* @param {ReadOnlyRuntimeRequirements} runtimeRequirements what that chunk needs
|
|
3668
3736
|
* @param {Module=} consumingModule the runtime module, where one exists to report against
|
|
3669
|
-
* @returns {
|
|
3737
|
+
* @returns {Map<ChunkId, string> | null} the urls, or `null` to keep the runtime form
|
|
3670
3738
|
*/
|
|
3671
3739
|
analyzableCssChunkUrls(
|
|
3672
3740
|
runtimeChunk,
|
|
@@ -3698,14 +3766,14 @@ class RuntimeTemplate {
|
|
|
3698
3766
|
/**
|
|
3699
3767
|
* Static `new URL(<file>, import.meta.url).href` for every javascript chunk a
|
|
3700
3768
|
* runtime can hint at with `<link rel="prefetch"/"modulepreload">`, keyed by chunk
|
|
3701
|
-
* id
|
|
3702
|
-
*
|
|
3769
|
+
* id, or `null` when they have to keep the runtime
|
|
3770
|
+
* `publicPath + getChunkScriptFilename(id)` form. Both the runtime module reading
|
|
3703
3771
|
* them and the plugin declaring what it needs ask this, so the two always agree.
|
|
3704
3772
|
* @param {Chunk} runtimeChunk the chunk holding the hint handlers
|
|
3705
3773
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3706
3774
|
* @param {ReadOnlyRuntimeRequirements} runtimeRequirements what that chunk needs
|
|
3707
3775
|
* @param {Module=} consumingModule the runtime module, where one exists to report against
|
|
3708
|
-
* @returns {
|
|
3776
|
+
* @returns {Map<ChunkId, string> | null} the urls, or `null` to keep the runtime form
|
|
3709
3777
|
*/
|
|
3710
3778
|
analyzableChunkScriptUrls(
|
|
3711
3779
|
runtimeChunk,
|
|
@@ -3742,17 +3810,156 @@ class RuntimeTemplate {
|
|
|
3742
3810
|
);
|
|
3743
3811
|
}
|
|
3744
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
|
+
|
|
3745
3953
|
/**
|
|
3746
3954
|
* The urls of one asset of each of `chunks`, written out so they can be read by
|
|
3747
|
-
* chunk id
|
|
3748
|
-
* 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.
|
|
3749
3956
|
* @param {Iterable<Chunk>} chunks the chunks whose asset is wanted
|
|
3750
3957
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3751
3958
|
* @param {Module | undefined} consumingModule the runtime module, where one exists to report against
|
|
3752
3959
|
* @param {Chunk[]} consumingChunks the chunks the urls are written into
|
|
3753
3960
|
* @param {string} sourceType which asset of each chunk to name
|
|
3754
3961
|
* @param {ReadOnlyRuntimeRequirements} runtimeRequirements what the runtime chunk needs
|
|
3755
|
-
* @returns {
|
|
3962
|
+
* @returns {Map<ChunkId, string> | null} the urls, or `null` to keep the runtime form
|
|
3756
3963
|
*/
|
|
3757
3964
|
_analyzableChunkUrls(
|
|
3758
3965
|
chunks,
|
|
@@ -3762,17 +3969,51 @@ class RuntimeTemplate {
|
|
|
3762
3969
|
sourceType,
|
|
3763
3970
|
runtimeRequirements
|
|
3764
3971
|
) {
|
|
3765
|
-
|
|
3766
|
-
// to HMR — analyzable output is what ships.
|
|
3767
|
-
if (
|
|
3768
|
-
runtimeRequirements.has(RuntimeGlobals.hmrDownloadUpdateHandlers) ||
|
|
3769
|
-
!this.supportsAnalyzable("url-runtime", chunkGraph, consumingModule)
|
|
3770
|
-
) {
|
|
3972
|
+
if (!this.supportsAnalyzable("url-runtime", chunkGraph, consumingModule)) {
|
|
3771
3973
|
return null;
|
|
3772
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
|
+
);
|
|
3773
4015
|
/** @type {Map<ChunkId, string>} */
|
|
3774
|
-
const
|
|
3775
|
-
let complete = true;
|
|
4016
|
+
const specifiers = new Map();
|
|
3776
4017
|
for (const chunk of chunks) {
|
|
3777
4018
|
if (chunk.id === null) continue;
|
|
3778
4019
|
const specifier = this._getAnalyzableChunkSpecifier(
|
|
@@ -3780,18 +4021,74 @@ class RuntimeTemplate {
|
|
|
3780
4021
|
chunk,
|
|
3781
4022
|
consumingModule,
|
|
3782
4023
|
chunkGraph,
|
|
3783
|
-
undefined,
|
|
3784
4024
|
consumingChunks,
|
|
3785
|
-
sourceType
|
|
4025
|
+
sourceType,
|
|
4026
|
+
hot
|
|
3786
4027
|
);
|
|
3787
|
-
|
|
3788
|
-
if (
|
|
3789
|
-
|
|
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))) {
|
|
3790
4057
|
continue;
|
|
3791
4058
|
}
|
|
3792
|
-
|
|
4059
|
+
if (!CHUNK_SPECIFIER_PART_KINDS.has(kind)) return false;
|
|
3793
4060
|
}
|
|
3794
|
-
|
|
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;
|
|
3795
4092
|
}
|
|
3796
4093
|
|
|
3797
4094
|
/**
|
|
@@ -3997,7 +4294,7 @@ class RuntimeTemplate {
|
|
|
3997
4294
|
* @returns {string} the stand-in to emit
|
|
3998
4295
|
*/
|
|
3999
4296
|
_reserveAnalyzableSpecifier(parts) {
|
|
4000
|
-
return
|
|
4297
|
+
return `${ANALYZABLE_TOKEN_PREFIX}${Buffer.from(JSON.stringify(parts))
|
|
4001
4298
|
.toString("base64")
|
|
4002
4299
|
.replace(/\+/g, "-")
|
|
4003
4300
|
.replace(/\//g, "_")
|
|
@@ -4068,6 +4365,10 @@ class RuntimeTemplate {
|
|
|
4068
4365
|
async () => {
|
|
4069
4366
|
const { outputOptions } = compilation;
|
|
4070
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();
|
|
4071
4372
|
/** @type {Map<string, Chunk> | undefined} */
|
|
4072
4373
|
let chunksById;
|
|
4073
4374
|
/** @type {Map<string, Chunk> | undefined} */
|
|
@@ -4122,7 +4423,9 @@ class RuntimeTemplate {
|
|
|
4122
4423
|
let base;
|
|
4123
4424
|
let specifier = "";
|
|
4124
4425
|
for (const [kind, value] of parts) {
|
|
4125
|
-
if (kind === "
|
|
4426
|
+
if (kind === "repair") {
|
|
4427
|
+
repairedAssets.add(assetName);
|
|
4428
|
+
} else if (kind === "base") {
|
|
4126
4429
|
base = /** @type {string} */ (value);
|
|
4127
4430
|
} else if (kind === "literal") {
|
|
4128
4431
|
specifier += value;
|
|
@@ -4193,7 +4496,7 @@ class RuntimeTemplate {
|
|
|
4193
4496
|
// the chunk loader does. A literal part may still carry a stand-in of its own,
|
|
4194
4497
|
// so finish those here rather than scanning again.
|
|
4195
4498
|
return fillFullHash(
|
|
4196
|
-
|
|
4499
|
+
RESOLVABLE_SPECIFIER_REGEXP.test(specifier)
|
|
4197
4500
|
? specifier
|
|
4198
4501
|
: `./${specifier}`
|
|
4199
4502
|
);
|
|
@@ -4246,6 +4549,8 @@ class RuntimeTemplate {
|
|
|
4246
4549
|
|
|
4247
4550
|
tasks.push({ name, source, replacements });
|
|
4248
4551
|
}
|
|
4552
|
+
compilation.runtimeTemplate._analyzableRepairedAssets =
|
|
4553
|
+
repairedAssets;
|
|
4249
4554
|
if (tasks.length === 0) return;
|
|
4250
4555
|
|
|
4251
4556
|
await Promise.all(
|