@depup/webpack 5.110.3-depup.0 → 5.111.1-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -8
- package/changes.json +7 -11
- package/lib/APIPlugin.js +26 -11
- 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/CompatibilityPlugin.js +3 -4
- package/lib/Compilation.js +336 -337
- package/lib/Compiler.js +213 -51
- package/lib/ConstPlugin.js +16 -132
- package/lib/CopyPlugin.js +1054 -0
- package/lib/DefinePlugin.js +24 -8
- package/lib/DependencyTemplate.js +2 -1
- package/lib/DotenvPlugin.js +24 -28
- package/lib/ErrorHelpers.js +113 -0
- package/lib/ExportsInfo.js +20 -16
- package/lib/ExternalModule.js +47 -22
- package/lib/FileSystemInfo.js +17 -14
- package/lib/FlagDependencyExportsPlugin.js +53 -34
- package/lib/FlagDependencyUsagePlugin.js +9 -13
- package/lib/Generator.js +24 -2
- package/lib/HotModuleReplacementPlugin.js +55 -7
- package/lib/IgnorePlugin.js +1 -1
- package/lib/JavascriptMetaInfoPlugin.js +5 -3
- package/lib/LoaderOptionsPlugin.js +1 -1
- package/lib/MainTemplate.js +5 -1
- package/lib/Module.js +19 -10
- package/lib/ModuleGraph.js +6 -9
- package/lib/MultiCompiler.js +7 -17
- package/lib/MultiWatching.js +1 -1
- package/lib/NormalModule.js +135 -50
- 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 +813 -518
- package/lib/SourceMapDevToolPlugin.js +54 -104
- package/lib/TemplatedPathPlugin.js +16 -59
- package/lib/Watching.js +9 -0
- package/lib/WebpackOptionsApply.js +84 -91
- package/lib/asset/AssetBytesGenerator.js +7 -1
- package/lib/asset/AssetGenerator.js +50 -24
- package/lib/asset/AssetModule.js +3 -0
- package/lib/asset/AssetSourceGenerator.js +7 -1
- package/lib/asset/WebManifestParser.js +7 -5
- package/lib/buildChunkGraph.js +11 -15
- package/lib/cache/AddBuildDependenciesPlugin.js +33 -4
- package/lib/cache/IdleFileCachePlugin.js +2 -2
- package/lib/cache/MemoryCachePlugin.js +4 -4
- package/lib/cache/MemoryWithGcCachePlugin.js +7 -8
- package/lib/cache/PackFileCacheStrategy.js +17 -19
- package/lib/cache/getLazyHashedEtag.js +3 -5
- package/lib/config/browserslistTargetHandler.js +17 -4
- package/lib/config/defaults.js +138 -128
- package/lib/config/getClaimedAssetTypes.js +10 -11
- package/lib/config/normalization.js +82 -12
- package/lib/config/target.js +13 -4
- package/lib/container/ContainerReferencePlugin.js +6 -0
- package/lib/container/RemoteRuntimeModule.js +9 -0
- package/lib/container/declaredRemotes.js +39 -0
- package/lib/{ContextExclusionPlugin.js → context/ContextExclusionPlugin.js} +1 -1
- package/lib/{ContextModule.js → context/ContextModule.js} +54 -115
- package/lib/{ContextModuleFactory.js → context/ContextModuleFactory.js} +19 -21
- package/lib/{ContextReplacementPlugin.js → context/ContextReplacementPlugin.js} +4 -4
- package/lib/css/CssGenerator.js +27 -11
- 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 +162 -31
- package/lib/css/CssServerStylesRuntimeModule.js +9 -0
- package/lib/css/cssMinify.js +43 -32
- package/lib/css/data.js +3514 -869
- package/lib/css/syntax.js +6370 -1220
- package/lib/debug/ProfilingPlugin.js +7 -4
- package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -3
- package/lib/dependencies/AMDRuntimeModules.js +18 -0
- package/lib/dependencies/CommonJsExportRequireDependency.js +13 -12
- package/lib/dependencies/CommonJsExportsParserPlugin.js +12 -13
- package/lib/dependencies/CommonJsImportsParserPlugin.js +5 -5
- package/lib/dependencies/CommonJsPlugin.js +19 -3
- package/lib/dependencies/CommonJsRequireDependency.js +14 -5
- package/lib/dependencies/CommonJsSelfReferenceDependency.js +2 -4
- package/lib/dependencies/ContextDependency.js +1 -1
- package/lib/dependencies/ContextDependencyHelpers.js +3 -9
- package/lib/dependencies/ContextElementDependency.js +1 -1
- package/lib/dependencies/CssIcssExportDependency.js +13 -9
- package/lib/dependencies/CssIcssImportDependency.js +3 -6
- package/lib/dependencies/CssUrlDependency.js +3 -5
- package/lib/dependencies/HarmonyCompatibilityDependency.js +67 -22
- package/lib/dependencies/HarmonyDetectionParserPlugin.js +3 -4
- package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +10 -7
- package/lib/dependencies/HarmonyExportExpressionDependency.js +47 -33
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +74 -17
- package/lib/dependencies/HarmonyExportInitFragment.js +110 -23
- package/lib/dependencies/HarmonyExportSpecifierDependency.js +25 -58
- package/lib/dependencies/HarmonyImportBareSideEffectDependency.js +59 -0
- package/lib/dependencies/HarmonyImportDependency.js +6 -1
- package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +111 -17
- package/lib/dependencies/HarmonyImportSideEffectDependency.js +3 -4
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +40 -3
- package/lib/dependencies/HarmonyModulesPlugin.js +20 -0
- package/lib/dependencies/HtmlEntryDependency.js +124 -102
- package/lib/dependencies/HtmlInlineScriptDependency.js +3 -4
- package/lib/dependencies/HtmlInlineStyleDependency.js +3 -4
- package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +1 -1
- package/lib/dependencies/ImportMetaGlobHelpers.js +1 -1
- package/lib/dependencies/ImportMetaMainDependency.js +104 -0
- package/lib/dependencies/ImportMetaPlugin.js +67 -25
- package/lib/dependencies/ImportParserPlugin.js +1 -1
- package/lib/dependencies/LoaderPlugin.js +26 -1
- package/lib/dependencies/RequireContextDependencyParserPlugin.js +1 -1
- package/lib/dependencies/SystemRuntimeModule.js +9 -0
- package/lib/dependencies/URLContextDependency.js +1 -1
- package/lib/dependencies/URLDependency.js +6 -5
- package/lib/dependencies/WorkerAndWorkletPlugin.js +15 -21
- package/lib/dependencies/WorkerDependency.js +7 -7
- package/lib/dependencies/WorkletDependency.js +7 -11
- 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/HookWebpackError.js +3 -2
- 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/hmr/LazyCompilationPlugin.js +3 -5
- package/lib/html/HtmlGenerator.js +72 -87
- package/lib/html/HtmlModulesPlugin.js +418 -200
- package/lib/html/HtmlParser.js +110 -147
- package/lib/html/builtinEmbeddedRenderer.js +107 -0
- package/lib/html/data.js +142 -7
- package/lib/html/htmlMinify.js +92 -122
- package/lib/html/syntax.js +1618 -1391
- package/lib/ids/HashedModuleIdsPlugin.js +2 -1
- package/lib/index.js +49 -3
- package/lib/javascript/ChunkFormatHelpers.js +4 -3
- package/lib/javascript/JavascriptGenerator.js +8 -1
- package/lib/javascript/JavascriptModule.js +1 -0
- package/lib/javascript/JavascriptModulesPlugin.js +73 -72
- package/lib/javascript/JavascriptParser.js +1970 -900
- 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 +1500 -0
- package/lib/javascript/regexp.js +1762 -0
- package/lib/javascript/regexpData.js +51 -0
- package/lib/javascript/syntax.js +9061 -5262
- package/lib/json/JsonGenerator.js +7 -1
- package/lib/library/ModuleLibraryPlugin.js +171 -132
- package/lib/loaders/LoaderRunner.js +137 -9
- package/lib/node/NodeWatchFileSystem.js +3 -9
- package/lib/node/ReadFileChunkLoadingRuntimeModule.js +22 -0
- package/lib/node/RequireChunkLoadingRuntimeModule.js +22 -0
- package/lib/optimize/AggressiveMergingPlugin.js +3 -5
- package/lib/optimize/ConcatenatedModule.js +178 -120
- package/lib/optimize/ConstExportsPlugin.js +50 -39
- package/lib/optimize/FlagIncludedChunksPlugin.js +3 -11
- package/lib/optimize/InlineExports.js +20 -123
- package/lib/optimize/InnerGraphPlugin.js +7 -13
- package/lib/optimize/LimitChunkCountPlugin.js +5 -8
- package/lib/optimize/MangleExportsPlugin.js +13 -4
- package/lib/optimize/ModuleConcatenationPlugin.js +27 -5
- package/lib/optimize/RealContentHashPlugin.js +68 -9
- package/lib/optimize/SideEffectsFlagPlugin.js +24 -28
- package/lib/optimize/SplitChunksPlugin.js +2 -4
- package/lib/performance/AnalyzableBailoutsPlugin.js +115 -0
- package/lib/performance/BroadContextsPlugin.js +1 -1
- package/lib/performance/CacheEffectivenessPlugin.js +7 -7
- 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/SizeLimitsPlugin.js +2 -4
- 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 +8 -8
- 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 +18 -23
- package/lib/prefetch/ResourceHintRuntimeModule.js +9 -0
- package/lib/prefetch/StartupAssetHintRuntimeModule.js +16 -10
- package/lib/rules/RuleSetCompiler.js +211 -4
- package/lib/runtime/AsyncModuleRuntimeModule.js +98 -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 +12 -4
- 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 +11 -4
- package/lib/runtime/HasOwnPropertyRuntimeModule.js +9 -0
- package/lib/runtime/HelperRuntimeModule.js +10 -0
- package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +305 -224
- package/lib/runtime/NonceRuntimeModule.js +9 -0
- package/lib/runtime/OnChunksLoadedRuntimeModule.js +67 -20
- package/lib/runtime/PublicPathRuntimeModule.js +9 -0
- package/lib/runtime/RuntimeIdRuntimeModule.js +9 -0
- package/lib/runtime/SpecNamespaceObjectRuntimeModule.js +90 -0
- package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +9 -0
- package/lib/runtime/StartupEntrypointRuntimeModule.js +9 -0
- package/lib/runtime/SystemContextRuntimeModule.js +9 -0
- package/lib/runtime/ToBinaryRuntimeModule.js +9 -0
- package/lib/schemes/DataUriPlugin.js +3 -6
- package/lib/schemes/VirtualUrlPlugin.js +1 -1
- package/lib/serialization/BinaryMiddleware.js +9 -9
- package/lib/serialization/FileMiddleware.js +16 -16
- package/lib/serialization/ObjectMiddleware.js +168 -139
- 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 +6 -5
- package/lib/stats/DefaultStatsPrinterPlugin.js +3 -0
- package/lib/typescript/TypeScriptPlugin.js +2 -3
- package/lib/url/URLParserPlugin.js +6 -8
- package/lib/util/LocConverter.js +4 -7
- package/lib/util/SourceProcessor.js +91 -91
- package/lib/util/async.js +292 -0
- package/lib/util/buildDiagnostics.js +69 -0
- package/lib/util/chainedImports.js +3 -4
- package/lib/util/concatenate.js +4 -4
- package/lib/util/createHooksRegistry.js +1 -2
- package/lib/util/dataURL.js +2 -3
- package/lib/util/deterministicGrouping.js +8 -13
- package/lib/util/findGraphRoots.js +6 -13
- package/lib/util/fs.js +27 -1
- package/lib/util/globUtils.js +1 -1
- package/lib/util/handlerKeys.js +40 -0
- package/lib/util/hash/wasm-hash.js +3 -4
- package/lib/util/identifier.js +20 -0
- package/lib/util/internalSerializables.js +5 -1
- package/lib/util/registerExternalSerializer.js +6 -45
- package/lib/util/semver.js +5 -3
- package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +9 -0
- package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +9 -0
- package/lib/wasm-async/AsyncWebAssemblyGenerator.js +6 -1
- package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +5 -1
- package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +12 -4
- package/lib/wasm-sync/WebAssemblyGenerator.js +6 -1
- package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +5 -1
- package/lib/wasm-sync/WebAssemblyUtils.js +2 -4
- package/lib/web/JsonpChunkLoadingRuntimeModule.js +36 -0
- package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +19 -0
- package/package.json +55 -46
- 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 +1723 -604
- 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:
|
|
@@ -659,14 +745,14 @@ class RuntimeTemplate {
|
|
|
659
745
|
: undefined;
|
|
660
746
|
// A reassigned `__webpack_public_path__` cannot reach a baked literal, and `.p`
|
|
661
747
|
// belongs to a runtime, so only the runtimes it reaches keep the runtime form.
|
|
662
|
-
// `url-inline` is unaffected:
|
|
663
|
-
// the reassigned value at the call site rather than through the wrapper.
|
|
748
|
+
// `url-inline` is unaffected: it reads the value at the call site.
|
|
664
749
|
if (
|
|
665
750
|
form !== "url-inline" &&
|
|
666
751
|
APIPlugin.runtimeUsesPublicPathOverride(
|
|
667
752
|
this.compilation,
|
|
668
753
|
scoped ? chunkGraph : undefined,
|
|
669
|
-
placedModule
|
|
754
|
+
placedModule,
|
|
755
|
+
runtime
|
|
670
756
|
)
|
|
671
757
|
) {
|
|
672
758
|
return this._analyzableBailout(
|
|
@@ -678,57 +764,31 @@ class RuntimeTemplate {
|
|
|
678
764
|
|
|
679
765
|
if (form === "import") {
|
|
680
766
|
// 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
|
-
}
|
|
767
|
+
const outputReason = this._chunkImportOutputReason();
|
|
768
|
+
if (outputReason !== null) {
|
|
769
|
+
return this._analyzableBailout(module, outputReason, false);
|
|
710
770
|
}
|
|
771
|
+
// A worker loading its own chunks some other way needs no answer here: it gets
|
|
772
|
+
// a chunk loader of its own, and only the ESM one asks this.
|
|
711
773
|
return true;
|
|
712
774
|
}
|
|
713
775
|
|
|
714
|
-
// `url-inline` asks whether the file can be named at the call site
|
|
715
|
-
// its `.p + <file>` fallback spells that without `import.meta
|
|
716
|
-
// below does not rule it out
|
|
776
|
+
// `url-inline` asks only whether the file can be named at the call site, and
|
|
777
|
+
// its `.p + <file>` fallback spells that without `import.meta`, so the gate
|
|
778
|
+
// below does not rule it out.
|
|
779
|
+
|
|
717
780
|
// `environment.module` is deliberately not consulted: ESM output writes
|
|
718
|
-
// `import.meta` regardless
|
|
719
|
-
//
|
|
781
|
+
// `import.meta` regardless, so the url forms match what the rest of the
|
|
782
|
+
// bundle already assumes the target reads.
|
|
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,17 +1122,15 @@ 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
|
-
// A protocol-relative base names a host but no scheme, and the runtime reads
|
|
1029
|
-
// against the
|
|
1030
|
-
//
|
|
1031
|
-
// here. Nothing walks back to the output root first: the base replaces it.
|
|
1127
|
+
// A protocol-relative base names a host but no scheme, and the runtime reads
|
|
1128
|
+
// it against the very url this literal resolves against, so it may stay that
|
|
1129
|
+
// way. Nothing walks back to the output root: the base replaces it.
|
|
1032
1130
|
if (base.startsWith("//")) {
|
|
1033
1131
|
return this._specifierOf(
|
|
1034
1132
|
[["literal", base], ...rootedParts(parts), ["literal", filename]],
|
|
1035
|
-
chunks
|
|
1036
|
-
module
|
|
1133
|
+
chunks
|
|
1037
1134
|
);
|
|
1038
1135
|
}
|
|
1039
1136
|
if (!isAbsoluteBaseUri(base)) {
|
|
@@ -1065,13 +1162,14 @@ class RuntimeTemplate {
|
|
|
1065
1162
|
);
|
|
1066
1163
|
}
|
|
1067
1164
|
if (text !== null) return toJsStringLiteral(resolved.href);
|
|
1068
|
-
if (!this._canDeferOrBail(chunks, module)) return null;
|
|
1069
1165
|
return toJsStringLiteral(
|
|
1070
|
-
this._reserveAnalyzableSpecifier(
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1166
|
+
this._reserveAnalyzableSpecifier(
|
|
1167
|
+
this._markedForRepair(this._needsRepair(chunks), [
|
|
1168
|
+
["base", base],
|
|
1169
|
+
...parts,
|
|
1170
|
+
["literal", filename]
|
|
1171
|
+
])
|
|
1172
|
+
)
|
|
1075
1173
|
);
|
|
1076
1174
|
}
|
|
1077
1175
|
|
|
@@ -1093,10 +1191,9 @@ class RuntimeTemplate {
|
|
|
1093
1191
|
let base;
|
|
1094
1192
|
let found = false;
|
|
1095
1193
|
for (const chunk of this.compilation.chunks) {
|
|
1096
|
-
//
|
|
1097
|
-
//
|
|
1098
|
-
//
|
|
1099
|
-
// chunk already share the base it sets, however their descriptors differ.
|
|
1194
|
+
// A literal must agree with the one value `BaseUriRuntimeModule` writes, and
|
|
1195
|
+
// that reads the entry options off the chunk it is emitted into, so only a
|
|
1196
|
+
// chunk carrying a runtime has a say.
|
|
1100
1197
|
if (!chunk.hasRuntime()) continue;
|
|
1101
1198
|
const entryOptions = chunk.getEntryOptions();
|
|
1102
1199
|
// An entry this code cannot run under has no say in the base it resolves to.
|
|
@@ -1384,14 +1481,13 @@ class RuntimeTemplate {
|
|
|
1384
1481
|
}
|
|
1385
1482
|
if (!this.supportTemplateLiteral()) return this._es5Concatenation(args);
|
|
1386
1483
|
|
|
1387
|
-
// cost comparison between template literal and concatenation
|
|
1388
|
-
//
|
|
1389
|
-
//
|
|
1390
|
-
//
|
|
1391
|
-
//
|
|
1392
|
-
//
|
|
1393
|
-
//
|
|
1394
|
-
// e. g. `x${a}x${b}x${c}x` (3*3 = 9) is shorter than "x"+a+"x"+b+"x"+c+"x" (4+4+4 = 12)
|
|
1484
|
+
// WHY: cost comparison between a template literal and a concatenation, both
|
|
1485
|
+
// needing equal surroundings (`xxx` against "xxx"). A template literal costs
|
|
1486
|
+
// a constant 3 chars per expression; an es5 concatenation costs 3 + n chars
|
|
1487
|
+
// for n expressions in a row, and reduces by 3 where it ends with an
|
|
1488
|
+
// expression or starts with a single one. So `${a}${b}${c}` (3*3 = 9) is
|
|
1489
|
+
// longer than ""+a+b+c ((3+3)-3 = 3), while `x${a}x${b}x${c}x` (3*3 = 9) is
|
|
1490
|
+
// shorter than "x"+a+"x"+b+"x"+c+"x" (4+4+4 = 12).
|
|
1395
1491
|
|
|
1396
1492
|
let templateCost = 0;
|
|
1397
1493
|
let concatenationCost = 0;
|
|
@@ -1868,14 +1964,21 @@ class RuntimeTemplate {
|
|
|
1868
1964
|
});
|
|
1869
1965
|
const exportsType = module.getExportsType(chunkGraph.moduleGraph, strict);
|
|
1870
1966
|
switch (exportsType) {
|
|
1871
|
-
case "namespace":
|
|
1872
|
-
|
|
1967
|
+
case "namespace": {
|
|
1968
|
+
const raw = this.moduleRaw({
|
|
1873
1969
|
module,
|
|
1874
1970
|
chunkGraph,
|
|
1875
1971
|
request,
|
|
1876
1972
|
weak,
|
|
1877
1973
|
runtimeRequirements
|
|
1878
1974
|
});
|
|
1975
|
+
|
|
1976
|
+
if (!usesSpecNamespaceObject(module)) return raw;
|
|
1977
|
+
|
|
1978
|
+
runtimeRequirements.add(RuntimeGlobals.specNamespaceObject);
|
|
1979
|
+
|
|
1980
|
+
return `${RuntimeGlobals.specNamespaceObject}(${raw})`;
|
|
1981
|
+
}
|
|
1879
1982
|
case "default-with-named":
|
|
1880
1983
|
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
|
1881
1984
|
return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 3)`;
|
|
@@ -1984,6 +2087,21 @@ class RuntimeTemplate {
|
|
|
1984
2087
|
|
|
1985
2088
|
let mode = getMakeDeferredNamespaceModeFromExportsType(exportsType);
|
|
1986
2089
|
if (mode) mode = `${mode} | 16`;
|
|
2090
|
+
// The spec's namespace keys are the sorted exports, so hand them over
|
|
2091
|
+
// when they are fully known; otherwise the runtime stays permissive.
|
|
2092
|
+
const deferredExportNames = getKnownExportNames(
|
|
2093
|
+
chunkGraph.moduleGraph,
|
|
2094
|
+
module,
|
|
2095
|
+
exportsType
|
|
2096
|
+
);
|
|
2097
|
+
runtimeRequirements.add(
|
|
2098
|
+
deferredExportNames
|
|
2099
|
+
? RuntimeGlobals.hasSealedDeferredNamespace
|
|
2100
|
+
: RuntimeGlobals.hasSynthesizedDeferredNamespace
|
|
2101
|
+
);
|
|
2102
|
+
mode += deferredExportNames
|
|
2103
|
+
? `, ${JSON.stringify(deferredExportNames)}`
|
|
2104
|
+
: "";
|
|
1987
2105
|
|
|
1988
2106
|
const asyncDeps = Array.from(
|
|
1989
2107
|
getOutgoingAsyncModules(chunkGraph.moduleGraph, module),
|
|
@@ -2027,15 +2145,22 @@ class RuntimeTemplate {
|
|
|
2027
2145
|
} else {
|
|
2028
2146
|
let fakeType = 16;
|
|
2029
2147
|
switch (exportsType) {
|
|
2030
|
-
case "namespace":
|
|
2031
|
-
|
|
2032
|
-
|
|
2148
|
+
case "namespace": {
|
|
2149
|
+
const specNamespace = usesSpecNamespaceObject(module);
|
|
2150
|
+
const asyncModule = chunkGraph.moduleGraph.isAsync(module);
|
|
2151
|
+
if (header || (specNamespace && !asyncModule)) {
|
|
2152
|
+
let rawModule = this.moduleRaw({
|
|
2033
2153
|
module,
|
|
2034
2154
|
chunkGraph,
|
|
2035
2155
|
request,
|
|
2036
2156
|
weak,
|
|
2037
2157
|
runtimeRequirements
|
|
2038
2158
|
});
|
|
2159
|
+
if (specNamespace && !asyncModule) {
|
|
2160
|
+
runtimeRequirements.add(RuntimeGlobals.specNamespaceObject);
|
|
2161
|
+
// Wrap before promise resolution assimilates an exported `then`.
|
|
2162
|
+
rawModule = `${RuntimeGlobals.specNamespaceObject}(${rawModule})`;
|
|
2163
|
+
}
|
|
2039
2164
|
appending = `.then(${this.basicFunction(
|
|
2040
2165
|
"",
|
|
2041
2166
|
`${header}return ${rawModule};`
|
|
@@ -2047,7 +2172,14 @@ class RuntimeTemplate {
|
|
|
2047
2172
|
`${comment}${idExpr}`
|
|
2048
2173
|
)})`;
|
|
2049
2174
|
}
|
|
2175
|
+
|
|
2176
|
+
if (specNamespace && asyncModule) {
|
|
2177
|
+
runtimeRequirements.add(RuntimeGlobals.specNamespaceObject);
|
|
2178
|
+
appending += `.then(${RuntimeGlobals.specNamespaceObject})`;
|
|
2179
|
+
}
|
|
2180
|
+
|
|
2050
2181
|
break;
|
|
2182
|
+
}
|
|
2051
2183
|
case "dynamic":
|
|
2052
2184
|
fakeType |= 4;
|
|
2053
2185
|
/* fall through */
|
|
@@ -2101,6 +2233,15 @@ class RuntimeTemplate {
|
|
|
2101
2233
|
)})`;
|
|
2102
2234
|
}
|
|
2103
2235
|
}
|
|
2236
|
+
if (synthesizesSpecNamespaceObject(originModule)) {
|
|
2237
|
+
runtimeRequirements.add(RuntimeGlobals.specNamespaceObject);
|
|
2238
|
+
runtimeRequirements.add(RuntimeGlobals.moduleCache);
|
|
2239
|
+
const owner = synthesizedNamespaceOwner(moduleId, fakeType);
|
|
2240
|
+
appending += `.then(${this.returningFunction(
|
|
2241
|
+
`${RuntimeGlobals.specNamespaceObject}(m${owner})`,
|
|
2242
|
+
"m"
|
|
2243
|
+
)})`;
|
|
2244
|
+
}
|
|
2104
2245
|
break;
|
|
2105
2246
|
}
|
|
2106
2247
|
}
|
|
@@ -2209,10 +2350,9 @@ class RuntimeTemplate {
|
|
|
2209
2350
|
request,
|
|
2210
2351
|
weak
|
|
2211
2352
|
});
|
|
2212
|
-
//
|
|
2213
|
-
//
|
|
2214
|
-
//
|
|
2215
|
-
// block-scoped (`let`/`const`).
|
|
2353
|
+
// A harmony import may sit inside a runtime-condition `if` block yet be
|
|
2354
|
+
// referenced outside it, so it stays function-scoped with `var` rather than
|
|
2355
|
+
// block-scoped.
|
|
2216
2356
|
const optDeclaration = update ? "" : "var ";
|
|
2217
2357
|
|
|
2218
2358
|
const exportsType = module.getExportsType(
|
|
@@ -2351,10 +2491,8 @@ class RuntimeTemplate {
|
|
|
2351
2491
|
}
|
|
2352
2492
|
// accessing the .default property is same thing as `require()` the module.
|
|
2353
2493
|
|
|
2354
|
-
//
|
|
2355
|
-
//
|
|
2356
|
-
// is translated to
|
|
2357
|
-
// var mod = require("cjs"); mod.x;
|
|
2494
|
+
// So `import mod from "cjs"; mod.default.x` translates to
|
|
2495
|
+
// `var mod = require("cjs"); mod.x`.
|
|
2358
2496
|
switch (exportsType) {
|
|
2359
2497
|
case "dynamic":
|
|
2360
2498
|
if (isCall) {
|
|
@@ -2394,10 +2532,9 @@ class RuntimeTemplate {
|
|
|
2394
2532
|
exportsType === "default-only" ||
|
|
2395
2533
|
exportsType === "default-with-named"
|
|
2396
2534
|
) {
|
|
2397
|
-
//
|
|
2398
|
-
//
|
|
2399
|
-
//
|
|
2400
|
-
// we will need to createFakeNamespaceObject that simulates ES Module namespace object
|
|
2535
|
+
// `exportName.length` is 0, so the namespace object is used in an unknown
|
|
2536
|
+
// way — `import * as ns from "cjs"; console.log(ns)` — and needs
|
|
2537
|
+
// `createFakeNamespaceObject` to simulate an ES module namespace.
|
|
2401
2538
|
runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
|
|
2402
2539
|
initFragments.push(
|
|
2403
2540
|
new InitFragment(
|
|
@@ -2407,16 +2544,38 @@ class RuntimeTemplate {
|
|
|
2407
2544
|
`${importVar}_namespace_cache`
|
|
2408
2545
|
)
|
|
2409
2546
|
);
|
|
2547
|
+
const fakeMode = exportsType === "default-only" ? 0 : 2;
|
|
2548
|
+
const fakeArguments = fakeMode === 0 ? "" : ", 2";
|
|
2549
|
+
let fakeNamespace = `${RuntimeGlobals.createFakeNamespaceObject}(${importVar}${fakeArguments})`;
|
|
2550
|
+
if (synthesizesSpecNamespaceObject(originModule)) {
|
|
2551
|
+
runtimeRequirements.add(RuntimeGlobals.specNamespaceObject);
|
|
2552
|
+
runtimeRequirements.add(RuntimeGlobals.moduleCache);
|
|
2553
|
+
const owner = synthesizedNamespaceOwner(
|
|
2554
|
+
chunkGraph.getModuleId(module),
|
|
2555
|
+
fakeMode
|
|
2556
|
+
);
|
|
2557
|
+
fakeNamespace = `${RuntimeGlobals.specNamespaceObject}(${fakeNamespace}${owner})`;
|
|
2558
|
+
}
|
|
2410
2559
|
return `/*#__PURE__*/ ${
|
|
2411
2560
|
asiSafe ? "" : asiSafe === false ? ";" : "Object"
|
|
2412
|
-
}(${importVar}_namespace_cache || (${importVar}_namespace_cache = ${
|
|
2413
|
-
RuntimeGlobals.createFakeNamespaceObject
|
|
2414
|
-
}(${importVar}${exportsType === "default-only" ? "" : ", 2"})))`;
|
|
2561
|
+
}(${importVar}_namespace_cache || (${importVar}_namespace_cache = ${fakeNamespace}))`;
|
|
2415
2562
|
}
|
|
2416
2563
|
}
|
|
2417
2564
|
|
|
2418
2565
|
if (exportName.length > 0) {
|
|
2419
2566
|
const exportsInfo = moduleGraph.getExportsInfo(module);
|
|
2567
|
+
// A name the module does not export is the namespace's to answer — reading
|
|
2568
|
+
// it is undefined and writing it fails — not the exports object's.
|
|
2569
|
+
if (
|
|
2570
|
+
!isModuleDeferred &&
|
|
2571
|
+
usesSpecNamespaceObject(module) &&
|
|
2572
|
+
exportsInfo.isExportProvided(exportName) === false
|
|
2573
|
+
) {
|
|
2574
|
+
runtimeRequirements.add(RuntimeGlobals.specNamespaceObject);
|
|
2575
|
+
const ns = `${RuntimeGlobals.specNamespaceObject}(${importVar})`;
|
|
2576
|
+
|
|
2577
|
+
return `${ns}${propertyAccess(exportName)}`;
|
|
2578
|
+
}
|
|
2420
2579
|
// in some case the exported item is renamed (get this by getUsedName). for example,
|
|
2421
2580
|
// x.default might be emitted as x.Z (default is renamed to Z)
|
|
2422
2581
|
const used = exportsInfo.getUsedName(exportName, runtime);
|
|
@@ -2461,9 +2620,19 @@ class RuntimeTemplate {
|
|
|
2461
2620
|
runtimeRequirements.add(RuntimeGlobals.makeDeferredNamespaceObject);
|
|
2462
2621
|
const id = chunkGraph.getModuleId(module);
|
|
2463
2622
|
const type = getMakeDeferredNamespaceModeFromExportsType(exportsType);
|
|
2464
|
-
const
|
|
2465
|
-
|
|
2466
|
-
|
|
2623
|
+
const names = getKnownExportNames(
|
|
2624
|
+
chunkGraph.moduleGraph,
|
|
2625
|
+
module,
|
|
2626
|
+
exportsType
|
|
2627
|
+
);
|
|
2628
|
+
runtimeRequirements.add(
|
|
2629
|
+
names
|
|
2630
|
+
? RuntimeGlobals.hasSealedDeferredNamespace
|
|
2631
|
+
: RuntimeGlobals.hasSynthesizedDeferredNamespace
|
|
2632
|
+
);
|
|
2633
|
+
const init = `${RuntimeGlobals.makeDeferredNamespaceObject}(${JSON.stringify(
|
|
2634
|
+
id
|
|
2635
|
+
)}, ${type}${names ? `, ${JSON.stringify(names)}` : ""})`;
|
|
2467
2636
|
|
|
2468
2637
|
return `/*#__PURE__*/ ${
|
|
2469
2638
|
asiSafe ? "" : asiSafe === false ? ";" : "Object"
|
|
@@ -2490,6 +2659,16 @@ class RuntimeTemplate {
|
|
|
2490
2659
|
// if we hit here, the importVar is either
|
|
2491
2660
|
// - already a ES module namespace object
|
|
2492
2661
|
// - or imported by a way that does not need interop.
|
|
2662
|
+
if (
|
|
2663
|
+
exportsType === "namespace" &&
|
|
2664
|
+
exportName.length === 0 &&
|
|
2665
|
+
usesSpecNamespaceObject(module)
|
|
2666
|
+
) {
|
|
2667
|
+
runtimeRequirements.add(RuntimeGlobals.specNamespaceObject);
|
|
2668
|
+
|
|
2669
|
+
return `${RuntimeGlobals.specNamespaceObject}(${importVar})`;
|
|
2670
|
+
}
|
|
2671
|
+
|
|
2493
2672
|
return importVar;
|
|
2494
2673
|
}
|
|
2495
2674
|
|
|
@@ -2570,7 +2749,7 @@ class RuntimeTemplate {
|
|
|
2570
2749
|
* @param {string} options.message the message
|
|
2571
2750
|
* @param {ChunkGraph} options.chunkGraph the chunk graph
|
|
2572
2751
|
* @param {RuntimeRequirements} options.runtimeRequirements if set, will be filled with runtime requirements
|
|
2573
|
-
* @param {Module=} options.originModule the module the `import()` is emitted into
|
|
2752
|
+
* @param {Module=} options.originModule the module the `import()` is emitted into, to report against
|
|
2574
2753
|
* @returns {string} expression
|
|
2575
2754
|
*/
|
|
2576
2755
|
blockPromise({
|
|
@@ -2600,156 +2779,32 @@ class RuntimeTemplate {
|
|
|
2600
2779
|
message,
|
|
2601
2780
|
chunkName: block.chunkName
|
|
2602
2781
|
});
|
|
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;
|
|
2782
|
+
// An output that cannot use a native `import()` gets no ESM chunk loader to ask,
|
|
2783
|
+
// so the reason is recorded here, where any build generates its imports.
|
|
2784
|
+
if (this.outputOptions.module && originModule !== undefined) {
|
|
2785
|
+
const outputReason = this._chunkImportOutputReason();
|
|
2786
|
+
if (outputReason !== null) {
|
|
2787
|
+
this._analyzableBailout(originModule, outputReason, false);
|
|
2675
2788
|
}
|
|
2676
2789
|
}
|
|
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;
|
|
2790
|
+
const fetchPriority = chunkGroup.options.fetchPriority;
|
|
2791
|
+
const priorityArg = fetchPriority
|
|
2792
|
+
? `, ${JSON.stringify(fetchPriority)}`
|
|
2793
|
+
: "";
|
|
2794
|
+
if (chunks.length === 0) return `Promise.resolve(${comment.trim()})`;
|
|
2795
|
+
runtimeRequirements.add(RuntimeGlobals.ensureChunk);
|
|
2796
|
+
if (fetchPriority) {
|
|
2797
|
+
runtimeRequirements.add(RuntimeGlobals.hasFetchPriority);
|
|
2706
2798
|
}
|
|
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
|
-
);
|
|
2799
|
+
if (chunks.length === 1) {
|
|
2800
|
+
const chunkId = JSON.stringify(chunks[0].id);
|
|
2801
|
+
return `${RuntimeGlobals.ensureChunk}(${comment}${chunkId}${priorityArg})`;
|
|
2716
2802
|
}
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
undefined,
|
|
2721
|
-
chunk,
|
|
2722
|
-
originModule,
|
|
2723
|
-
chunkGraph
|
|
2803
|
+
const items = chunks.map(
|
|
2804
|
+
(chunk) =>
|
|
2805
|
+
`${RuntimeGlobals.ensureChunk}(${JSON.stringify(chunk.id)}${priorityArg})`
|
|
2724
2806
|
);
|
|
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})`)})`;
|
|
2807
|
+
return `Promise.all(${comment.trim()}[${items.join(", ")}])`;
|
|
2753
2808
|
}
|
|
2754
2809
|
|
|
2755
2810
|
/**
|
|
@@ -2785,6 +2840,17 @@ class RuntimeTemplate {
|
|
|
2785
2840
|
const late = this._settlesLate(chunk);
|
|
2786
2841
|
if (late !== this._settlesLate(target)) return !late;
|
|
2787
2842
|
}
|
|
2843
|
+
return this._hashRoundBefore(chunk, target);
|
|
2844
|
+
}
|
|
2845
|
+
|
|
2846
|
+
/**
|
|
2847
|
+
* Whether the four rounds alone settle `chunk` before `target`, leaving out what the
|
|
2848
|
+
* full-hash marks move: the order a runtime module generated in its chunk's round sees.
|
|
2849
|
+
* @param {Chunk} chunk the chunk whose hash would be read
|
|
2850
|
+
* @param {Chunk} target the chunk reading it
|
|
2851
|
+
* @returns {boolean} true when the hash exists by the time the target is hashed
|
|
2852
|
+
*/
|
|
2853
|
+
_hashRoundBefore(chunk, target) {
|
|
2788
2854
|
const chunkGraph = /** @type {ChunkGraph} */ (this.compilation.chunkGraph);
|
|
2789
2855
|
const round = hashRound(chunk, chunkGraph);
|
|
2790
2856
|
const targetRound = hashRound(target, chunkGraph);
|
|
@@ -2807,6 +2873,42 @@ class RuntimeTemplate {
|
|
|
2807
2873
|
);
|
|
2808
2874
|
}
|
|
2809
2875
|
|
|
2876
|
+
/**
|
|
2877
|
+
* Whether a `[chunkhash]`/`[contenthash]` name is settled before every chunk it is
|
|
2878
|
+
* written into, so a runtime module generated in its chunk's round can spell it.
|
|
2879
|
+
* @param {Chunk} chunk the chunk named
|
|
2880
|
+
* @param {string} template what names it
|
|
2881
|
+
* @param {Iterable<Chunk>} targets the chunks the name is written into
|
|
2882
|
+
* @returns {boolean} true when the hashes it reads exist by then
|
|
2883
|
+
*/
|
|
2884
|
+
_hashedNameSettledBefore(chunk, template, targets) {
|
|
2885
|
+
const kinds = getTemplatedPathPlugin().getPresentKinds(template);
|
|
2886
|
+
// The compilation hash exists in no round a chunk is hashed in.
|
|
2887
|
+
if (kinds.has("fullhash") || kinds.has("hash")) return false;
|
|
2888
|
+
for (const target of targets) {
|
|
2889
|
+
if (!this._hashRoundBefore(chunk, target)) return false;
|
|
2890
|
+
}
|
|
2891
|
+
return true;
|
|
2892
|
+
}
|
|
2893
|
+
|
|
2894
|
+
/**
|
|
2895
|
+
* Whether the hashes a name reads are on the chunk now, which they are only once its
|
|
2896
|
+
* round of `createHash` has run — never while modules are being generated.
|
|
2897
|
+
* @param {Chunk} chunk the chunk named
|
|
2898
|
+
* @param {string} template what names it
|
|
2899
|
+
* @param {string} sourceType which asset of the chunk it names
|
|
2900
|
+
* @returns {boolean} true when the name can be resolved here
|
|
2901
|
+
*/
|
|
2902
|
+
_hashedNamePresent(chunk, template, sourceType) {
|
|
2903
|
+
const kinds = getTemplatedPathPlugin().getPresentKinds(template);
|
|
2904
|
+
return (
|
|
2905
|
+
!kinds.has("fullhash") &&
|
|
2906
|
+
!kinds.has("hash") &&
|
|
2907
|
+
(!kinds.has("chunkhash") || chunk.hash !== undefined) &&
|
|
2908
|
+
(!kinds.has("contenthash") || chunk.contentHash[sourceType] !== undefined)
|
|
2909
|
+
);
|
|
2910
|
+
}
|
|
2911
|
+
|
|
2810
2912
|
/**
|
|
2811
2913
|
* Whether `createHash` settles this chunk's hash in the round that runs after the
|
|
2812
2914
|
* compilation hash rather than in one of the four before it. Asked of the chunk
|
|
@@ -3068,35 +3170,6 @@ class RuntimeTemplate {
|
|
|
3068
3170
|
this._chunksByIdForFold = undefined;
|
|
3069
3171
|
}
|
|
3070
3172
|
|
|
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
3173
|
/**
|
|
3101
3174
|
* The chunks a reference emitted into `module` is written into — the assets a
|
|
3102
3175
|
* stand-in of ours would land in, and so the only ones a deferred fill could go
|
|
@@ -3212,7 +3285,7 @@ class RuntimeTemplate {
|
|
|
3212
3285
|
* The `../` path from a chunk's own asset back to the output root. Hashes are
|
|
3213
3286
|
* neutralized first: a runtime module is generated once to be hashed, before any
|
|
3214
3287
|
* hash exists, so resolving one there throws — and `RuntimeModule.updateHash`
|
|
3215
|
-
*
|
|
3288
|
+
* lets that throw fail the build rather than hashing it.
|
|
3216
3289
|
* @param {Chunk} chunk the chunk whose asset holds the reference
|
|
3217
3290
|
* @param {boolean} enforceRelative whether the answer keeps a leading `./`
|
|
3218
3291
|
* @returns {string} the path back to the output root
|
|
@@ -3243,7 +3316,10 @@ class RuntimeTemplate {
|
|
|
3243
3316
|
* @returns {Placement} where a literal in it is read from
|
|
3244
3317
|
*/
|
|
3245
3318
|
_modulePlacement(module, chunkGraph) {
|
|
3246
|
-
return this._placementOf(
|
|
3319
|
+
return this._placementOf(
|
|
3320
|
+
this._moduleChunks(module, chunkGraph),
|
|
3321
|
+
isHotModule(module)
|
|
3322
|
+
);
|
|
3247
3323
|
}
|
|
3248
3324
|
|
|
3249
3325
|
/**
|
|
@@ -3262,11 +3338,12 @@ class RuntimeTemplate {
|
|
|
3262
3338
|
|
|
3263
3339
|
/**
|
|
3264
3340
|
* The one answer every chunk in `chunks` agrees on, with either half `null` where
|
|
3265
|
-
* they do not.
|
|
3341
|
+
* they do not — under HMR the update chunk, which re-runs the module, has a say too.
|
|
3266
3342
|
* @param {Iterable<Chunk>} chunks the chunks a literal is written into
|
|
3343
|
+
* @param {boolean=} hot whether a hot update can re-run what is written
|
|
3267
3344
|
* @returns {Placement} where a literal in them is read from
|
|
3268
3345
|
*/
|
|
3269
|
-
_placementOf(chunks) {
|
|
3346
|
+
_placementOf(chunks, hot = false) {
|
|
3270
3347
|
/** @type {Placement | undefined} */
|
|
3271
3348
|
let first;
|
|
3272
3349
|
/** @type {string | null} */
|
|
@@ -3275,13 +3352,17 @@ class RuntimeTemplate {
|
|
|
3275
3352
|
let loaded = null;
|
|
3276
3353
|
for (const chunk of chunks) {
|
|
3277
3354
|
const own = this._chunkPlacement(chunk);
|
|
3355
|
+
const ownUndo =
|
|
3356
|
+
hot && own.undo !== null && own.undo !== this._hotUpdateUndo(chunk)
|
|
3357
|
+
? null
|
|
3358
|
+
: own.undo;
|
|
3278
3359
|
if (first === undefined) {
|
|
3279
3360
|
first = own;
|
|
3280
|
-
undo =
|
|
3361
|
+
undo = ownUndo;
|
|
3281
3362
|
loaded = own.loaded;
|
|
3282
3363
|
continue;
|
|
3283
3364
|
}
|
|
3284
|
-
if (undo !==
|
|
3365
|
+
if (undo !== ownUndo) undo = null;
|
|
3285
3366
|
if (loaded !== own.loaded) loaded = null;
|
|
3286
3367
|
}
|
|
3287
3368
|
if (first === undefined) return NO_PLACEMENT;
|
|
@@ -3301,16 +3382,9 @@ class RuntimeTemplate {
|
|
|
3301
3382
|
* @param {Chunk} chunk the worker's entry chunk
|
|
3302
3383
|
* @param {Module} module the module the reference is emitted into
|
|
3303
3384
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3304
|
-
* @param {RuntimeRequirements} runtimeRequirements what the consuming chunk needs
|
|
3305
3385
|
* @returns {string | null} a quoted literal, or `null` to fall back
|
|
3306
3386
|
*/
|
|
3307
|
-
getAnalyzableWorkerUrl(
|
|
3308
|
-
overridePublicPath,
|
|
3309
|
-
chunk,
|
|
3310
|
-
module,
|
|
3311
|
-
chunkGraph,
|
|
3312
|
-
runtimeRequirements
|
|
3313
|
-
) {
|
|
3387
|
+
getAnalyzableWorkerUrl(overridePublicPath, chunk, module, chunkGraph) {
|
|
3314
3388
|
// Without an id nothing can name the chunk in a stand-in.
|
|
3315
3389
|
if (
|
|
3316
3390
|
chunk.id === null ||
|
|
@@ -3322,8 +3396,7 @@ class RuntimeTemplate {
|
|
|
3322
3396
|
overridePublicPath,
|
|
3323
3397
|
chunk,
|
|
3324
3398
|
module,
|
|
3325
|
-
chunkGraph
|
|
3326
|
-
runtimeRequirements
|
|
3399
|
+
chunkGraph
|
|
3327
3400
|
);
|
|
3328
3401
|
}
|
|
3329
3402
|
|
|
@@ -3336,12 +3409,11 @@ class RuntimeTemplate {
|
|
|
3336
3409
|
* @param {Module | undefined} consumingModule the module the reference is emitted
|
|
3337
3410
|
* into, or `undefined` when `consumingChunks` names where it goes instead
|
|
3338
3411
|
* @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
3412
|
* @param {Chunk[]=} consumingChunks the chunks the reference is written into, where
|
|
3342
3413
|
* they are known without a module to read them from
|
|
3343
3414
|
* @param {string=} sourceType which half of the chunk is named — its javascript by
|
|
3344
3415
|
* default, or its stylesheet
|
|
3416
|
+
* @param {boolean=} hot whether a hot update can re-run what is written
|
|
3345
3417
|
* @returns {string | null} a JS string literal or expression, or `null` to fall back to the runtime form
|
|
3346
3418
|
*/
|
|
3347
3419
|
_getAnalyzableChunkSpecifier(
|
|
@@ -3349,117 +3421,113 @@ class RuntimeTemplate {
|
|
|
3349
3421
|
chunk,
|
|
3350
3422
|
consumingModule,
|
|
3351
3423
|
chunkGraph,
|
|
3352
|
-
runtimeRequirements,
|
|
3353
3424
|
consumingChunks,
|
|
3354
|
-
sourceType = JAVASCRIPT_TYPE
|
|
3425
|
+
sourceType = JAVASCRIPT_TYPE,
|
|
3426
|
+
hot = isHotModule(consumingModule)
|
|
3355
3427
|
) {
|
|
3356
3428
|
const { compilation } = this;
|
|
3357
3429
|
const { outputOptions } = compilation;
|
|
3358
3430
|
const naming = CHUNK_ASSET_NAMING.get(sourceType);
|
|
3359
3431
|
// Nothing here names this type's asset, so nothing can spell where it will be.
|
|
3360
3432
|
if (naming === undefined) return null;
|
|
3361
|
-
const template = this.
|
|
3362
|
-
naming.template(chunk, outputOptions),
|
|
3363
|
-
chunk,
|
|
3364
|
-
sourceType
|
|
3365
|
-
);
|
|
3433
|
+
const template = this._chunkAssetTemplate(chunk, sourceType);
|
|
3366
3434
|
if (template === null) return null;
|
|
3367
3435
|
// A hashed name is settled long after this code is generated, so a stand-in is
|
|
3368
3436
|
// emitted and filled in once the hash exists.
|
|
3369
3437
|
const deferred = template === undefined || HASH_IN_FILENAME.test(template);
|
|
3370
3438
|
// An id names the chunk in the stand-in, and one nothing could resolve would
|
|
3371
|
-
// reach the bundle verbatim. The whole name is re-resolved later
|
|
3372
|
-
//
|
|
3373
|
-
// One of the two always names where the reference goes.
|
|
3439
|
+
// reach the bundle verbatim. The whole name is re-resolved later, so any hash
|
|
3440
|
+
// spelling is fine here; one of the two always names the destination.
|
|
3374
3441
|
const chunks =
|
|
3375
3442
|
consumingChunks ||
|
|
3376
3443
|
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
|
-
});
|
|
3444
|
+
// An id names the chunk in the stand-in; `blockPromise` drops an id-less chunk
|
|
3445
|
+
// before asking, so the guard only keeps `null` out of a name.
|
|
3446
|
+
if (chunk.id === null) return null;
|
|
3447
|
+
// A runtime module is generated in its chunk's round of `createHash`, where a
|
|
3448
|
+
// hashed name settled earlier exists: spelled, so a hot update carries the new one.
|
|
3449
|
+
const settled =
|
|
3450
|
+
deferred &&
|
|
3451
|
+
template !== undefined &&
|
|
3452
|
+
this._hashedNamePresent(chunk, template, sourceType) &&
|
|
3453
|
+
this._namesBeforeAll(chunk, chunks);
|
|
3454
|
+
const canReserve = this._canDeferAnalyzableName(chunks);
|
|
3455
|
+
// A content-named consumer folds this name into its hash when it settles first;
|
|
3456
|
+
// what the fold cannot cover is repaired instead.
|
|
3457
|
+
const canFold = !canReserve && this._namesBeforeAll(chunk, chunks);
|
|
3458
|
+
const filename =
|
|
3459
|
+
deferred && !settled
|
|
3460
|
+
? ""
|
|
3461
|
+
: compilation.getPath(/** @type {string} */ (template), {
|
|
3462
|
+
chunk,
|
|
3463
|
+
// Matches what names the asset, or a placeholder resolved here would
|
|
3464
|
+
// not be the one on disk.
|
|
3465
|
+
runtime: chunk.runtime,
|
|
3466
|
+
contentHashType: sourceType
|
|
3467
|
+
});
|
|
3411
3468
|
/**
|
|
3412
3469
|
* @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
|
|
3470
|
+
* @returns {string} the specifier already quoted
|
|
3415
3471
|
*/
|
|
3416
3472
|
const specifier = (prefix) => {
|
|
3417
|
-
if (!deferred) {
|
|
3473
|
+
if (!deferred || settled) {
|
|
3418
3474
|
const text = literalText(prefix);
|
|
3419
3475
|
if (text !== null) return toJsStringLiteral(text + filename);
|
|
3420
3476
|
}
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
}
|
|
3477
|
+
const repair =
|
|
3478
|
+
!canReserve && !(canFold && this._foldsWholeName(prefix, chunks));
|
|
3424
3479
|
return toJsStringLiteral(
|
|
3425
|
-
this._reserveAnalyzableSpecifier(
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3480
|
+
this._reserveAnalyzableSpecifier(
|
|
3481
|
+
this._markedForRepair(repair, [
|
|
3482
|
+
...prefix,
|
|
3483
|
+
// A settled name is carried as text: the fill would spell the same,
|
|
3484
|
+
// but only text of its own moves the runtime module's hash.
|
|
3485
|
+
settled
|
|
3486
|
+
? ["literal", filename]
|
|
3487
|
+
: [naming.standIn, /** @type {ChunkId} */ (chunk.id)]
|
|
3488
|
+
])
|
|
3489
|
+
)
|
|
3429
3490
|
);
|
|
3430
3491
|
};
|
|
3431
3492
|
if (overridePublicPath) {
|
|
3432
|
-
const resolved = this._resolvePublicPathPrefix(
|
|
3433
|
-
overridePublicPath,
|
|
3434
|
-
consumingModule,
|
|
3435
|
-
chunks
|
|
3436
|
-
);
|
|
3493
|
+
const resolved = this._resolvePublicPathPrefix(overridePublicPath);
|
|
3437
3494
|
return resolved === null ? null : specifier(resolved);
|
|
3438
3495
|
}
|
|
3439
3496
|
const { publicPath } = outputOptions;
|
|
3440
3497
|
if (publicPath === "auto") {
|
|
3441
|
-
const { undo } = this._placementOf(chunks);
|
|
3498
|
+
const { undo } = this._placementOf(chunks, hot);
|
|
3442
3499
|
if (undo !== null) return specifier([["literal", undo]]);
|
|
3443
3500
|
// Different depths — no one `../` path is right for every asset the reference
|
|
3444
3501
|
// 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)}`;
|
|
3502
|
+
return specifier([["undo", ""]]);
|
|
3454
3503
|
}
|
|
3455
3504
|
const prefix = this._analyzablePathPrefix(
|
|
3456
3505
|
consumingModule,
|
|
3457
3506
|
chunkGraph,
|
|
3458
|
-
chunks
|
|
3507
|
+
chunks,
|
|
3508
|
+
undefined,
|
|
3509
|
+
hot
|
|
3459
3510
|
);
|
|
3460
3511
|
return prefix === null ? null : specifier(prefix);
|
|
3461
3512
|
}
|
|
3462
3513
|
|
|
3514
|
+
/**
|
|
3515
|
+
* The template this chunk's asset of `sourceType` is named by: `undefined` where a
|
|
3516
|
+
* function reads a hash, `null` where nothing here names that type or it answers nothing.
|
|
3517
|
+
* @param {Chunk} chunk the chunk
|
|
3518
|
+
* @param {string} sourceType which asset of the chunk
|
|
3519
|
+
* @returns {string | undefined | null} the template
|
|
3520
|
+
*/
|
|
3521
|
+
_chunkAssetTemplate(chunk, sourceType) {
|
|
3522
|
+
const naming = CHUNK_ASSET_NAMING.get(sourceType);
|
|
3523
|
+
if (naming === undefined) return null;
|
|
3524
|
+
return this._resolveChunkFilenameTemplate(
|
|
3525
|
+
naming.template(chunk, this.outputOptions),
|
|
3526
|
+
chunk,
|
|
3527
|
+
sourceType
|
|
3528
|
+
);
|
|
3529
|
+
}
|
|
3530
|
+
|
|
3463
3531
|
/**
|
|
3464
3532
|
* The parts that go in front of a name so a literal read from the chunk holding it
|
|
3465
3533
|
* reaches what the runtime would. A public path needing no base is the whole answer.
|
|
@@ -3473,18 +3541,24 @@ class RuntimeTemplate {
|
|
|
3473
3541
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3474
3542
|
* @param {Iterable<Chunk>} chunks the chunks a stand-in would be written into
|
|
3475
3543
|
* @param {string=} relativeBase an entry `baseUri` read against the output root
|
|
3544
|
+
* @param {boolean=} hot whether a hot update can re-run what is written
|
|
3476
3545
|
* @returns {SpecifierPart[] | null} the parts, or `null` having recorded why not
|
|
3477
3546
|
*/
|
|
3478
|
-
_analyzablePathPrefix(
|
|
3547
|
+
_analyzablePathPrefix(
|
|
3548
|
+
module,
|
|
3549
|
+
chunkGraph,
|
|
3550
|
+
chunks,
|
|
3551
|
+
relativeBase,
|
|
3552
|
+
hot = isHotModule(module)
|
|
3553
|
+
) {
|
|
3479
3554
|
const publicPath = /** @type {PublicPath} */ (
|
|
3480
3555
|
this.outputOptions.publicPath
|
|
3481
3556
|
);
|
|
3482
3557
|
const shape = this._publicPathShape();
|
|
3483
3558
|
if (shape === undefined) return null;
|
|
3484
|
-
const resolve = () =>
|
|
3485
|
-
this._resolvePublicPathPrefix(publicPath, module, chunks);
|
|
3559
|
+
const resolve = () => this._resolvePublicPathPrefix(publicPath);
|
|
3486
3560
|
if (isBaseIndependent(shape)) return resolve();
|
|
3487
|
-
const { undo, loaded } = this._placementOf(chunks);
|
|
3561
|
+
const { undo, loaded } = this._placementOf(chunks, hot);
|
|
3488
3562
|
// What a chunk the loader fetched climbs back out of. One of no depth leaves
|
|
3489
3563
|
// nothing to climb, and then both answers put the same text in front.
|
|
3490
3564
|
const served = this._publicPathClimb();
|
|
@@ -3518,12 +3592,9 @@ class RuntimeTemplate {
|
|
|
3518
3592
|
* the deferred pass whole instead. A function is called for its value rather than
|
|
3519
3593
|
* read as a template, so one whose answer moves with the hash is called again there.
|
|
3520
3594
|
* @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
3595
|
* @returns {SpecifierPart[] | null} the parts, or `null` when it cannot be known
|
|
3525
3596
|
*/
|
|
3526
|
-
_resolvePublicPathPrefix(publicPath
|
|
3597
|
+
_resolvePublicPathPrefix(publicPath) {
|
|
3527
3598
|
if (typeof publicPath === "function") {
|
|
3528
3599
|
// One that answers nothing to a probe cannot be placed, absolute or not.
|
|
3529
3600
|
if (this._publicPathShape() === undefined) return null;
|
|
@@ -3534,28 +3605,18 @@ class RuntimeTemplate {
|
|
|
3534
3605
|
if (resolved !== null) return [["literal", resolved]];
|
|
3535
3606
|
// Called again by the fill against the compilation hash, so what it answers
|
|
3536
3607
|
// there is that hash by another name.
|
|
3537
|
-
return
|
|
3538
|
-
? [["publicPath", ""]]
|
|
3539
|
-
: null;
|
|
3608
|
+
return [["publicPath", ""]];
|
|
3540
3609
|
}
|
|
3541
3610
|
if (!publicPath.includes("[")) return [["literal", publicPath]];
|
|
3542
3611
|
// A re-encoded digest cannot be spelled by a stand-in, so it stays a template.
|
|
3543
3612
|
if (getTemplatedPathPlugin().usesFullHashDigest(publicPath)) {
|
|
3544
|
-
return
|
|
3545
|
-
? [["template", publicPath]]
|
|
3546
|
-
: null;
|
|
3613
|
+
return [["template", publicPath]];
|
|
3547
3614
|
}
|
|
3548
3615
|
const literal = this.compilation.getPath(
|
|
3549
3616
|
publicPath,
|
|
3550
3617
|
this._deferredFullHashPathData()
|
|
3551
3618
|
);
|
|
3552
|
-
return
|
|
3553
|
-
this._hasReservedFullHash(literal),
|
|
3554
|
-
chunks,
|
|
3555
|
-
module
|
|
3556
|
-
)
|
|
3557
|
-
? [["literal", literal]]
|
|
3558
|
-
: null;
|
|
3619
|
+
return [["literal", literal]];
|
|
3559
3620
|
}
|
|
3560
3621
|
|
|
3561
3622
|
/**
|
|
@@ -3640,7 +3701,7 @@ class RuntimeTemplate {
|
|
|
3640
3701
|
relativeBase
|
|
3641
3702
|
);
|
|
3642
3703
|
if (prefix === null) return null;
|
|
3643
|
-
return this._specifierOf([...prefix, ...file], chunks
|
|
3704
|
+
return this._specifierOf([...prefix, ...file], chunks);
|
|
3644
3705
|
}
|
|
3645
3706
|
// No public path to place it against, so the `../` path back to the output root
|
|
3646
3707
|
// is the whole prefix. Different depths — no one is right for every asset the
|
|
@@ -3650,23 +3711,22 @@ class RuntimeTemplate {
|
|
|
3650
3711
|
const parts = [undo === null ? ["undo", ""] : ["literal", undo]];
|
|
3651
3712
|
if (relativeBase !== undefined) parts.push(["literal", relativeBase]);
|
|
3652
3713
|
parts.push(...file);
|
|
3653
|
-
return this._specifierOf(parts, chunks
|
|
3714
|
+
return this._specifierOf(parts, chunks);
|
|
3654
3715
|
}
|
|
3655
3716
|
|
|
3656
3717
|
/**
|
|
3657
3718
|
* Static `new URL(<file>, import.meta.url)` for every stylesheet a runtime can load,
|
|
3658
|
-
* keyed by chunk id
|
|
3659
|
-
*
|
|
3719
|
+
* keyed by chunk id, or `null` when they have to keep the runtime
|
|
3720
|
+
* `publicPath + getChunkCssFilename(id)` form. Both the runtime module reading them
|
|
3660
3721
|
* and the plugin declaring what it needs ask this, so the two always agree. The
|
|
3661
3722
|
* runtime hands an absolute url string to `link.href`, and so does this — the browser
|
|
3662
3723
|
* 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.
|
|
3724
|
+
* the loader reads the url as text either way.
|
|
3665
3725
|
* @param {Chunk} runtimeChunk the chunk holding the stylesheet loader
|
|
3666
3726
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3667
3727
|
* @param {ReadOnlyRuntimeRequirements} runtimeRequirements what that chunk needs
|
|
3668
3728
|
* @param {Module=} consumingModule the runtime module, where one exists to report against
|
|
3669
|
-
* @returns {
|
|
3729
|
+
* @returns {Map<ChunkId, string> | null} the urls, or `null` to keep the runtime form
|
|
3670
3730
|
*/
|
|
3671
3731
|
analyzableCssChunkUrls(
|
|
3672
3732
|
runtimeChunk,
|
|
@@ -3698,14 +3758,14 @@ class RuntimeTemplate {
|
|
|
3698
3758
|
/**
|
|
3699
3759
|
* Static `new URL(<file>, import.meta.url).href` for every javascript chunk a
|
|
3700
3760
|
* runtime can hint at with `<link rel="prefetch"/"modulepreload">`, keyed by chunk
|
|
3701
|
-
* id
|
|
3702
|
-
*
|
|
3761
|
+
* id, or `null` when they have to keep the runtime
|
|
3762
|
+
* `publicPath + getChunkScriptFilename(id)` form. Both the runtime module reading
|
|
3703
3763
|
* them and the plugin declaring what it needs ask this, so the two always agree.
|
|
3704
3764
|
* @param {Chunk} runtimeChunk the chunk holding the hint handlers
|
|
3705
3765
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3706
3766
|
* @param {ReadOnlyRuntimeRequirements} runtimeRequirements what that chunk needs
|
|
3707
3767
|
* @param {Module=} consumingModule the runtime module, where one exists to report against
|
|
3708
|
-
* @returns {
|
|
3768
|
+
* @returns {Map<ChunkId, string> | null} the urls, or `null` to keep the runtime form
|
|
3709
3769
|
*/
|
|
3710
3770
|
analyzableChunkScriptUrls(
|
|
3711
3771
|
runtimeChunk,
|
|
@@ -3742,17 +3802,156 @@ class RuntimeTemplate {
|
|
|
3742
3802
|
);
|
|
3743
3803
|
}
|
|
3744
3804
|
|
|
3805
|
+
/**
|
|
3806
|
+
* Why no chunk import of this build can be a native `import()`, read from the
|
|
3807
|
+
* output configuration alone, or `null` when nothing in it rules one out.
|
|
3808
|
+
* @returns {string | null} the reason
|
|
3809
|
+
*/
|
|
3810
|
+
_chunkImportOutputReason() {
|
|
3811
|
+
const { chunkFormat, importFunctionName } = this.outputOptions;
|
|
3812
|
+
if (chunkFormat !== "module") {
|
|
3813
|
+
return `output.chunkFormat is ${JSON.stringify(chunkFormat)}, so chunks are not read through a native import()`;
|
|
3814
|
+
}
|
|
3815
|
+
if (importFunctionName !== "import") {
|
|
3816
|
+
return `output.importFunctionName is ${JSON.stringify(importFunctionName)}, so the call site is not a native import()`;
|
|
3817
|
+
}
|
|
3818
|
+
return null;
|
|
3819
|
+
}
|
|
3820
|
+
|
|
3821
|
+
/**
|
|
3822
|
+
* Records that this runtime reads its chunks some way other than a native
|
|
3823
|
+
* `import()`, so no literal can name what it loads. Recorded on the entries that
|
|
3824
|
+
* chose it, which is where the setting behind it lives.
|
|
3825
|
+
* @param {Chunk} chunk the runtime chunk
|
|
3826
|
+
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3827
|
+
* @returns {void}
|
|
3828
|
+
*/
|
|
3829
|
+
reportChunkImportBailout(chunk, chunkGraph) {
|
|
3830
|
+
if (!this.outputOptions.module) return;
|
|
3831
|
+
const entryOptions = chunk.getEntryOptions();
|
|
3832
|
+
const chunkLoading =
|
|
3833
|
+
entryOptions && entryOptions.chunkLoading !== undefined
|
|
3834
|
+
? entryOptions.chunkLoading
|
|
3835
|
+
: this.outputOptions.chunkLoading;
|
|
3836
|
+
if (chunkLoading === "import") return;
|
|
3837
|
+
const subject = entryOptions && entryOptions.worker ? "worker" : "runtime";
|
|
3838
|
+
const reason = `this ${subject} loads its chunks with ${JSON.stringify(chunkLoading)}, not "import"`;
|
|
3839
|
+
for (const module of chunkGraph.getChunkEntryModulesIterable(chunk)) {
|
|
3840
|
+
this._analyzableBailout(module, reason, false);
|
|
3841
|
+
}
|
|
3842
|
+
}
|
|
3843
|
+
|
|
3844
|
+
/**
|
|
3845
|
+
* The chunks this loader can be handed an id for: the ones held by a group outside
|
|
3846
|
+
* the initial wave, which is what an `import()` or a context map turns into an id.
|
|
3847
|
+
* @param {Chunk} runtimeChunk the chunk holding the chunk loader
|
|
3848
|
+
* @returns {Set<Chunk>} the chunks reachable from here through a non-initial group
|
|
3849
|
+
*/
|
|
3850
|
+
_loadableChunks(runtimeChunk) {
|
|
3851
|
+
const queue = new Set(runtimeChunk.groupsIterable);
|
|
3852
|
+
/** @type {Set<Chunk>} */
|
|
3853
|
+
const chunks = new Set();
|
|
3854
|
+
for (const group of queue) {
|
|
3855
|
+
if (!group.isInitial()) {
|
|
3856
|
+
for (const chunk of group.chunks) chunks.add(chunk);
|
|
3857
|
+
}
|
|
3858
|
+
for (const child of group.childrenIterable) queue.add(child);
|
|
3859
|
+
}
|
|
3860
|
+
return chunks;
|
|
3861
|
+
}
|
|
3862
|
+
|
|
3863
|
+
/**
|
|
3864
|
+
* Whether the loader still needs to build a url from a chunk id, which is the case
|
|
3865
|
+
* for a chunk it can be asked for that `analyzableChunkImports` leaves unnamed: one
|
|
3866
|
+
* carrying a runtime of its own, or one a second entrypoint has at startup.
|
|
3867
|
+
* @param {Chunk} runtimeChunk the chunk holding the chunk loader
|
|
3868
|
+
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3869
|
+
* @returns {boolean} true when an id the map does not hold can reach the loader
|
|
3870
|
+
*/
|
|
3871
|
+
chunkImportsNeedRuntimeUrl(runtimeChunk, chunkGraph) {
|
|
3872
|
+
const installed = new Set(runtimeChunk.getAllInitialChunks());
|
|
3873
|
+
for (const chunk of this._loadableChunks(runtimeChunk)) {
|
|
3874
|
+
if (chunk === runtimeChunk) continue;
|
|
3875
|
+
if (!chunk.hasRuntime() && !installed.has(chunk)) continue;
|
|
3876
|
+
if (JavascriptModulesPlugin.chunkHasJs(chunk, chunkGraph)) return true;
|
|
3877
|
+
}
|
|
3878
|
+
return false;
|
|
3879
|
+
}
|
|
3880
|
+
|
|
3881
|
+
/**
|
|
3882
|
+
* A literal `import()` specifier for every javascript chunk a runtime loads on
|
|
3883
|
+
* demand, keyed by chunk id, or `null` when one of them cannot be named here. The
|
|
3884
|
+
* map is written into the runtime chunk rather than at each import site, so a
|
|
3885
|
+
* hashed chunk name reaches no module that imports it.
|
|
3886
|
+
* @param {Chunk} runtimeChunk the chunk holding the chunk loader
|
|
3887
|
+
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3888
|
+
* @param {ReadOnlyRuntimeRequirements} runtimeRequirements what that chunk needs
|
|
3889
|
+
* @param {Module=} consumingModule the runtime module, where one exists to report against
|
|
3890
|
+
* @returns {Map<ChunkId, string> | null} the specifiers, or `null` to keep the runtime form
|
|
3891
|
+
*/
|
|
3892
|
+
analyzableChunkImports(
|
|
3893
|
+
runtimeChunk,
|
|
3894
|
+
chunkGraph,
|
|
3895
|
+
runtimeRequirements,
|
|
3896
|
+
consumingModule
|
|
3897
|
+
) {
|
|
3898
|
+
// The runtime names the scope `__webpack_public_path__` belongs to, so the
|
|
3899
|
+
// answer holds whether or not a runtime module is there to ask about.
|
|
3900
|
+
if (
|
|
3901
|
+
!this.supportsAnalyzable(
|
|
3902
|
+
"import",
|
|
3903
|
+
chunkGraph,
|
|
3904
|
+
consumingModule,
|
|
3905
|
+
runtimeChunk.runtime
|
|
3906
|
+
)
|
|
3907
|
+
) {
|
|
3908
|
+
return null;
|
|
3909
|
+
}
|
|
3910
|
+
// An initial chunk and one carrying a runtime are both reached by a static
|
|
3911
|
+
// import, so naming either here would only make two hashes chase each other.
|
|
3912
|
+
const installed = new Set(runtimeChunk.getAllInitialChunks());
|
|
3913
|
+
/** @type {Chunk[]} */
|
|
3914
|
+
const chunks = [];
|
|
3915
|
+
for (const chunk of runtimeChunk.getAllReferencedChunks()) {
|
|
3916
|
+
if (
|
|
3917
|
+
chunk === runtimeChunk ||
|
|
3918
|
+
chunk.hasRuntime() ||
|
|
3919
|
+
installed.has(chunk) ||
|
|
3920
|
+
!JavascriptModulesPlugin.chunkHasJs(chunk, chunkGraph)
|
|
3921
|
+
) {
|
|
3922
|
+
continue;
|
|
3923
|
+
}
|
|
3924
|
+
chunks.push(chunk);
|
|
3925
|
+
}
|
|
3926
|
+
const specifiers = this._analyzableChunkSpecifiers(
|
|
3927
|
+
chunks,
|
|
3928
|
+
chunkGraph,
|
|
3929
|
+
consumingModule,
|
|
3930
|
+
[runtimeChunk],
|
|
3931
|
+
JAVASCRIPT_TYPE,
|
|
3932
|
+
runtimeRequirements
|
|
3933
|
+
);
|
|
3934
|
+
if (specifiers === null) return null;
|
|
3935
|
+
for (const [id, specifier] of specifiers) {
|
|
3936
|
+
// A bare specifier is a package name, so spell it relative the way the
|
|
3937
|
+
// runtime form's `.p + <file>` would have resolved it.
|
|
3938
|
+
if (!RESOLVABLE_SPECIFIER_REGEXP.test(specifier.slice(1))) {
|
|
3939
|
+
specifiers.set(id, `"./${specifier.slice(1)}`);
|
|
3940
|
+
}
|
|
3941
|
+
}
|
|
3942
|
+
return specifiers;
|
|
3943
|
+
}
|
|
3944
|
+
|
|
3745
3945
|
/**
|
|
3746
3946
|
* 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.
|
|
3947
|
+
* chunk id, or `null` as soon as one of them cannot be named here.
|
|
3749
3948
|
* @param {Iterable<Chunk>} chunks the chunks whose asset is wanted
|
|
3750
3949
|
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3751
3950
|
* @param {Module | undefined} consumingModule the runtime module, where one exists to report against
|
|
3752
3951
|
* @param {Chunk[]} consumingChunks the chunks the urls are written into
|
|
3753
3952
|
* @param {string} sourceType which asset of each chunk to name
|
|
3754
3953
|
* @param {ReadOnlyRuntimeRequirements} runtimeRequirements what the runtime chunk needs
|
|
3755
|
-
* @returns {
|
|
3954
|
+
* @returns {Map<ChunkId, string> | null} the urls, or `null` to keep the runtime form
|
|
3756
3955
|
*/
|
|
3757
3956
|
_analyzableChunkUrls(
|
|
3758
3957
|
chunks,
|
|
@@ -3762,17 +3961,51 @@ class RuntimeTemplate {
|
|
|
3762
3961
|
sourceType,
|
|
3763
3962
|
runtimeRequirements
|
|
3764
3963
|
) {
|
|
3765
|
-
|
|
3766
|
-
// to HMR — analyzable output is what ships.
|
|
3767
|
-
if (
|
|
3768
|
-
runtimeRequirements.has(RuntimeGlobals.hmrDownloadUpdateHandlers) ||
|
|
3769
|
-
!this.supportsAnalyzable("url-runtime", chunkGraph, consumingModule)
|
|
3770
|
-
) {
|
|
3964
|
+
if (!this.supportsAnalyzable("url-runtime", chunkGraph, consumingModule)) {
|
|
3771
3965
|
return null;
|
|
3772
3966
|
}
|
|
3967
|
+
const urls = this._analyzableChunkSpecifiers(
|
|
3968
|
+
chunks,
|
|
3969
|
+
chunkGraph,
|
|
3970
|
+
consumingModule,
|
|
3971
|
+
consumingChunks,
|
|
3972
|
+
sourceType,
|
|
3973
|
+
runtimeRequirements
|
|
3974
|
+
);
|
|
3975
|
+
if (urls === null) return null;
|
|
3976
|
+
for (const [id, specifier] of urls) {
|
|
3977
|
+
urls.set(id, `${this.importMetaUrl(specifier)}.href`);
|
|
3978
|
+
}
|
|
3979
|
+
return urls;
|
|
3980
|
+
}
|
|
3981
|
+
|
|
3982
|
+
/**
|
|
3983
|
+
* The quoted specifier naming one asset of each of `chunks`, keyed by chunk id, or
|
|
3984
|
+
* `null` as soon as one of them cannot be named here. What the name is read against
|
|
3985
|
+
* is the caller's: a url resolves it, an `import()` hands it to the loader.
|
|
3986
|
+
* @param {Iterable<Chunk>} chunks the chunks whose asset is wanted
|
|
3987
|
+
* @param {ChunkGraph} chunkGraph the chunk graph
|
|
3988
|
+
* @param {Module | undefined} consumingModule the runtime module, where one exists to report against
|
|
3989
|
+
* @param {Chunk[]} consumingChunks the chunks the specifiers are written into
|
|
3990
|
+
* @param {string} sourceType which asset of each chunk to name
|
|
3991
|
+
* @param {ReadOnlyRuntimeRequirements} runtimeRequirements what the runtime chunk needs
|
|
3992
|
+
* @returns {Map<ChunkId, string> | null} the specifiers, or `null` to keep the runtime form
|
|
3993
|
+
*/
|
|
3994
|
+
_analyzableChunkSpecifiers(
|
|
3995
|
+
chunks,
|
|
3996
|
+
chunkGraph,
|
|
3997
|
+
consumingModule,
|
|
3998
|
+
consumingChunks,
|
|
3999
|
+
sourceType,
|
|
4000
|
+
runtimeRequirements
|
|
4001
|
+
) {
|
|
4002
|
+
// A hot update re-ships the runtime module only when its own code changes, so
|
|
4003
|
+
// each name has to be text nothing but an id joining or leaving the map can move.
|
|
4004
|
+
const hot = runtimeRequirements.has(
|
|
4005
|
+
RuntimeGlobals.hmrDownloadUpdateHandlers
|
|
4006
|
+
);
|
|
3773
4007
|
/** @type {Map<ChunkId, string>} */
|
|
3774
|
-
const
|
|
3775
|
-
let complete = true;
|
|
4008
|
+
const specifiers = new Map();
|
|
3776
4009
|
for (const chunk of chunks) {
|
|
3777
4010
|
if (chunk.id === null) continue;
|
|
3778
4011
|
const specifier = this._getAnalyzableChunkSpecifier(
|
|
@@ -3780,18 +4013,74 @@ class RuntimeTemplate {
|
|
|
3780
4013
|
chunk,
|
|
3781
4014
|
consumingModule,
|
|
3782
4015
|
chunkGraph,
|
|
3783
|
-
undefined,
|
|
3784
4016
|
consumingChunks,
|
|
3785
|
-
sourceType
|
|
4017
|
+
sourceType,
|
|
4018
|
+
hot
|
|
3786
4019
|
);
|
|
3787
|
-
|
|
3788
|
-
if (
|
|
3789
|
-
|
|
4020
|
+
if (specifier === null) return null;
|
|
4021
|
+
if (
|
|
4022
|
+
hot &&
|
|
4023
|
+
!this._settledUnderHot(specifier, chunk, sourceType, consumingChunks)
|
|
4024
|
+
) {
|
|
4025
|
+
return this._analyzableBailout(consumingModule, HOT_NAME_BAILOUT, null);
|
|
4026
|
+
}
|
|
4027
|
+
specifiers.set(chunk.id, specifier);
|
|
4028
|
+
}
|
|
4029
|
+
return specifiers.size > 0 ? specifiers : null;
|
|
4030
|
+
}
|
|
4031
|
+
|
|
4032
|
+
/**
|
|
4033
|
+
* Whether a url a hot update re-ships moves only with the runtime module's own text:
|
|
4034
|
+
* spelled here, or a stand-in of each asset's depth and a hash-free or settled name.
|
|
4035
|
+
* @param {string} specifier the specifier already quoted
|
|
4036
|
+
* @param {Chunk} chunk the chunk it names
|
|
4037
|
+
* @param {string} sourceType which asset of the chunk it names
|
|
4038
|
+
* @param {Chunk[]} consumingChunks the chunks the map is written into
|
|
4039
|
+
* @returns {boolean} true when no update moves what the fill spells
|
|
4040
|
+
*/
|
|
4041
|
+
_settledUnderHot(specifier, chunk, sourceType, consumingChunks) {
|
|
4042
|
+
const match = ANALYZABLE_TOKEN_PAYLOAD.exec(specifier);
|
|
4043
|
+
if (match === null) return true;
|
|
4044
|
+
const parts = RuntimeTemplate._readAnalyzableSpecifier(match[1]);
|
|
4045
|
+
if (parts === null) return false;
|
|
4046
|
+
for (const [kind, value] of parts) {
|
|
4047
|
+
if (kind === "undo") continue;
|
|
4048
|
+
if (kind === "literal" && !this._hasReservedFullHash(String(value))) {
|
|
3790
4049
|
continue;
|
|
3791
4050
|
}
|
|
3792
|
-
|
|
4051
|
+
if (!CHUNK_SPECIFIER_PART_KINDS.has(kind)) return false;
|
|
3793
4052
|
}
|
|
3794
|
-
|
|
4053
|
+
const template = this._chunkAssetTemplate(chunk, sourceType);
|
|
4054
|
+
return (
|
|
4055
|
+
typeof template === "string" &&
|
|
4056
|
+
(!HASH_IN_FILENAME.test(template) ||
|
|
4057
|
+
this._hashedNameSettledBefore(chunk, template, consumingChunks))
|
|
4058
|
+
);
|
|
4059
|
+
}
|
|
4060
|
+
|
|
4061
|
+
/**
|
|
4062
|
+
* The `../` path from a chunk's hot update file, which re-runs its modules, back to
|
|
4063
|
+
* the output root. Hashes are neutralized; the chunk's own id may add a directory.
|
|
4064
|
+
* @param {Chunk} chunk the chunk being updated
|
|
4065
|
+
* @returns {string} the path back to the output root
|
|
4066
|
+
*/
|
|
4067
|
+
_hotUpdateUndo(chunk) {
|
|
4068
|
+
const cached = this._hotUpdateUndoByChunk.get(chunk);
|
|
4069
|
+
if (cached !== undefined) return cached;
|
|
4070
|
+
const { outputOptions } = this;
|
|
4071
|
+
if (this._hotUpdateShapeText === undefined) {
|
|
4072
|
+
this._hotUpdateShapeText = outputOptions.hotUpdateChunkFilename.replace(
|
|
4073
|
+
HASH_IN_FILENAME_GLOBAL,
|
|
4074
|
+
"x"
|
|
4075
|
+
);
|
|
4076
|
+
}
|
|
4077
|
+
const undo = getUndoPath(
|
|
4078
|
+
this.compilation.getPath(this._hotUpdateShapeText, { chunk }),
|
|
4079
|
+
/** @type {string} */ (outputOptions.path),
|
|
4080
|
+
true
|
|
4081
|
+
);
|
|
4082
|
+
this._hotUpdateUndoByChunk.set(chunk, undo);
|
|
4083
|
+
return undo;
|
|
3795
4084
|
}
|
|
3796
4085
|
|
|
3797
4086
|
/**
|
|
@@ -3997,7 +4286,7 @@ class RuntimeTemplate {
|
|
|
3997
4286
|
* @returns {string} the stand-in to emit
|
|
3998
4287
|
*/
|
|
3999
4288
|
_reserveAnalyzableSpecifier(parts) {
|
|
4000
|
-
return
|
|
4289
|
+
return `${ANALYZABLE_TOKEN_PREFIX}${Buffer.from(JSON.stringify(parts))
|
|
4001
4290
|
.toString("base64")
|
|
4002
4291
|
.replace(/\+/g, "-")
|
|
4003
4292
|
.replace(/\//g, "_")
|
|
@@ -4058,16 +4347,18 @@ class RuntimeTemplate {
|
|
|
4058
4347
|
compilation.hooks.processAssets.tapPromise(
|
|
4059
4348
|
{
|
|
4060
4349
|
name: PASS_NAME,
|
|
4061
|
-
// Before source maps are written and before a minifier runs
|
|
4062
|
-
// the asset
|
|
4063
|
-
// Every hash it reads is
|
|
4064
|
-
// every `processAssets` stage — and `RealContentHashPlugin` still repairs
|
|
4065
|
-
// the names afterwards.
|
|
4350
|
+
// Before source maps are written and before a minifier runs, since both
|
|
4351
|
+
// read the asset and a stand-in differs in length from what replaces it.
|
|
4352
|
+
// Every hash it reads is settled: `createHash` precedes every stage.
|
|
4066
4353
|
stage: getCompilation().PROCESS_ASSETS_STAGE_DERIVED
|
|
4067
4354
|
},
|
|
4068
4355
|
async () => {
|
|
4069
4356
|
const { outputOptions } = compilation;
|
|
4070
4357
|
const fullHash = compilation.hash;
|
|
4358
|
+
// The assets a stand-in landed in whose hashed name has to be brought
|
|
4359
|
+
// back in line, which `RealContentHashPlugin` then does.
|
|
4360
|
+
/** @type {Set<string>} */
|
|
4361
|
+
const repairedAssets = new Set();
|
|
4071
4362
|
/** @type {Map<string, Chunk> | undefined} */
|
|
4072
4363
|
let chunksById;
|
|
4073
4364
|
/** @type {Map<string, Chunk> | undefined} */
|
|
@@ -4122,7 +4413,9 @@ class RuntimeTemplate {
|
|
|
4122
4413
|
let base;
|
|
4123
4414
|
let specifier = "";
|
|
4124
4415
|
for (const [kind, value] of parts) {
|
|
4125
|
-
if (kind === "
|
|
4416
|
+
if (kind === "repair") {
|
|
4417
|
+
repairedAssets.add(assetName);
|
|
4418
|
+
} else if (kind === "base") {
|
|
4126
4419
|
base = /** @type {string} */ (value);
|
|
4127
4420
|
} else if (kind === "literal") {
|
|
4128
4421
|
specifier += value;
|
|
@@ -4193,7 +4486,7 @@ class RuntimeTemplate {
|
|
|
4193
4486
|
// the chunk loader does. A literal part may still carry a stand-in of its own,
|
|
4194
4487
|
// so finish those here rather than scanning again.
|
|
4195
4488
|
return fillFullHash(
|
|
4196
|
-
|
|
4489
|
+
RESOLVABLE_SPECIFIER_REGEXP.test(specifier)
|
|
4197
4490
|
? specifier
|
|
4198
4491
|
: `./${specifier}`
|
|
4199
4492
|
);
|
|
@@ -4246,6 +4539,8 @@ class RuntimeTemplate {
|
|
|
4246
4539
|
|
|
4247
4540
|
tasks.push({ name, source, replacements });
|
|
4248
4541
|
}
|
|
4542
|
+
compilation.runtimeTemplate._analyzableRepairedAssets =
|
|
4543
|
+
repairedAssets;
|
|
4249
4544
|
if (tasks.length === 0) return;
|
|
4250
4545
|
|
|
4251
4546
|
await Promise.all(
|