@depup/webpack 5.110.1-depup.0 → 5.110.3-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/changes.json +3 -3
- package/lib/ChunkGraph.js +20 -18
- package/lib/Compilation.js +1 -1
- package/lib/ConcatenationScope.js +25 -35
- package/lib/DotenvPlugin.js +41 -13
- package/lib/ExportsInfo.js +10 -0
- package/lib/FlagDependencyUsagePlugin.js +8 -2
- package/lib/NormalModule.js +13 -20
- package/lib/RuntimePlugin.js +3 -0
- package/lib/RuntimeTemplate.js +437 -432
- package/lib/async-modules/AsyncModuleHelpers.js +10 -4
- package/lib/config/defaults.js +26 -16
- package/lib/config/normalization.js +18 -8
- package/lib/css/CssLoadingRuntimeModule.js +32 -13
- package/lib/css/CssModulesPlugin.js +9 -17
- package/lib/css/data.js +13 -3
- package/lib/css/syntax.js +78 -10
- package/lib/dependencies/CommonJsRequireDependency.js +18 -4
- package/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +20 -7
- package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +10 -4
- package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +2 -0
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +143 -17
- package/lib/dependencies/HarmonyImportDependency.js +94 -41
- package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +93 -14
- package/lib/dependencies/HarmonyImportSideEffectDependency.js +114 -0
- package/lib/dependencies/HtmlEntryDependency.js +12 -2
- package/lib/dependencies/ImportContextDependency.js +43 -3
- package/lib/dependencies/ImportDependency.js +8 -29
- package/lib/dependencies/ImportParserPlugin.js +24 -14
- package/lib/dependencies/RequireHeaderDependency.js +20 -21
- package/lib/dependencies/WorkerAndWorkletPlugin.js +1 -0
- package/lib/dependencies/WorkerDependency.js +6 -12
- package/lib/dependencies/WorkletDependency.js +7 -11
- package/lib/dependencies/importOptionsCheck.js +47 -0
- package/lib/errors/DotenvFileError.js +29 -0
- package/lib/errors/ImportedBindingAssignmentError.js +30 -0
- package/lib/esm/ModuleChunkLoadingPlugin.js +6 -9
- package/lib/esm/ModuleChunkLoadingRuntimeModule.js +7 -1
- package/lib/html/HtmlModulesPlugin.js +84 -38
- package/lib/html/syntax.js +417 -169
- package/lib/javascript/JavascriptModulesPlugin.js +5 -10
- package/lib/loaders/LoaderRunner.js +33 -5
- package/lib/node/ReadFileCompileAsyncWasmPlugin.js +8 -15
- package/lib/optimize/ConcatenatedModule.js +46 -7
- package/lib/optimize/ConstExportsPlugin.js +5 -0
- package/lib/optimize/InlineExports.js +121 -0
- package/lib/optimize/RealContentHashPlugin.js +111 -35
- package/lib/prefetch/ResourceHintPlugin.js +12 -13
- package/lib/runtime/AsyncModuleRuntimeModule.js +5 -1
- package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +11 -1
- package/lib/schemes/HttpUriPlugin.js +22 -5
- package/lib/serialization/FileMiddleware.js +15 -2
- package/lib/typescript/TypeScriptPlugin.js +8 -10
- package/lib/util/ArrayQueue.js +3 -3
- package/lib/util/SourceProcessor.js +24 -8
- package/lib/util/URLAbsoluteSpecifier.js +3 -1
- package/lib/util/conventions.js +5 -1
- package/lib/util/createMappings.js +25 -3
- package/lib/util/internalSerializables.js +2 -0
- package/lib/util/removeBOM.js +82 -1
- package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +5 -3
- package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +5 -3
- package/lib/wasm-async/UniversalCompileAsyncWasmPlugin.js +7 -12
- package/lib/web/FetchCompileAsyncWasmPlugin.js +10 -6
- package/lib/web/FetchCompileWasmPlugin.js +4 -2
- package/package.json +7 -7
- package/schemas/WebpackOptions.check.js +1 -1
- package/schemas/WebpackOptions.json +9 -10
- package/types.d.ts +95 -27
|
@@ -130,6 +130,7 @@ module.exports = class HarmonyExportDependencyParserPlugin {
|
|
|
130
130
|
/** @type {HarmonySettings | undefined} */
|
|
131
131
|
(parser.getTagData(name, harmonySpecifierTag));
|
|
132
132
|
if (!settings || settings.ids.length !== 0) return;
|
|
133
|
+
settings.used = true;
|
|
133
134
|
if (ImportPhaseUtils.isDefer(settings.phase)) return;
|
|
134
135
|
const harmonyNamedExports = (parser.state.harmonyNamedExports =
|
|
135
136
|
parser.state.harmonyNamedExports || new Set());
|
|
@@ -255,6 +256,7 @@ module.exports = class HarmonyExportDependencyParserPlugin {
|
|
|
255
256
|
const settings =
|
|
256
257
|
/** @type {HarmonySettings} */
|
|
257
258
|
(parser.getTagData(id, harmonySpecifierTag));
|
|
259
|
+
if (settings) settings.used = true;
|
|
258
260
|
const harmonyNamedExports = (parser.state.harmonyNamedExports =
|
|
259
261
|
parser.state.harmonyNamedExports || new Set());
|
|
260
262
|
harmonyNamedExports.add(name);
|
|
@@ -135,6 +135,11 @@ class ExportMode {
|
|
|
135
135
|
/** @type {InstanceType<ExportInfo> | null} */
|
|
136
136
|
this.partialNamespaceExportInfo = null;
|
|
137
137
|
|
|
138
|
+
// for "reexport-undefined": the name resolves through a circular
|
|
139
|
+
// reexport chain rather than being absent from a non-harmony module
|
|
140
|
+
/** @type {boolean} */
|
|
141
|
+
this.circular = false;
|
|
142
|
+
|
|
138
143
|
// for "dynamic-reexport":
|
|
139
144
|
/** @type {ExportModeIgnored | null} */
|
|
140
145
|
this.ignored = null;
|
|
@@ -232,12 +237,28 @@ const isStarReexportBackToParent = (moduleGraph, exportInfo, parentModule) => {
|
|
|
232
237
|
}
|
|
233
238
|
};
|
|
234
239
|
|
|
240
|
+
/**
|
|
241
|
+
* Two `export *` sources are ambiguous for a name when they resolve to
|
|
242
|
+
* different bindings; a diamond re-export of the same binding is not.
|
|
243
|
+
* @param {ModuleGraph} moduleGraph module graph
|
|
244
|
+
* @param {InstanceType<ExportInfo>} previous export info of the star source that first provided the name
|
|
245
|
+
* @param {InstanceType<ExportInfo>} exportInfo export info of a later star source providing the same name
|
|
246
|
+
* @returns {boolean} true when the two sources provide different bindings
|
|
247
|
+
*/
|
|
248
|
+
const isAmbiguousWith = (moduleGraph, previous, exportInfo) => {
|
|
249
|
+
const previousBinding = previous.getTerminalBinding(moduleGraph);
|
|
250
|
+
if (!previousBinding) return false;
|
|
251
|
+
const binding = exportInfo.getTerminalBinding(moduleGraph);
|
|
252
|
+
if (!binding) return false;
|
|
253
|
+
return previousBinding !== binding;
|
|
254
|
+
};
|
|
255
|
+
|
|
235
256
|
/**
|
|
236
257
|
* Determine export assignments.
|
|
237
258
|
* @param {ModuleGraph} moduleGraph module graph
|
|
238
259
|
* @param {HarmonyExportImportedSpecifierDependency[]} dependencies dependencies
|
|
239
260
|
* @param {HarmonyExportImportedSpecifierDependency=} additionalDependency additional dependency
|
|
240
|
-
* @returns {{ names: ExportInfoName[], dependencyIndices: DependencyIndices }} result
|
|
261
|
+
* @returns {{ names: ExportInfoName[], dependencyIndices: DependencyIndices, conflicting: Set<ExportInfoName> | undefined }} result
|
|
241
262
|
*/
|
|
242
263
|
const determineExportAssignments = (
|
|
243
264
|
moduleGraph,
|
|
@@ -248,6 +269,10 @@ const determineExportAssignments = (
|
|
|
248
269
|
const names = new Set();
|
|
249
270
|
/** @type {DependencyIndices} */
|
|
250
271
|
const dependencyIndices = [];
|
|
272
|
+
/** @type {Map<ExportInfoName, InstanceType<ExportInfo>>} */
|
|
273
|
+
const firstProvider = new Map();
|
|
274
|
+
/** @type {Set<ExportInfoName> | undefined} */
|
|
275
|
+
let conflicting;
|
|
251
276
|
|
|
252
277
|
if (additionalDependency) {
|
|
253
278
|
dependencies = [...dependencies, additionalDependency];
|
|
@@ -265,24 +290,42 @@ const determineExportAssignments = (
|
|
|
265
290
|
if (otherImportedModule) {
|
|
266
291
|
const exportsInfo = moduleGraph.getExportsInfo(otherImportedModule);
|
|
267
292
|
for (const exportInfo of exportsInfo.exports) {
|
|
293
|
+
if (exportInfo.provided !== true || exportInfo.name === "default") {
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
if (names.has(exportInfo.name)) {
|
|
297
|
+
const previous =
|
|
298
|
+
/** @type {InstanceType<ExportInfo>} */
|
|
299
|
+
(firstProvider.get(exportInfo.name));
|
|
300
|
+
if (
|
|
301
|
+
isAmbiguousWith(moduleGraph, previous, exportInfo) &&
|
|
302
|
+
// A cyclic contribution resolves to nothing, so it never competes
|
|
303
|
+
// with the binding a sibling `export *` provides.
|
|
304
|
+
!(
|
|
305
|
+
parentModule &&
|
|
306
|
+
isStarReexportBackToParent(moduleGraph, exportInfo, parentModule)
|
|
307
|
+
)
|
|
308
|
+
) {
|
|
309
|
+
if (conflicting === undefined) conflicting = new Set();
|
|
310
|
+
conflicting.add(exportInfo.name);
|
|
311
|
+
}
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
268
314
|
if (
|
|
269
|
-
|
|
270
|
-
exportInfo
|
|
271
|
-
!names.has(exportInfo.name) &&
|
|
272
|
-
!(
|
|
273
|
-
parentModule &&
|
|
274
|
-
isStarReexportBackToParent(moduleGraph, exportInfo, parentModule)
|
|
275
|
-
)
|
|
315
|
+
parentModule &&
|
|
316
|
+
isStarReexportBackToParent(moduleGraph, exportInfo, parentModule)
|
|
276
317
|
) {
|
|
277
|
-
|
|
278
|
-
dependencyIndices[i] = names.size;
|
|
318
|
+
continue;
|
|
279
319
|
}
|
|
320
|
+
names.add(exportInfo.name);
|
|
321
|
+
firstProvider.set(exportInfo.name, exportInfo);
|
|
322
|
+
dependencyIndices[i] = names.size;
|
|
280
323
|
}
|
|
281
324
|
}
|
|
282
325
|
}
|
|
283
326
|
dependencyIndices.push(names.size);
|
|
284
327
|
|
|
285
|
-
return { names: [...names], dependencyIndices };
|
|
328
|
+
return { names: [...names], dependencyIndices, conflicting };
|
|
286
329
|
};
|
|
287
330
|
|
|
288
331
|
/**
|
|
@@ -396,6 +439,14 @@ const getMode = (moduleGraph, dep, runtimeKey) => {
|
|
|
396
439
|
mode.name = name;
|
|
397
440
|
break;
|
|
398
441
|
default:
|
|
442
|
+
// forwarding to a circular chain would recurse until the stack
|
|
443
|
+
// blows, so the name resolves to undefined like a missing one
|
|
444
|
+
if (exportInfo.hasCircularTarget(moduleGraph)) {
|
|
445
|
+
mode = new ExportMode("reexport-undefined");
|
|
446
|
+
mode.name = name;
|
|
447
|
+
mode.circular = true;
|
|
448
|
+
break;
|
|
449
|
+
}
|
|
399
450
|
mode = new ExportMode("normal-reexport");
|
|
400
451
|
mode.items = [
|
|
401
452
|
new NormalReexportItem(name, ids, exportInfo, false, false)
|
|
@@ -653,6 +704,12 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
|
|
|
653
704
|
/** @type {IgnoredExports} */
|
|
654
705
|
const ignoredExports = new Set(this.activeExports);
|
|
655
706
|
ignoredExports.add("default");
|
|
707
|
+
// An ambiguous name resolves to no binding at all, so no `export *` in this
|
|
708
|
+
// module may contribute it — not even the first one.
|
|
709
|
+
const conflicting = this._getConflictingStarExportNames(moduleGraph);
|
|
710
|
+
if (conflicting !== undefined) {
|
|
711
|
+
for (const name of conflicting) ignoredExports.add(name);
|
|
712
|
+
}
|
|
656
713
|
|
|
657
714
|
/** @type {Hidden | undefined} */
|
|
658
715
|
let hiddenExports;
|
|
@@ -858,6 +915,21 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
|
|
|
858
915
|
}
|
|
859
916
|
}
|
|
860
917
|
|
|
918
|
+
/**
|
|
919
|
+
* Names this module's `export *` sources provide with conflicting bindings.
|
|
920
|
+
* @param {ModuleGraph} moduleGraph the module graph
|
|
921
|
+
* @returns {Set<ExportInfoName> | undefined} ambiguous names, or nothing when there are none
|
|
922
|
+
*/
|
|
923
|
+
_getConflictingStarExportNames(moduleGraph) {
|
|
924
|
+
// Every `export *` carries the module's full star list; a lone one has
|
|
925
|
+
// nothing to be ambiguous with, so skip the walk.
|
|
926
|
+
if (!this.allStarExports) return;
|
|
927
|
+
const { dependencies } = this.allStarExports;
|
|
928
|
+
if (dependencies.length < 2) return;
|
|
929
|
+
return moduleGraph.cached(determineExportAssignments, dependencies)
|
|
930
|
+
.conflicting;
|
|
931
|
+
}
|
|
932
|
+
|
|
861
933
|
/**
|
|
862
934
|
* Discover active exports from other star exports.
|
|
863
935
|
* @param {ModuleGraph} moduleGraph the module graph
|
|
@@ -1059,10 +1131,54 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
|
|
|
1059
1131
|
*/
|
|
1060
1132
|
getWarnings(moduleGraph) {
|
|
1061
1133
|
const exportsPresence = this._getEffectiveExportPresenceLevel(moduleGraph);
|
|
1134
|
+
const circular =
|
|
1135
|
+
this._getCircularReexportPresenceLevel() === ExportPresenceModes.WARN
|
|
1136
|
+
? this._getCircularReexportErrors(moduleGraph)
|
|
1137
|
+
: undefined;
|
|
1062
1138
|
if (exportsPresence === ExportPresenceModes.WARN) {
|
|
1063
|
-
|
|
1139
|
+
const errors = this._getErrors(moduleGraph);
|
|
1140
|
+
if (!circular) return errors;
|
|
1141
|
+
return errors ? [...errors, ...circular] : circular;
|
|
1064
1142
|
}
|
|
1065
|
-
return
|
|
1143
|
+
return circular;
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
/**
|
|
1147
|
+
* Reporting level for a circular reexport chain. It skips the promotion to
|
|
1148
|
+
* an error that AUTO gives a strict harmony module — a cycle warns by
|
|
1149
|
+
* default — but an explicit setting still says whether and how to report.
|
|
1150
|
+
* @returns {ExportPresenceMode} effective mode
|
|
1151
|
+
*/
|
|
1152
|
+
_getCircularReexportPresenceLevel() {
|
|
1153
|
+
return this.exportPresenceMode === ExportPresenceModes.AUTO
|
|
1154
|
+
? ExportPresenceModes.WARN
|
|
1155
|
+
: this.exportPresenceMode;
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
/**
|
|
1159
|
+
* Returns errors for a name resolving through a circular reexport chain.
|
|
1160
|
+
* @param {ModuleGraph} moduleGraph module graph
|
|
1161
|
+
* @returns {WebpackError[] | undefined} errors
|
|
1162
|
+
*/
|
|
1163
|
+
_getCircularReexportErrors(moduleGraph) {
|
|
1164
|
+
const ids = this.getIds(moduleGraph);
|
|
1165
|
+
if (ids.length === 0 || !this.name) return;
|
|
1166
|
+
const parentModule = /** @type {Module} */ (
|
|
1167
|
+
moduleGraph.getParentModule(this)
|
|
1168
|
+
);
|
|
1169
|
+
const exportInfo = moduleGraph
|
|
1170
|
+
.getExportsInfo(parentModule)
|
|
1171
|
+
.getReadOnlyExportInfo(this.name);
|
|
1172
|
+
if (!exportInfo.hasCircularTarget(moduleGraph)) return;
|
|
1173
|
+
return [
|
|
1174
|
+
new HarmonyLinkingError(
|
|
1175
|
+
`export '${ids.join(".")}' (reexported as '${
|
|
1176
|
+
this.name
|
|
1177
|
+
}') is part of a circular reexport chain in '${
|
|
1178
|
+
this.userRequest
|
|
1179
|
+
}' and is undefined`
|
|
1180
|
+
)
|
|
1181
|
+
];
|
|
1066
1182
|
}
|
|
1067
1183
|
|
|
1068
1184
|
/**
|
|
@@ -1072,10 +1188,18 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
|
|
|
1072
1188
|
*/
|
|
1073
1189
|
getErrors(moduleGraph) {
|
|
1074
1190
|
const exportsPresence = this._getEffectiveExportPresenceLevel(moduleGraph);
|
|
1075
|
-
|
|
1076
|
-
|
|
1191
|
+
const errors =
|
|
1192
|
+
exportsPresence === ExportPresenceModes.ERROR
|
|
1193
|
+
? this._getErrors(moduleGraph)
|
|
1194
|
+
: null;
|
|
1195
|
+
if (
|
|
1196
|
+
this._getCircularReexportPresenceLevel() !== ExportPresenceModes.ERROR
|
|
1197
|
+
) {
|
|
1198
|
+
return errors;
|
|
1077
1199
|
}
|
|
1078
|
-
|
|
1200
|
+
const circular = this._getCircularReexportErrors(moduleGraph);
|
|
1201
|
+
if (!circular) return errors;
|
|
1202
|
+
return errors ? [...errors, ...circular] : circular;
|
|
1079
1203
|
}
|
|
1080
1204
|
|
|
1081
1205
|
/**
|
|
@@ -1429,7 +1553,9 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
|
|
|
1429
1553
|
initFragments.push(
|
|
1430
1554
|
this.getReexportFragment(
|
|
1431
1555
|
module,
|
|
1432
|
-
|
|
1556
|
+
mode.circular
|
|
1557
|
+
? "reexport circular"
|
|
1558
|
+
: "reexport non-default export from non-harmony",
|
|
1433
1559
|
moduleGraph
|
|
1434
1560
|
.getExportsInfo(module)
|
|
1435
1561
|
.getUsedName(/** @type {string} */ (mode.name), runtime),
|
|
@@ -11,11 +11,14 @@ const InitFragment = require("../InitFragment");
|
|
|
11
11
|
const Template = require("../Template");
|
|
12
12
|
const AwaitDependenciesInitFragment = require("../async-modules/AwaitDependenciesInitFragment");
|
|
13
13
|
const isGeneratorLowered = require("../async-modules/isGeneratorLowered");
|
|
14
|
+
const memoize = require("../util/memoize");
|
|
14
15
|
const { filterRuntime, mergeRuntime } = require("../util/runtime");
|
|
15
16
|
const HarmonyLinkingError = require("./HarmonyLinkingError");
|
|
16
17
|
const { ImportPhase, ImportPhaseUtils } = require("./ImportPhase");
|
|
17
18
|
const ModuleDependency = require("./ModuleDependency");
|
|
18
19
|
|
|
20
|
+
const getExternalModule = memoize(() => require("../ExternalModule"));
|
|
21
|
+
|
|
19
22
|
/** @import { ReplaceSource } from "webpack-sources" */
|
|
20
23
|
/**
|
|
21
24
|
* @import {
|
|
@@ -97,6 +100,31 @@ const getNonOptionalPart = (members, membersOptionals) => {
|
|
|
97
100
|
|
|
98
101
|
/** @typedef {string[]} Ids */
|
|
99
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Export names a lazy barrel still defers, so they are missing from its provided
|
|
105
|
+
* exports without being absent from the module.
|
|
106
|
+
* @param {Module} module the imported module
|
|
107
|
+
* @returns {Set<string> | true | undefined} deferred names, true when a deferred star re-export may provide any name, undefined when none
|
|
108
|
+
*/
|
|
109
|
+
const getDeferredExports = (module) => {
|
|
110
|
+
const factoryMeta = module.factoryMeta;
|
|
111
|
+
if (factoryMeta === undefined || !factoryMeta.sideEffectFree) return;
|
|
112
|
+
/** @type {Set<string> | undefined} */
|
|
113
|
+
let names;
|
|
114
|
+
for (const dep of module.dependencies) {
|
|
115
|
+
// TODO remove in webpack 6
|
|
116
|
+
// These may be missing on custom dependency types not extending the base Dependency
|
|
117
|
+
if (!("getLazyUntil" in dep) || !("isLazy" in dep)) continue;
|
|
118
|
+
if (!dep.isLazy()) continue;
|
|
119
|
+
const until = dep.getLazyUntil();
|
|
120
|
+
if (until === Dependency.LAZY_UNTIL_FALLBACK) return true;
|
|
121
|
+
if (until !== Dependency.LAZY_UNTIL_ID) continue;
|
|
122
|
+
if (names === undefined) names = new Set();
|
|
123
|
+
names.add(/** @type {string} */ (dep.getLazyName()));
|
|
124
|
+
}
|
|
125
|
+
return names;
|
|
126
|
+
};
|
|
127
|
+
|
|
100
128
|
class HarmonyImportDependency extends ModuleDependency {
|
|
101
129
|
/**
|
|
102
130
|
* Creates an instance of HarmonyImportDependency.
|
|
@@ -185,9 +213,14 @@ class HarmonyImportDependency extends ModuleDependency {
|
|
|
185
213
|
const importedModule = /** @type {Module} */ (moduleGraph.getModule(this));
|
|
186
214
|
const meta = moduleGraph.getMeta(module);
|
|
187
215
|
|
|
216
|
+
// An async external is a promise webpack awaits, not a module record with
|
|
217
|
+
// an evaluating state, so deferring its namespace would never throw.
|
|
188
218
|
const isDeferred =
|
|
189
219
|
ImportPhaseUtils.isDefer(this.phase) &&
|
|
190
|
-
!(
|
|
220
|
+
!(
|
|
221
|
+
/** @type {BuildMeta} */ (importedModule.buildMeta).async &&
|
|
222
|
+
importedModule instanceof getExternalModule()
|
|
223
|
+
);
|
|
191
224
|
|
|
192
225
|
const metaKey = isDeferred ? "deferredImportVarMap" : "importVarMap";
|
|
193
226
|
let importVarMap = meta[metaKey];
|
|
@@ -283,48 +316,63 @@ class HarmonyImportDependency extends ModuleDependency {
|
|
|
283
316
|
(exportsType !== "default-with-named" || ids[0] !== "default") &&
|
|
284
317
|
moduleGraph.isExportProvided(importedModule, ids) === false
|
|
285
318
|
) {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
319
|
+
const deferredExports = getDeferredExports(importedModule);
|
|
320
|
+
|
|
321
|
+
if (
|
|
322
|
+
deferredExports !== true &&
|
|
323
|
+
(deferredExports === undefined || !deferredExports.has(ids[0]))
|
|
324
|
+
) {
|
|
325
|
+
// We are sure that it's not provided
|
|
326
|
+
|
|
327
|
+
// Try to provide detailed info in the error message
|
|
328
|
+
let pos = 0;
|
|
329
|
+
let exportsInfo = moduleGraph.getExportsInfo(importedModule);
|
|
330
|
+
while (pos < ids.length && exportsInfo) {
|
|
331
|
+
const id = ids[pos++];
|
|
332
|
+
const exportInfo = exportsInfo.getReadOnlyExportInfo(id);
|
|
333
|
+
if (exportInfo.provided === false) {
|
|
334
|
+
// We are sure that it's not provided
|
|
335
|
+
let providedExports = exportsInfo.getProvidedExports();
|
|
336
|
+
// only the first level names the imported module itself
|
|
337
|
+
if (
|
|
338
|
+
pos === 1 &&
|
|
339
|
+
deferredExports !== undefined &&
|
|
340
|
+
Array.isArray(providedExports)
|
|
341
|
+
) {
|
|
342
|
+
providedExports = [...providedExports, ...deferredExports];
|
|
343
|
+
}
|
|
344
|
+
const moreInfo = !Array.isArray(providedExports)
|
|
345
|
+
? " (possible exports unknown)"
|
|
346
|
+
: providedExports.length === 0
|
|
347
|
+
? " (module has no exports)"
|
|
348
|
+
: ` (possible exports: ${providedExports.join(", ")})`;
|
|
349
|
+
return [
|
|
350
|
+
new HarmonyLinkingError(
|
|
351
|
+
`export ${ids
|
|
352
|
+
.slice(0, pos)
|
|
353
|
+
.map((id) => `'${id}'`)
|
|
354
|
+
.join(".")} ${additionalMessage} was not found in '${
|
|
355
|
+
this.userRequest
|
|
356
|
+
}'${moreInfo}`
|
|
357
|
+
)
|
|
358
|
+
];
|
|
359
|
+
}
|
|
360
|
+
exportsInfo =
|
|
361
|
+
/** @type {ExportsInfo} */
|
|
362
|
+
(exportInfo.getNestedExportsInfo());
|
|
312
363
|
}
|
|
313
|
-
exportsInfo =
|
|
314
|
-
/** @type {ExportsInfo} */
|
|
315
|
-
(exportInfo.getNestedExportsInfo());
|
|
316
|
-
}
|
|
317
364
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
365
|
+
// General error message
|
|
366
|
+
return [
|
|
367
|
+
new HarmonyLinkingError(
|
|
368
|
+
`export ${ids
|
|
369
|
+
.map((id) => `'${id}'`)
|
|
370
|
+
.join(".")} ${additionalMessage} was not found in '${
|
|
371
|
+
this.userRequest
|
|
372
|
+
}'`
|
|
373
|
+
)
|
|
374
|
+
];
|
|
375
|
+
}
|
|
328
376
|
}
|
|
329
377
|
}
|
|
330
378
|
switch (exportsType) {
|
|
@@ -468,8 +516,13 @@ HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate extends
|
|
|
468
516
|
}
|
|
469
517
|
|
|
470
518
|
const importStatement = dep.getImportStatement(false, templateContext);
|
|
519
|
+
// A module deferring itself is already evaluating: awaiting it would probe
|
|
520
|
+
// the deferred namespace and force the evaluation it must not trigger.
|
|
521
|
+
const isSelfDeferred =
|
|
522
|
+
ImportPhaseUtils.isDefer(dep.phase) && referencedModule === module;
|
|
471
523
|
if (
|
|
472
524
|
referencedModule &&
|
|
525
|
+
!isSelfDeferred &&
|
|
473
526
|
templateContext.moduleGraph.isAsync(referencedModule)
|
|
474
527
|
) {
|
|
475
528
|
templateContext.initFragments.push(
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
"use strict";
|
|
7
7
|
|
|
8
|
+
const ImportedBindingAssignmentError = require("../errors/ImportedBindingAssignmentError");
|
|
8
9
|
const WebpackError = require("../errors/WebpackError");
|
|
9
10
|
const getParserHooks = require("../hmr/parserHooks");
|
|
10
11
|
const {
|
|
@@ -43,6 +44,7 @@ const { ImportPhaseUtils, createGetImportPhase } = require("./ImportPhase");
|
|
|
43
44
|
* } from "../../declarations/WebpackOptions"
|
|
44
45
|
*/
|
|
45
46
|
/** @import Module from "../Module" */
|
|
47
|
+
/** @import { JavascriptModuleBuildInfo } from "../javascript/JavascriptModule" */
|
|
46
48
|
/**
|
|
47
49
|
* @import JavascriptParser, {
|
|
48
50
|
* ImportAttributes,
|
|
@@ -71,10 +73,24 @@ const EMPTY_ID_RANGES = [];
|
|
|
71
73
|
* @property {boolean} await
|
|
72
74
|
* @property {ImportAttributes=} attributes
|
|
73
75
|
* @property {ImportPhaseType} phase
|
|
76
|
+
* @property {boolean} used whether the binding is referenced anywhere
|
|
77
|
+
* @property {HarmonyImportSideEffectDependency | undefined} dependency the statement's own dependency
|
|
74
78
|
*/
|
|
75
79
|
|
|
76
80
|
const PLUGIN_NAME = "HarmonyImportDependencyParserPlugin";
|
|
77
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Records that an import binding is referenced, so it is not reported as an
|
|
84
|
+
* unused specifier naming a missing export.
|
|
85
|
+
* @param {HarmonySettings | undefined} settings settings of the referenced tag
|
|
86
|
+
* @returns {boolean} true when the reference was a harmony import specifier
|
|
87
|
+
*/
|
|
88
|
+
const markUsed = (settings) => {
|
|
89
|
+
if (!settings) return false;
|
|
90
|
+
settings.used = true;
|
|
91
|
+
return true;
|
|
92
|
+
};
|
|
93
|
+
|
|
78
94
|
/**
|
|
79
95
|
* Gets in operator harmony import info.
|
|
80
96
|
* @param {JavascriptParser} parser the parser
|
|
@@ -107,6 +123,7 @@ const getInOperatorHarmonyImportInfo = (parser, left, right) => {
|
|
|
107
123
|
if (!settings) {
|
|
108
124
|
return;
|
|
109
125
|
}
|
|
126
|
+
settings.used = true;
|
|
110
127
|
|
|
111
128
|
return {
|
|
112
129
|
leftPart,
|
|
@@ -125,7 +142,10 @@ const getInOperatorHarmonyImportInfo = (parser, left, right) => {
|
|
|
125
142
|
const findImportSpecifier = (parser, node) => {
|
|
126
143
|
switch (node.type) {
|
|
127
144
|
case "Identifier":
|
|
128
|
-
return
|
|
145
|
+
return markUsed(
|
|
146
|
+
/** @type {HarmonySettings | undefined} */
|
|
147
|
+
(parser.getTagData(node.name, harmonySpecifierTag))
|
|
148
|
+
);
|
|
129
149
|
case "UnaryExpression":
|
|
130
150
|
return findImportSpecifier(
|
|
131
151
|
parser,
|
|
@@ -213,6 +233,35 @@ class HarmonyImportDependencyParserPlugin {
|
|
|
213
233
|
this.options.sourceImport
|
|
214
234
|
);
|
|
215
235
|
|
|
236
|
+
// Parsers are reused across modules, so both are reset per program.
|
|
237
|
+
/** @type {HarmonySettings[]} */
|
|
238
|
+
const declaredSpecifiers = [];
|
|
239
|
+
/** @type {HarmonyImportSideEffectDependency | undefined} */
|
|
240
|
+
let lastSideEffectDependency;
|
|
241
|
+
|
|
242
|
+
parser.hooks.program.tap(PLUGIN_NAME, () => {
|
|
243
|
+
declaredSpecifiers.length = 0;
|
|
244
|
+
lastSideEffectDependency = undefined;
|
|
245
|
+
});
|
|
246
|
+
parser.hooks.finish.tap(PLUGIN_NAME, () => {
|
|
247
|
+
for (const settings of declaredSpecifiers) {
|
|
248
|
+
const dependency = settings.dependency;
|
|
249
|
+
if (dependency === undefined || settings.used) continue;
|
|
250
|
+
if (dependency.unusedSpecifiers === undefined) {
|
|
251
|
+
dependency.unusedSpecifiers = {
|
|
252
|
+
exportPresenceMode: this.exportPresenceMode,
|
|
253
|
+
specifiers: []
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
dependency.unusedSpecifiers.specifiers.push([
|
|
257
|
+
settings.ids,
|
|
258
|
+
settings.name
|
|
259
|
+
]);
|
|
260
|
+
}
|
|
261
|
+
declaredSpecifiers.length = 0;
|
|
262
|
+
lastSideEffectDependency = undefined;
|
|
263
|
+
});
|
|
264
|
+
|
|
216
265
|
/**
|
|
217
266
|
* Gets non optional member chain.
|
|
218
267
|
* @param {MemberExpression} node member expression
|
|
@@ -228,7 +277,10 @@ class HarmonyImportDependencyParserPlugin {
|
|
|
228
277
|
const expr = /** @type {Identifier} */ (expression);
|
|
229
278
|
if (
|
|
230
279
|
parser.isVariableDefined(expr.name) ||
|
|
231
|
-
|
|
280
|
+
markUsed(
|
|
281
|
+
/** @type {HarmonySettings | undefined} */
|
|
282
|
+
(parser.getTagData(expr.name, harmonySpecifierTag))
|
|
283
|
+
)
|
|
232
284
|
) {
|
|
233
285
|
return true;
|
|
234
286
|
}
|
|
@@ -267,6 +319,7 @@ class HarmonyImportDependencyParserPlugin {
|
|
|
267
319
|
);
|
|
268
320
|
sideEffectDep.loc = parser.getLocation(statement);
|
|
269
321
|
parser.state.module.addDependency(sideEffectDep);
|
|
322
|
+
lastSideEffectDependency = sideEffectDep;
|
|
270
323
|
return true;
|
|
271
324
|
});
|
|
272
325
|
parser.hooks.importSpecifier.tap(
|
|
@@ -274,18 +327,20 @@ class HarmonyImportDependencyParserPlugin {
|
|
|
274
327
|
(statement, source, id, name) => {
|
|
275
328
|
const ids = id === null ? [] : [id];
|
|
276
329
|
const phase = getImportPhase(parser, statement);
|
|
277
|
-
|
|
330
|
+
const settings = /** @type {HarmonySettings} */ ({
|
|
278
331
|
name,
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
332
|
+
source,
|
|
333
|
+
ids,
|
|
334
|
+
sourceOrder: parser.state.lastHarmonyImportOrder,
|
|
335
|
+
attributes: getImportAttributes(statement),
|
|
336
|
+
phase,
|
|
337
|
+
used: false,
|
|
338
|
+
dependency: lastSideEffectDependency
|
|
339
|
+
});
|
|
340
|
+
parser.tagVariable(name, harmonySpecifierTag, settings);
|
|
341
|
+
// The statement's dependency carries them, so a never-referenced
|
|
342
|
+
// one still resolves; a namespace import names no export.
|
|
343
|
+
if (ids.length !== 0) declaredSpecifiers.push(settings);
|
|
289
344
|
return true;
|
|
290
345
|
}
|
|
291
346
|
);
|
|
@@ -328,16 +383,37 @@ class HarmonyImportDependencyParserPlugin {
|
|
|
328
383
|
nameInfo &&
|
|
329
384
|
nameInfo.rootInfo instanceof VariableInfo &&
|
|
330
385
|
nameInfo.rootInfo.name &&
|
|
331
|
-
|
|
386
|
+
markUsed(
|
|
387
|
+
/** @type {HarmonySettings | undefined} */
|
|
388
|
+
(parser.getTagData(nameInfo.rootInfo.name, harmonySpecifierTag))
|
|
389
|
+
)
|
|
332
390
|
) {
|
|
333
391
|
return true;
|
|
334
392
|
}
|
|
335
393
|
}
|
|
336
394
|
);
|
|
395
|
+
// Concatenation would turn the binding into a plain local, losing the
|
|
396
|
+
// getter-only property whose write throws.
|
|
397
|
+
parser.hooks.assign.for(harmonySpecifierTag).tap(PLUGIN_NAME, (expr) => {
|
|
398
|
+
const settings = /** @type {HarmonySettings} */ (parser.currentTagData);
|
|
399
|
+
markUsed(settings);
|
|
400
|
+
/** @type {JavascriptModuleBuildInfo} */
|
|
401
|
+
(parser.state.module.buildInfo).moduleConcatenationBailout =
|
|
402
|
+
"assignment to an imported binding";
|
|
403
|
+
// A named import is written through the namespace's getter-only
|
|
404
|
+
// property, which throws on its own. A namespace one is the binding
|
|
405
|
+
// itself, and nothing webpack can emit for it throws, so report it.
|
|
406
|
+
if (settings.ids.length === 0) {
|
|
407
|
+
const error = new ImportedBindingAssignmentError(settings.name);
|
|
408
|
+
error.loc = parser.getLocation(expr);
|
|
409
|
+
parser.state.module.addError(error);
|
|
410
|
+
}
|
|
411
|
+
});
|
|
337
412
|
parser.hooks.expression
|
|
338
413
|
.for(harmonySpecifierTag)
|
|
339
414
|
.tap(PLUGIN_NAME, (expr) => {
|
|
340
415
|
const settings = /** @type {HarmonySettings} */ (parser.currentTagData);
|
|
416
|
+
settings.used = true;
|
|
341
417
|
|
|
342
418
|
const dep = new HarmonyImportSpecifierDependency(
|
|
343
419
|
settings.source,
|
|
@@ -376,6 +452,7 @@ class HarmonyImportDependencyParserPlugin {
|
|
|
376
452
|
const settings =
|
|
377
453
|
/** @type {HarmonySettings} */
|
|
378
454
|
(parser.currentTagData);
|
|
455
|
+
settings.used = true;
|
|
379
456
|
const nonOptionalMembers = getNonOptionalPart(
|
|
380
457
|
members,
|
|
381
458
|
membersOptionals
|
|
@@ -431,6 +508,7 @@ class HarmonyImportDependencyParserPlugin {
|
|
|
431
508
|
const settings = /** @type {HarmonySettings} */ (
|
|
432
509
|
parser.currentTagData
|
|
433
510
|
);
|
|
511
|
+
settings.used = true;
|
|
434
512
|
const nonOptionalMembers = getNonOptionalPart(
|
|
435
513
|
members,
|
|
436
514
|
membersOptionals
|
|
@@ -491,6 +569,7 @@ class HarmonyImportDependencyParserPlugin {
|
|
|
491
569
|
.for(harmonySpecifierTag)
|
|
492
570
|
.tap(PLUGIN_NAME, (expression, members) => {
|
|
493
571
|
const settings = /** @type {HarmonySettings} */ (parser.currentTagData);
|
|
572
|
+
settings.used = true;
|
|
494
573
|
if (!ImportPhaseUtils.isDefer(settings.phase)) return;
|
|
495
574
|
if (expression.operator !== "=") return;
|
|
496
575
|
if (members.length !== 1) return;
|