webpack 5.110.2 → 5.110.3
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 +0 -2
- package/lib/ChunkGraph.js +20 -18
- package/lib/Compilation.js +1 -1
- package/lib/ConcatenationScope.js +25 -35
- package/lib/DotenvPlugin.js +41 -13
- package/lib/FlagDependencyUsagePlugin.js +8 -2
- package/lib/NormalModule.js +13 -20
- package/lib/RuntimePlugin.js +3 -0
- package/lib/RuntimeTemplate.js +14 -2
- package/lib/async-modules/AsyncModuleHelpers.js +10 -4
- package/lib/config/defaults.js +26 -16
- package/lib/config/normalization.js +18 -8
- package/lib/dependencies/CommonJsRequireDependency.js +18 -4
- package/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +20 -7
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +100 -19
- package/lib/dependencies/HarmonyImportDependency.js +94 -41
- package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +12 -2
- package/lib/dependencies/HtmlEntryDependency.js +12 -2
- package/lib/dependencies/ImportContextDependency.js +43 -3
- package/lib/dependencies/ImportDependency.js +8 -29
- package/lib/dependencies/ImportParserPlugin.js +24 -14
- package/lib/dependencies/RequireHeaderDependency.js +20 -21
- package/lib/dependencies/importOptionsCheck.js +47 -0
- package/lib/errors/DotenvFileError.js +29 -0
- package/lib/errors/ImportedBindingAssignmentError.js +30 -0
- package/lib/html/HtmlModulesPlugin.js +29 -22
- package/lib/html/syntax.js +304 -143
- package/lib/javascript/JavascriptModulesPlugin.js +2 -0
- package/lib/optimize/ConcatenatedModule.js +38 -7
- package/lib/prefetch/ResourceHintPlugin.js +6 -1
- package/lib/runtime/AsyncModuleRuntimeModule.js +5 -1
- package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +11 -1
- package/lib/schemes/HttpUriPlugin.js +22 -5
- package/lib/serialization/FileMiddleware.js +15 -2
- package/lib/util/ArrayQueue.js +3 -3
- package/lib/util/URLAbsoluteSpecifier.js +3 -1
- package/lib/util/conventions.js +5 -1
- package/lib/util/internalSerializables.js +2 -0
- package/package.json +1 -1
- package/schemas/WebpackOptions.check.js +1 -1
- package/schemas/WebpackOptions.json +9 -10
- package/types.d.ts +26 -17
package/README.md
CHANGED
|
@@ -301,8 +301,6 @@ For information about the governance of the webpack project, see [GOVERNANCE.md]
|
|
|
301
301
|
**Aviv Keller** <<me@aviv.sh>> (he/him)
|
|
302
302
|
- [evenstensberg](https://github.com/evenstensberg) -
|
|
303
303
|
**Even Stensberg** <<evenstensberg@gmail.com>> (he/him)
|
|
304
|
-
- [ovflowd](https://github.com/ovflowd) -
|
|
305
|
-
**Claudio Wunder** <<cwunder@gnome.org>> (he/they)
|
|
306
304
|
- [thelarkinn](https://github.com/thelarkinn) -
|
|
307
305
|
**Sean Larkin** <<selarkin@microsoft.com>> (he/him)
|
|
308
306
|
|
package/lib/ChunkGraph.js
CHANGED
|
@@ -1380,27 +1380,29 @@ class ChunkGraph {
|
|
|
1380
1380
|
|
|
1381
1381
|
for (const chunkGroup of chunk.groupsIterable) {
|
|
1382
1382
|
if (chunkGroup instanceof Entrypoint) {
|
|
1383
|
+
if (entrypoints.has(chunkGroup)) continue;
|
|
1384
|
+
entrypoints.add(chunkGroup);
|
|
1385
|
+
// `entrypoints` doubles as the visited set: a diamond of `dependOn`
|
|
1386
|
+
// edges would otherwise re-traverse the shared entrypoint per path
|
|
1383
1387
|
const queue = [chunkGroup];
|
|
1384
|
-
|
|
1385
|
-
const current = queue
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
queue.push(/** @type {Entrypoint} */ (child));
|
|
1388
|
+
for (let i = 0; i < queue.length; i++) {
|
|
1389
|
+
const current = queue[i];
|
|
1390
|
+
let hasChildrenEntrypoint = false;
|
|
1391
|
+
for (const child of current.childrenIterable) {
|
|
1392
|
+
if (child instanceof Entrypoint && child.dependOn(current)) {
|
|
1393
|
+
hasChildrenEntrypoint = true;
|
|
1394
|
+
if (!entrypoints.has(child)) {
|
|
1395
|
+
entrypoints.add(child);
|
|
1396
|
+
queue.push(child);
|
|
1394
1397
|
}
|
|
1395
1398
|
}
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
}
|
|
1399
|
+
}
|
|
1400
|
+
// an entrypoint others depend on has to be loaded before them,
|
|
1401
|
+
// unless it is the runtime chunk itself or carries its own runtime
|
|
1402
|
+
if (hasChildrenEntrypoint) {
|
|
1403
|
+
const entrypointChunk = current.getEntrypointChunk();
|
|
1404
|
+
if (entrypointChunk !== chunk && !entrypointChunk.hasRuntime()) {
|
|
1405
|
+
set.add(entrypointChunk);
|
|
1404
1406
|
}
|
|
1405
1407
|
}
|
|
1406
1408
|
}
|
package/lib/Compilation.js
CHANGED
|
@@ -4083,7 +4083,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|
|
4083
4083
|
const text = /** @type {string} */ (source.source());
|
|
4084
4084
|
// Everything the hook is handed is in the key: a tap answers per language
|
|
4085
4085
|
// pair, so identical text offered as two of them is two questions.
|
|
4086
|
-
const key = `${info.type}
|
|
4086
|
+
const key = `${info.type}\0${info.hostType}\0${text}`;
|
|
4087
4087
|
const resolved = this._embeddedSources.get(info.module);
|
|
4088
4088
|
if (resolved !== undefined) {
|
|
4089
4089
|
const hit = resolved.get(key);
|
|
@@ -19,9 +19,10 @@ const {
|
|
|
19
19
|
* ExportName as Ids
|
|
20
20
|
* } from "./optimize/ConcatenatedModule"
|
|
21
21
|
*/
|
|
22
|
-
/** @import { Range } from "./javascript/JavascriptParser" */
|
|
23
22
|
|
|
24
|
-
/** @typedef {{ start: number, end: number, name: string }} ModuleReferenceMatch */
|
|
23
|
+
/** @typedef {{ start: number, end: number, name: string, leaked: boolean }} ModuleReferenceMatch */
|
|
24
|
+
|
|
25
|
+
const MODULE_REFERENCE_TOKEN = "__WEBPACK_MODULE_REFERENCE__";
|
|
25
26
|
|
|
26
27
|
const MODULE_REFERENCE_REGEXP =
|
|
27
28
|
/^__WEBPACK_MODULE_REFERENCE__(\d+)_([\da-f]+|ns)(_call)?(_directImport)?(_deferredImport)?(_mangleableNs)?(_moduleExportsAccess)?(?:_asiSafe(\d))?__$/;
|
|
@@ -33,6 +34,8 @@ const MODULE_REFERENCE_SCAN_REGEXP = new RegExp(
|
|
|
33
34
|
"g"
|
|
34
35
|
);
|
|
35
36
|
|
|
37
|
+
const IDENTIFIER_CHARACTER_REGEXP = /[\w$]/;
|
|
38
|
+
|
|
36
39
|
/** @type {WeakMap<Source, ModuleReferenceMatch[]>} */
|
|
37
40
|
const moduleReferencesCache = new WeakMap();
|
|
38
41
|
|
|
@@ -76,10 +79,6 @@ class ConcatenationScope {
|
|
|
76
79
|
this.usedNames = usedNames;
|
|
77
80
|
/** @type {Map<Module, ModuleInfo>} */
|
|
78
81
|
this._modulesMap = modulesMap;
|
|
79
|
-
// written and read by dependency templates within a single code
|
|
80
|
-
// generation pass, never across passes
|
|
81
|
-
/** @type {Range[] | undefined} */
|
|
82
|
-
this._replacedRequireRanges = undefined;
|
|
83
82
|
}
|
|
84
83
|
|
|
85
84
|
/**
|
|
@@ -121,33 +120,6 @@ class ConcatenationScope {
|
|
|
121
120
|
return this._currentModule.wrapped;
|
|
122
121
|
}
|
|
123
122
|
|
|
124
|
-
/**
|
|
125
|
-
* Records a `require(...)` call that was replaced as a whole by a
|
|
126
|
-
* concatenation reference, so nothing else rewrites a range inside it.
|
|
127
|
-
* @param {Range} range source range of the replaced call
|
|
128
|
-
*/
|
|
129
|
-
registerReplacedRequire(range) {
|
|
130
|
-
if (this._replacedRequireRanges === undefined) {
|
|
131
|
-
this._replacedRequireRanges = [];
|
|
132
|
-
}
|
|
133
|
-
this._replacedRequireRanges.push(range);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Checks whether an offset sits inside an already-replaced `require(...)` call.
|
|
138
|
-
* Containment, not exact match: `new require(...)` is replaced from `new`.
|
|
139
|
-
* @param {number} start start offset to test
|
|
140
|
-
* @returns {boolean} true, when the offset was replaced already
|
|
141
|
-
*/
|
|
142
|
-
isInsideReplacedRequire(start) {
|
|
143
|
-
const ranges = this._replacedRequireRanges;
|
|
144
|
-
if (ranges === undefined) return false;
|
|
145
|
-
for (const [rangeStart, rangeEnd] of ranges) {
|
|
146
|
-
if (start >= rangeStart && start < rangeEnd) return true;
|
|
147
|
-
}
|
|
148
|
-
return false;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
123
|
/**
|
|
152
124
|
* Records the symbol that should be used when the current module exports a
|
|
153
125
|
* named binding.
|
|
@@ -263,7 +235,22 @@ class ConcatenationScope {
|
|
|
263
235
|
}
|
|
264
236
|
|
|
265
237
|
/**
|
|
266
|
-
*
|
|
238
|
+
* Checks whether an identifier buries a reference token without being one,
|
|
239
|
+
* which nothing can resolve: it would reach the output as an undeclared global.
|
|
240
|
+
* @param {string} name the identifier
|
|
241
|
+
* @returns {boolean} true, when a reference token is buried in the identifier
|
|
242
|
+
*/
|
|
243
|
+
static isLeakedModuleReference(name) {
|
|
244
|
+
return (
|
|
245
|
+
name.includes(MODULE_REFERENCE_TOKEN) &&
|
|
246
|
+
!MODULE_REFERENCE_REGEXP.test(name)
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Finds all encoded module references in a generated source. A match that
|
|
252
|
+
* continues an identifier is reported as `leaked`: it is a token a wider
|
|
253
|
+
* replacement swallowed, so substituting it would rewrite the middle of a name.
|
|
267
254
|
* @param {Source} source generated source
|
|
268
255
|
* @returns {ModuleReferenceMatch[]} reference token positions (end is exclusive, excludes the appended "._")
|
|
269
256
|
*/
|
|
@@ -279,7 +266,10 @@ class ConcatenationScope {
|
|
|
279
266
|
result.push({
|
|
280
267
|
start: match.index,
|
|
281
268
|
end: match.index + match[0].length,
|
|
282
|
-
name: match[0]
|
|
269
|
+
name: match[0],
|
|
270
|
+
leaked:
|
|
271
|
+
match.index > 0 &&
|
|
272
|
+
IDENTIFIER_CHARACTER_REGEXP.test(code[match.index - 1])
|
|
283
273
|
});
|
|
284
274
|
match = MODULE_REFERENCE_SCAN_REGEXP.exec(code);
|
|
285
275
|
}
|
package/lib/DotenvPlugin.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
"use strict";
|
|
7
7
|
|
|
8
8
|
const FileSystemInfo = require("./FileSystemInfo");
|
|
9
|
+
const DotenvFileError = require("./errors/DotenvFileError");
|
|
9
10
|
const { join } = require("./util/fs");
|
|
10
11
|
|
|
11
12
|
/** @import { DotenvPluginOptions } from "../declarations/WebpackOptions" */
|
|
@@ -155,8 +156,8 @@ function expandValue(value, processEnv, runningParsed) {
|
|
|
155
156
|
const opMatch = expression.match(opRegex);
|
|
156
157
|
const splitter = opMatch ? opMatch[0] : null;
|
|
157
158
|
|
|
158
|
-
|
|
159
|
-
|
|
159
|
+
// `split(null)` splits on the string "null", cutting up names containing it
|
|
160
|
+
const r = splitter ? expression.split(splitter) : [expression];
|
|
160
161
|
|
|
161
162
|
/** @type {string} */
|
|
162
163
|
let defaultValue;
|
|
@@ -235,16 +236,21 @@ function expand(options) {
|
|
|
235
236
|
/**
|
|
236
237
|
* Format environment variables as DefinePlugin definitions
|
|
237
238
|
* @param {Env} env environment variables
|
|
238
|
-
* @returns {Record<string, string>} formatted definitions
|
|
239
|
+
* @returns {Record<string, string | Env>} formatted definitions
|
|
239
240
|
*/
|
|
240
241
|
const envToDefinitions = (env) => {
|
|
241
|
-
const definitions = /** @type {Record<string, string>} */ ({});
|
|
242
|
+
const definitions = /** @type {Record<string, string | Env>} */ ({});
|
|
243
|
+
// one nested definition rather than a `import.meta.env.<key>` per key: a
|
|
244
|
+
// dotted key would otherwise read back as a nested object, not as the key
|
|
245
|
+
const importMetaEnv = /** @type {Env} */ (Object.create(null));
|
|
242
246
|
|
|
243
247
|
for (const [key, value] of Object.entries(env)) {
|
|
244
248
|
const defValue = JSON.stringify(value);
|
|
249
|
+
// `process.env` stays flat — it must not shadow the real one at runtime
|
|
245
250
|
definitions[`process.env.${key}`] = defValue;
|
|
246
|
-
|
|
251
|
+
importMetaEnv[key] = defValue;
|
|
247
252
|
}
|
|
253
|
+
definitions["import.meta.env"] = importMetaEnv;
|
|
248
254
|
|
|
249
255
|
return definitions;
|
|
250
256
|
};
|
|
@@ -296,6 +302,8 @@ class DotenvPlugin {
|
|
|
296
302
|
|
|
297
303
|
/** @type {undefined | InstanceType<Snapshot>} */
|
|
298
304
|
let snapshot;
|
|
305
|
+
/** @type {undefined | DotenvFileError} */
|
|
306
|
+
let loadError;
|
|
299
307
|
|
|
300
308
|
const cache = compiler.getCache(PLUGIN_NAME);
|
|
301
309
|
const identifier = JSON.stringify(
|
|
@@ -304,16 +312,31 @@ class DotenvPlugin {
|
|
|
304
312
|
const itemCache = cache.getItemCache(identifier, null);
|
|
305
313
|
|
|
306
314
|
compiler.hooks.beforeCompile.tapPromise(PLUGIN_NAME, async () => {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
315
|
+
loadError = undefined;
|
|
316
|
+
try {
|
|
317
|
+
const { parsed, snapshot: newSnapshot } = dir
|
|
318
|
+
? await this._loadEnv(compiler, itemCache, dir)
|
|
319
|
+
: { parsed: {} };
|
|
320
|
+
const env = this._getEnv(prefixes, parsed);
|
|
321
|
+
|
|
322
|
+
definePlugin.definitions = envToDefinitions(env || {});
|
|
323
|
+
snapshot = newSnapshot;
|
|
324
|
+
} catch (err) {
|
|
325
|
+
// reported on the compilation so watch mode recovers when it is fixed
|
|
326
|
+
if (!(err instanceof DotenvFileError)) throw err;
|
|
327
|
+
loadError = err;
|
|
328
|
+
definePlugin.definitions = envToDefinitions({});
|
|
329
|
+
snapshot = undefined;
|
|
330
|
+
}
|
|
314
331
|
});
|
|
315
332
|
|
|
316
333
|
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
|
|
334
|
+
if (loadError) {
|
|
335
|
+
compilation.errors.push(loadError);
|
|
336
|
+
compilation.fileDependencies.add(
|
|
337
|
+
/** @type {string} */ (loadError.file)
|
|
338
|
+
);
|
|
339
|
+
}
|
|
317
340
|
if (snapshot) {
|
|
318
341
|
compilation.fileDependencies.addAll(snapshot.getFileIterable());
|
|
319
342
|
compilation.missingDependencies.addAll(snapshot.getMissingIterable());
|
|
@@ -369,7 +392,12 @@ class DotenvPlugin {
|
|
|
369
392
|
fileDependencies.push(filePath);
|
|
370
393
|
return content;
|
|
371
394
|
},
|
|
372
|
-
() => {
|
|
395
|
+
(err) => {
|
|
396
|
+
const code = /** @type {NodeJS.ErrnoException} */ (err).code;
|
|
397
|
+
// only an absent file is normal; anything else is a real fault
|
|
398
|
+
if (code !== "ENOENT" && code !== "ENOTDIR") {
|
|
399
|
+
throw new DotenvFileError(filePath, err);
|
|
400
|
+
}
|
|
373
401
|
// File doesn't exist, add to missingDependencies (this is normal)
|
|
374
402
|
missingDependencies.push(filePath);
|
|
375
403
|
return "";
|
|
@@ -345,10 +345,16 @@ class FlagDependencyUsagePlugin {
|
|
|
345
345
|
if (oldItem === undefined || Array.isArray(oldItem)) {
|
|
346
346
|
exportsMap.set(key, item);
|
|
347
347
|
} else {
|
|
348
|
+
// An unset flag means "allowed", so merge on `!== false`:
|
|
349
|
+
// `undefined && false` reads back as allowed.
|
|
348
350
|
exportsMap.set(key, {
|
|
349
351
|
name: item.name,
|
|
350
|
-
canMangle:
|
|
351
|
-
|
|
352
|
+
canMangle:
|
|
353
|
+
item.canMangle !== false &&
|
|
354
|
+
oldItem.canMangle !== false,
|
|
355
|
+
canInline:
|
|
356
|
+
item.canInline !== false &&
|
|
357
|
+
oldItem.canInline !== false
|
|
352
358
|
});
|
|
353
359
|
}
|
|
354
360
|
}
|
package/lib/NormalModule.js
CHANGED
|
@@ -109,7 +109,6 @@ const getModuleBuildError = memoize(() => require("./errors/ModuleBuildError"));
|
|
|
109
109
|
* BuildMeta,
|
|
110
110
|
* CodeGenerationContext,
|
|
111
111
|
* CodeGenerationResult,
|
|
112
|
-
* CodeGenerationResultData,
|
|
113
112
|
* ConcatenationBailoutReasonContext,
|
|
114
113
|
* KnownBuildInfo,
|
|
115
114
|
* LibIdentOptions,
|
|
@@ -119,7 +118,6 @@ const getModuleBuildError = memoize(() => require("./errors/ModuleBuildError"));
|
|
|
119
118
|
* NeedBuildCallback,
|
|
120
119
|
* BuildCallback,
|
|
121
120
|
* RuntimeRequirements,
|
|
122
|
-
* Sources,
|
|
123
121
|
* SourceType,
|
|
124
122
|
* SourceTypes
|
|
125
123
|
* } from "./Module"
|
|
@@ -728,11 +726,6 @@ class NormalModule extends Module {
|
|
|
728
726
|
this._sideEffectsStateGraph = undefined;
|
|
729
727
|
/** @type {ConnectionState | undefined} */
|
|
730
728
|
this._sideEffectsStateValue = undefined;
|
|
731
|
-
/**
|
|
732
|
-
* @private
|
|
733
|
-
* @type {CodeGenerationResultData}
|
|
734
|
-
*/
|
|
735
|
-
this._codeGeneratorData = new Map();
|
|
736
729
|
}
|
|
737
730
|
|
|
738
731
|
/**
|
|
@@ -1892,10 +1885,19 @@ class NormalModule extends Module {
|
|
|
1892
1885
|
runtimeRequirements.add(RuntimeGlobals.thisAsExports);
|
|
1893
1886
|
}
|
|
1894
1887
|
|
|
1895
|
-
|
|
1888
|
+
/** @type {CodeGenerationResult} */
|
|
1889
|
+
const resultEntry = {
|
|
1890
|
+
sources: new Map(),
|
|
1891
|
+
runtimeRequirements,
|
|
1892
|
+
data: undefined,
|
|
1893
|
+
hash: undefined
|
|
1894
|
+
};
|
|
1895
|
+
|
|
1896
|
+
const getData = () => {
|
|
1897
|
+
if (resultEntry.data === undefined) resultEntry.data = new Map();
|
|
1898
|
+
return resultEntry.data;
|
|
1899
|
+
};
|
|
1896
1900
|
|
|
1897
|
-
/** @type {Sources} */
|
|
1898
|
-
const sources = new Map();
|
|
1899
1901
|
for (const type of sourceTypes || chunkGraph.getModuleSourceTypes(this)) {
|
|
1900
1902
|
// TODO webpack@6 make generateError required
|
|
1901
1903
|
const generator =
|
|
@@ -1930,17 +1932,10 @@ class NormalModule extends Module {
|
|
|
1930
1932
|
});
|
|
1931
1933
|
|
|
1932
1934
|
if (source) {
|
|
1933
|
-
sources.set(type, new CachedSource(source));
|
|
1935
|
+
resultEntry.sources.set(type, new CachedSource(source));
|
|
1934
1936
|
}
|
|
1935
1937
|
}
|
|
1936
1938
|
|
|
1937
|
-
/** @type {CodeGenerationResult} */
|
|
1938
|
-
const resultEntry = {
|
|
1939
|
-
sources,
|
|
1940
|
-
runtimeRequirements,
|
|
1941
|
-
data: this._codeGeneratorData,
|
|
1942
|
-
hash: undefined
|
|
1943
|
-
};
|
|
1944
1939
|
return resultEntry;
|
|
1945
1940
|
}
|
|
1946
1941
|
|
|
@@ -2116,7 +2111,6 @@ class NormalModule extends Module {
|
|
|
2116
2111
|
write(this.error);
|
|
2117
2112
|
write(this._lastSuccessfulBuildMeta);
|
|
2118
2113
|
write(this._forceBuild);
|
|
2119
|
-
write(this._codeGeneratorData);
|
|
2120
2114
|
write(this.hot);
|
|
2121
2115
|
super.serialize(context);
|
|
2122
2116
|
}
|
|
@@ -2160,7 +2154,6 @@ class NormalModule extends Module {
|
|
|
2160
2154
|
this.error = read();
|
|
2161
2155
|
this._lastSuccessfulBuildMeta = read();
|
|
2162
2156
|
this._forceBuild = read();
|
|
2163
|
-
this._codeGeneratorData = read();
|
|
2164
2157
|
this.hot = read();
|
|
2165
2158
|
super.deserialize(context);
|
|
2166
2159
|
}
|
package/lib/RuntimePlugin.js
CHANGED
|
@@ -189,6 +189,9 @@ const TREE_DEPENDENCIES = {
|
|
|
189
189
|
RuntimeGlobals.makeNamespaceObject,
|
|
190
190
|
RuntimeGlobals.require
|
|
191
191
|
],
|
|
192
|
+
[RuntimeGlobals.deferredModuleAsyncTransitiveDependencies]: [
|
|
193
|
+
RuntimeGlobals.asyncModule
|
|
194
|
+
],
|
|
192
195
|
[RuntimeGlobals.makeOptimizedDeferredNamespaceObject]: [
|
|
193
196
|
RuntimeGlobals.require
|
|
194
197
|
],
|
package/lib/RuntimeTemplate.js
CHANGED
|
@@ -55,6 +55,7 @@ const {
|
|
|
55
55
|
const getCssModulesPlugin = memoize(() => require("./css/CssModulesPlugin"));
|
|
56
56
|
// `Compilation` requires this module, so its stage constants are read lazily.
|
|
57
57
|
const getCompilation = memoize(() => require("./Compilation"));
|
|
58
|
+
const getExternalModule = memoize(() => require("./ExternalModule"));
|
|
58
59
|
|
|
59
60
|
/**
|
|
60
61
|
* @typedef {object} ChunkAssetNaming
|
|
@@ -422,6 +423,11 @@ function getGlobalObject(definition) {
|
|
|
422
423
|
return `Object(${trimmed})`;
|
|
423
424
|
}
|
|
424
425
|
|
|
426
|
+
// An async external is a promise, not a module record with an evaluating state.
|
|
427
|
+
const isAsyncExternal = (/** @type {Module} */ module) =>
|
|
428
|
+
Boolean(/** @type {BuildMeta} */ (module.buildMeta).async) &&
|
|
429
|
+
module instanceof getExternalModule();
|
|
430
|
+
|
|
425
431
|
class RuntimeTemplate {
|
|
426
432
|
/**
|
|
427
433
|
* Creates an instance of RuntimeTemplate.
|
|
@@ -1984,6 +1990,9 @@ class RuntimeTemplate {
|
|
|
1984
1990
|
(m) => chunkGraph.getModuleId(m)
|
|
1985
1991
|
).filter((id) => id !== null);
|
|
1986
1992
|
if (asyncDeps.length) {
|
|
1993
|
+
runtimeRequirements.add(
|
|
1994
|
+
RuntimeGlobals.deferredModuleAsyncTransitiveDependencies
|
|
1995
|
+
);
|
|
1987
1996
|
if (header) {
|
|
1988
1997
|
appending = `.then(${this.basicFunction(
|
|
1989
1998
|
"",
|
|
@@ -2220,11 +2229,14 @@ class RuntimeTemplate {
|
|
|
2220
2229
|
(dependency instanceof HarmonyImportDependency ||
|
|
2221
2230
|
dependency instanceof ImportDependency) &&
|
|
2222
2231
|
ImportPhaseUtils.isDefer(dependency.phase) &&
|
|
2223
|
-
!(
|
|
2232
|
+
!isAsyncExternal(module);
|
|
2224
2233
|
|
|
2225
2234
|
if (isModuleDeferred) {
|
|
2226
2235
|
/** @type {Set<Module>} */
|
|
2227
2236
|
const outgoingAsyncModules = getOutgoingAsyncModules(moduleGraph, module);
|
|
2237
|
+
// A module deferring itself is already evaluating, so awaiting it here
|
|
2238
|
+
// would deadlock; forcing the namespace throws instead.
|
|
2239
|
+
outgoingAsyncModules.delete(originModule);
|
|
2228
2240
|
|
|
2229
2241
|
importContent = `/* deferred harmony import */ ${optDeclaration}${importVar} = ${getOptimizedDeferredModule(
|
|
2230
2242
|
moduleId,
|
|
@@ -2309,7 +2321,7 @@ class RuntimeTemplate {
|
|
|
2309
2321
|
(dependency instanceof HarmonyImportDependency ||
|
|
2310
2322
|
dependency instanceof ImportDependency) &&
|
|
2311
2323
|
ImportPhaseUtils.isDefer(dependency.phase) &&
|
|
2312
|
-
!(
|
|
2324
|
+
!isAsyncExternal(module);
|
|
2313
2325
|
|
|
2314
2326
|
if (defaultInterop) {
|
|
2315
2327
|
// when the defaultInterop is used (when a ESM imports a CJS module),
|
|
@@ -32,16 +32,22 @@ const getOutgoingAsyncModules = (moduleGraph, module) => {
|
|
|
32
32
|
const outgoingConnectionMap =
|
|
33
33
|
moduleGraph.getOutgoingConnectionsByModule(module);
|
|
34
34
|
if (outgoingConnectionMap) {
|
|
35
|
-
|
|
35
|
+
// Walk the imports in source order: the spec gathers these from
|
|
36
|
+
// `[[RequestedModules]]`, and their evaluation order is observable.
|
|
37
|
+
for (const dependency of module.dependencies) {
|
|
38
|
+
if (!(dependency instanceof HarmonyImportDependency)) continue;
|
|
39
|
+
const referenced = moduleGraph.getModule(dependency);
|
|
40
|
+
if (!referenced || seen.has(referenced)) continue;
|
|
41
|
+
const connections = outgoingConnectionMap.get(referenced);
|
|
36
42
|
if (
|
|
43
|
+
connections &&
|
|
37
44
|
connections.some(
|
|
38
45
|
(c) =>
|
|
39
46
|
c.dependency instanceof HarmonyImportDependency &&
|
|
40
47
|
c.isTargetActive(undefined)
|
|
41
|
-
)
|
|
42
|
-
module
|
|
48
|
+
)
|
|
43
49
|
) {
|
|
44
|
-
g(
|
|
50
|
+
g(referenced);
|
|
45
51
|
}
|
|
46
52
|
}
|
|
47
53
|
}
|
package/lib/config/defaults.js
CHANGED
|
@@ -179,6 +179,7 @@ const {
|
|
|
179
179
|
* portableRecords: NonNullable<Optimization["portableRecords"]>,
|
|
180
180
|
* realContentHash: NonNullable<Optimization["realContentHash"]>,
|
|
181
181
|
* minimize: NonNullable<Optimization["minimize"]>,
|
|
182
|
+
* minimizeOptions: NonNullable<Optimization["minimizeOptions"]>,
|
|
182
183
|
* minimizer: NonNullable<Exclude<Optimization["minimizer"], "...">>,
|
|
183
184
|
* nodeEnv: NonNullable<Optimization["nodeEnv"]>,
|
|
184
185
|
* }} OptimizationNormalizedWithDefaults
|
|
@@ -1747,6 +1748,8 @@ const applyOutputDefaults = (
|
|
|
1747
1748
|
"generator",
|
|
1748
1749
|
() => tp && optimistic(/** @type {boolean | undefined} */ (tp.generator))
|
|
1749
1750
|
);
|
|
1751
|
+
// No `topLevelAwait` here: the option is held back from the patch release,
|
|
1752
|
+
// so nothing derives it from `tp` yet. Reapply by reverting #21881.
|
|
1750
1753
|
F(
|
|
1751
1754
|
environment,
|
|
1752
1755
|
"forOf",
|
|
@@ -2463,20 +2466,28 @@ const applyOptimizationDefaults = (
|
|
|
2463
2466
|
D(optimization, "mangleWasmImports", false);
|
|
2464
2467
|
D(optimization, "portableRecords", records);
|
|
2465
2468
|
D(optimization, "realContentHash", production);
|
|
2466
|
-
|
|
2467
|
-
//
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2469
|
+
// A plugin assigning the object shorthand in `apply()` runs after
|
|
2470
|
+
// normalization: it replaces `minimizeOptions`, keeping `minimize` boolean.
|
|
2471
|
+
const minimizeAssignedInApply = /** @type {unknown} */ (
|
|
2472
|
+
optimization.minimize
|
|
2473
|
+
);
|
|
2474
|
+
if (typeof minimizeAssignedInApply === "object") {
|
|
2475
|
+
optimization.minimizeOptions = /** @type {OptimizationMinimizeOptions} */ (
|
|
2476
|
+
minimizeAssignedInApply
|
|
2477
|
+
);
|
|
2478
|
+
optimization.minimize = true;
|
|
2472
2479
|
}
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
+
D(optimization, "minimize", production);
|
|
2481
|
+
F(optimization, "minimizeOptions", () => ({}));
|
|
2482
|
+
const minimizeOptions =
|
|
2483
|
+
/** @type {NonNullable<Optimization["minimizeOptions"]>} */
|
|
2484
|
+
(optimization.minimizeOptions);
|
|
2485
|
+
if (optimization.minimize) {
|
|
2486
|
+
// Canonicalize the per-asset-type options: the JS minimizer's defaults
|
|
2487
|
+
// become visible in the resolved config rather than hidden in the wiring.
|
|
2488
|
+
F(minimizeOptions, "javascript", () => ({ compress: { passes: 2 } }));
|
|
2489
|
+
F(minimizeOptions, "css", () => ({}));
|
|
2490
|
+
F(minimizeOptions, "html", () => ({}));
|
|
2480
2491
|
}
|
|
2481
2492
|
A(optimization, "minimizer", () => [
|
|
2482
2493
|
{
|
|
@@ -2501,10 +2512,9 @@ const applyOptimizationDefaults = (
|
|
|
2501
2512
|
compiler
|
|
2502
2513
|
);
|
|
2503
2514
|
|
|
2504
|
-
//
|
|
2505
|
-
// object here: `false` disables a type, an object is its options.
|
|
2515
|
+
// Per asset type: `false` disables that type, an object is its options.
|
|
2506
2516
|
const minimizeByType = /** @type {OptimizationMinimizeOptions} */ (
|
|
2507
|
-
compiler.options.optimization.
|
|
2517
|
+
compiler.options.optimization.minimizeOptions
|
|
2508
2518
|
);
|
|
2509
2519
|
const terserOptions = minimizeByType.javascript || {
|
|
2510
2520
|
compress: { passes: 2 }
|
|
@@ -331,7 +331,14 @@ const getNormalizedWebpackOptions = (config) => ({
|
|
|
331
331
|
cacheGroups: cloneObject(splitChunks.cacheGroups)
|
|
332
332
|
}
|
|
333
333
|
),
|
|
334
|
-
|
|
334
|
+
// TODO webpack 6: normalize `minimize` to the per-asset-type object and
|
|
335
|
+
// drop `minimizeOptions` — a breaking change for what plugins read back.
|
|
336
|
+
minimize:
|
|
337
|
+
typeof optimization.minimize === "object" ? true : optimization.minimize,
|
|
338
|
+
minimizeOptions: getNormalizedOptimizationMinimizeOptions(
|
|
339
|
+
optimization.minimize,
|
|
340
|
+
optimization.minimizeOptions
|
|
341
|
+
),
|
|
335
342
|
minimizer:
|
|
336
343
|
optimization.minimizer !== undefined
|
|
337
344
|
? /** @type {OptimizationNormalized["minimizer"]} */ (
|
|
@@ -612,15 +619,18 @@ const getNormalizedEntryStatic = (entry) => {
|
|
|
612
619
|
};
|
|
613
620
|
|
|
614
621
|
/**
|
|
615
|
-
* Gets
|
|
616
|
-
*
|
|
622
|
+
* Gets the per-asset-type minimize options. `minimize` itself stays a boolean,
|
|
623
|
+
* and its object form is a shorthand an explicit `minimizeOptions` overrides.
|
|
617
624
|
* @param {Optimization["minimize"]} minimize minimize option
|
|
618
|
-
* @
|
|
625
|
+
* @param {Optimization["minimizeOptions"]} minimizeOptions minimizeOptions option
|
|
626
|
+
* @returns {OptimizationNormalized["minimizeOptions"]} normalized minimize options
|
|
619
627
|
*/
|
|
620
|
-
const
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
628
|
+
const getNormalizedOptimizationMinimizeOptions = (
|
|
629
|
+
minimize,
|
|
630
|
+
minimizeOptions
|
|
631
|
+
) => {
|
|
632
|
+
if (minimizeOptions !== undefined) return cloneObject(minimizeOptions);
|
|
633
|
+
if (typeof minimize !== "object") return;
|
|
624
634
|
return cloneObject(minimize);
|
|
625
635
|
};
|
|
626
636
|
|
|
@@ -20,6 +20,7 @@ const HarmonyImportGuard = require("./HarmonyImportGuard");
|
|
|
20
20
|
const ModuleDependency = require("./ModuleDependency");
|
|
21
21
|
|
|
22
22
|
/** @import { ReplaceSource } from "webpack-sources" */
|
|
23
|
+
/** @import ConcatenationScope from "../ConcatenationScope" */
|
|
23
24
|
/**
|
|
24
25
|
* @import {
|
|
25
26
|
* GetConditionFn,
|
|
@@ -30,6 +31,7 @@ const ModuleDependency = require("./ModuleDependency");
|
|
|
30
31
|
/** @import { DependencyTemplateContext } from "../DependencyTemplate" */
|
|
31
32
|
/** @import Module from "../Module" */
|
|
32
33
|
/** @import ModuleGraph from "../ModuleGraph" */
|
|
34
|
+
/** @import ModuleGraphConnection from "../ModuleGraphConnection" */
|
|
33
35
|
/** @import { Range } from "../javascript/JavascriptParser" */
|
|
34
36
|
/** @import { UsedByExports } from "../optimize/InnerGraph" */
|
|
35
37
|
/** @import { RuntimeSpec } from "../util/runtime" */
|
|
@@ -200,6 +202,19 @@ class CommonJsRequireDependency extends ModuleDependency {
|
|
|
200
202
|
return concatenateCommonJsModules && this._canConcatenate;
|
|
201
203
|
}
|
|
202
204
|
|
|
205
|
+
/**
|
|
206
|
+
* @param {ModuleGraphConnection} connection the active connection of this dependency
|
|
207
|
+
* @param {ConcatenationScope} concatenationScope the concatenation scope
|
|
208
|
+
* @returns {boolean} true when the call becomes a module reference
|
|
209
|
+
*/
|
|
210
|
+
rendersAsConcatenatedReference(connection, concatenationScope) {
|
|
211
|
+
return (
|
|
212
|
+
this._canConcatenate &&
|
|
213
|
+
this.valueRange !== undefined &&
|
|
214
|
+
concatenationScope.isModuleInScope(connection.module)
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
|
|
203
218
|
/**
|
|
204
219
|
* Serializes this instance into the provided serializer context.
|
|
205
220
|
* @param {ObjectSerializerContext} context context
|
|
@@ -278,9 +293,9 @@ CommonJsRequireDependency.Template = class CommonJsRequireDependencyTemplate ext
|
|
|
278
293
|
if (
|
|
279
294
|
connection &&
|
|
280
295
|
concatenationScope !== undefined &&
|
|
281
|
-
dep.
|
|
282
|
-
concatenationScope.isModuleInScope(connection.module)
|
|
296
|
+
dep.rendersAsConcatenatedReference(connection, concatenationScope)
|
|
283
297
|
) {
|
|
298
|
+
const valueRange = /** @type {Range} */ (dep.valueRange);
|
|
284
299
|
let content = concatenationScope.createModuleReference(
|
|
285
300
|
connection.module,
|
|
286
301
|
{
|
|
@@ -300,8 +315,7 @@ CommonJsRequireDependency.Template = class CommonJsRequireDependencyTemplate ext
|
|
|
300
315
|
);
|
|
301
316
|
content = `${RuntimeGlobals.constructRequire}(${content})`;
|
|
302
317
|
}
|
|
303
|
-
source.replace(
|
|
304
|
-
concatenationScope.registerReplacedRequire(dep.valueRange);
|
|
318
|
+
source.replace(valueRange[0], valueRange[1] - 1, content);
|
|
305
319
|
return;
|
|
306
320
|
}
|
|
307
321
|
const importedModule = /** @type {Module} */ (moduleGraph.getModule(dep));
|