webpack 5.107.0 → 5.107.1
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/lib/BannerPlugin.js +3 -4
- package/lib/Chunk.js +21 -25
- package/lib/ChunkGroup.js +57 -15
- package/lib/Compilation.js +33 -11
- package/lib/EvalSourceMapDevToolPlugin.js +0 -1
- package/lib/ExportsInfo.js +30 -34
- package/lib/ExternalModule.js +15 -11
- package/lib/ExternalModuleFactoryPlugin.js +2 -1
- package/lib/Module.js +1 -1
- package/lib/ModuleNotFoundError.js +10 -0
- package/lib/ModuleSourceTypeConstants.js +24 -22
- package/lib/NormalModule.js +106 -46
- package/lib/NormalModuleFactory.js +38 -26
- package/lib/RuntimePlugin.js +1 -1
- package/lib/SourceMapDevToolPlugin.js +250 -49
- package/lib/Template.js +1 -1
- package/lib/TemplatedPathPlugin.js +22 -4
- package/lib/asset/AssetBytesGenerator.js +6 -6
- package/lib/asset/AssetGenerator.js +14 -14
- package/lib/asset/AssetModulesPlugin.js +3 -7
- package/lib/asset/AssetSourceGenerator.js +6 -6
- package/lib/css/CssModulesPlugin.js +2 -2
- package/lib/dependencies/CommonJsImportsParserPlugin.js +108 -1
- package/lib/dependencies/CssUrlDependency.js +3 -2
- package/lib/dependencies/HarmonyDetectionParserPlugin.js +21 -1
- package/lib/dependencies/HtmlScriptSrcDependency.js +264 -25
- package/lib/dependencies/HtmlSourceDependency.js +3 -2
- package/lib/html/HtmlModulesPlugin.js +1 -5
- package/lib/html/walkHtmlTokens.js +641 -125
- package/lib/index.js +2 -0
- package/lib/javascript/JavascriptModulesPlugin.js +2 -2
- package/lib/optimize/SideEffectsFlagPlugin.js +1 -2
- package/lib/optimize/SplitChunksPlugin.js +4 -4
- package/lib/runtime/AutoPublicPathRuntimeModule.js +3 -3
- package/lib/runtime/GetChunkFilenameRuntimeModule.js +5 -5
- package/lib/sharing/ConsumeSharedPlugin.js +2 -8
- package/lib/sharing/ProvideSharedPlugin.js +4 -4
- package/lib/wasm-async/AsyncWebAssemblyModulesPlugin.js +1 -2
- package/package.json +3 -3
- package/schemas/WebpackOptions.check.js +1 -1
- package/schemas/WebpackOptions.json +11 -9
- package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
- package/schemas/plugins/container/ContainerReferencePlugin.json +1 -0
- package/schemas/plugins/container/ExternalsType.check.js +1 -1
- package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
- package/schemas/plugins/container/ModuleFederationPlugin.json +1 -0
- package/types.d.ts +355 -144
|
@@ -30,7 +30,7 @@ const { makePathsAbsolute } = require("./util/identifier");
|
|
|
30
30
|
/** @typedef {import("./Compiler")} Compiler */
|
|
31
31
|
/** @typedef {import("./Module")} Module */
|
|
32
32
|
/** @typedef {import("./NormalModule").RawSourceMap} RawSourceMap */
|
|
33
|
-
/** @typedef {import("./TemplatedPathPlugin").TemplatePath}
|
|
33
|
+
/** @typedef {import("./TemplatedPathPlugin").TemplatePath} SourceMappingURLComment */
|
|
34
34
|
/** @typedef {import("./util/fs").OutputFileSystem} OutputFileSystem */
|
|
35
35
|
|
|
36
36
|
/**
|
|
@@ -70,6 +70,91 @@ const resetRegexpState = (regexp) => {
|
|
|
70
70
|
*/
|
|
71
71
|
const quoteMeta = (str) => str.replace(METACHARACTERS_REGEXP, "\\$&");
|
|
72
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Compilation-scoped registry of original asset sources for multi-plugin
|
|
75
|
+
* cooperation. The first SourceMapDevToolPlugin instance to see a file pins a
|
|
76
|
+
* reference to the asset's still-unwrapped {@link Source} object; later
|
|
77
|
+
* instances whose `asset.source.sourceAndMap()` would now return `null` (the
|
|
78
|
+
* earlier instance replaced the asset with a `RawSource`) can re-extract the
|
|
79
|
+
* map from this pinned reference. We keep the registry on a module-scoped
|
|
80
|
+
* `WeakMap` so the entries are reclaimed automatically when the compilation
|
|
81
|
+
* itself becomes unreachable; we never store anything on the compilation
|
|
82
|
+
* object directly.
|
|
83
|
+
*
|
|
84
|
+
* Stashing the `Source` object itself rather than an extracted map keeps the
|
|
85
|
+
* fast path free of cloning and source-map serialization work — the
|
|
86
|
+
* extraction only happens if a subsequent plugin actually needs the map.
|
|
87
|
+
* @type {WeakMap<Compilation, Map<string, Source>>}
|
|
88
|
+
*/
|
|
89
|
+
const originalSourceRegistry = new WeakMap();
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Returns (creating if necessary) the per-compilation registry of original
|
|
93
|
+
* asset {@link Source} objects.
|
|
94
|
+
* @param {Compilation} compilation compilation
|
|
95
|
+
* @returns {Map<string, Source>} registry
|
|
96
|
+
*/
|
|
97
|
+
const getOriginalSourceRegistry = (compilation) => {
|
|
98
|
+
let registry = originalSourceRegistry.get(compilation);
|
|
99
|
+
if (registry === undefined) {
|
|
100
|
+
registry = new Map();
|
|
101
|
+
originalSourceRegistry.set(compilation, registry);
|
|
102
|
+
}
|
|
103
|
+
return registry;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Extracts source and source map from a Source object, falling back to a
|
|
108
|
+
* registered original source for assets that another SourceMapDevToolPlugin
|
|
109
|
+
* instance has already wrapped (whose internal map is now `null`).
|
|
110
|
+
*
|
|
111
|
+
* The returned source is read from the asset as it currently stands — that way
|
|
112
|
+
* any `sourceMappingURL` comments appended by earlier plugin instances survive
|
|
113
|
+
* — while the map is taken from the pinned original Source when the current
|
|
114
|
+
* one no longer carries it.
|
|
115
|
+
* @param {string} file file name
|
|
116
|
+
* @param {Source} asset source object as currently held by the compilation
|
|
117
|
+
* @param {MapOptions} options map extraction options
|
|
118
|
+
* @param {Map<string, Source>} registry compilation-scoped original-source registry
|
|
119
|
+
* @returns {{ source: string, sourceMap: RawSourceMap } | undefined} extracted pair or `undefined` when no map is recoverable
|
|
120
|
+
*/
|
|
121
|
+
const extractSourceAndMap = (file, asset, options, registry) => {
|
|
122
|
+
/** @type {string | Buffer} */
|
|
123
|
+
let source;
|
|
124
|
+
/** @type {null | RawSourceMap} */
|
|
125
|
+
let sourceMap;
|
|
126
|
+
if (asset.sourceAndMap) {
|
|
127
|
+
const sourceAndMap = asset.sourceAndMap(options);
|
|
128
|
+
source = sourceAndMap.source;
|
|
129
|
+
sourceMap = sourceAndMap.map;
|
|
130
|
+
} else {
|
|
131
|
+
source = asset.source();
|
|
132
|
+
sourceMap = asset.map(options);
|
|
133
|
+
}
|
|
134
|
+
// Bail before touching the registry if we can't return a usable string
|
|
135
|
+
// source — pinning a non-string-producing asset would only waste the slot.
|
|
136
|
+
if (typeof source !== "string") return;
|
|
137
|
+
if (sourceMap) {
|
|
138
|
+
// The current asset still owns the original map — pin a reference so
|
|
139
|
+
// that a later plugin instance (which will see a rewrapped asset
|
|
140
|
+
// without a map) can recover it on demand.
|
|
141
|
+
if (!registry.has(file)) registry.set(file, asset);
|
|
142
|
+
} else {
|
|
143
|
+
// The current asset (typically a `RawSource` left by an earlier
|
|
144
|
+
// SourceMapDevToolPlugin instance) has no internal map. Re-extract
|
|
145
|
+
// the map from the original Source we pinned earlier. We keep using
|
|
146
|
+
// `source` from the current asset so that any prior wrappers (e.g.
|
|
147
|
+
// appended sourceMappingURL comments) are preserved.
|
|
148
|
+
const original = registry.get(file);
|
|
149
|
+
if (!original) return;
|
|
150
|
+
sourceMap = original.sourceAndMap
|
|
151
|
+
? original.sourceAndMap(options).map
|
|
152
|
+
: original.map(options);
|
|
153
|
+
if (!sourceMap) return;
|
|
154
|
+
}
|
|
155
|
+
return { source, sourceMap };
|
|
156
|
+
};
|
|
157
|
+
|
|
73
158
|
/**
|
|
74
159
|
* Creating {@link SourceMapTask} for given file
|
|
75
160
|
* @param {string} file current compiled file
|
|
@@ -78,6 +163,7 @@ const quoteMeta = (str) => str.replace(METACHARACTERS_REGEXP, "\\$&");
|
|
|
78
163
|
* @param {MapOptions} options source map options
|
|
79
164
|
* @param {Compilation} compilation compilation instance
|
|
80
165
|
* @param {ItemCacheFacade} cacheItem cache item
|
|
166
|
+
* @param {Map<string, Source>} registry compilation-scoped original-source registry
|
|
81
167
|
* @returns {SourceMapTask | undefined} created task instance or `undefined`
|
|
82
168
|
*/
|
|
83
169
|
const getTaskForFile = (
|
|
@@ -86,24 +172,12 @@ const getTaskForFile = (
|
|
|
86
172
|
assetInfo,
|
|
87
173
|
options,
|
|
88
174
|
compilation,
|
|
89
|
-
cacheItem
|
|
175
|
+
cacheItem,
|
|
176
|
+
registry
|
|
90
177
|
) => {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
let sourceMap;
|
|
95
|
-
/**
|
|
96
|
-
* Check if asset can build source map
|
|
97
|
-
*/
|
|
98
|
-
if (asset.sourceAndMap) {
|
|
99
|
-
const sourceAndMap = asset.sourceAndMap(options);
|
|
100
|
-
sourceMap = sourceAndMap.map;
|
|
101
|
-
source = sourceAndMap.source;
|
|
102
|
-
} else {
|
|
103
|
-
sourceMap = asset.map(options);
|
|
104
|
-
source = asset.source();
|
|
105
|
-
}
|
|
106
|
-
if (!sourceMap || typeof source !== "string") return;
|
|
178
|
+
const extracted = extractSourceAndMap(file, asset, options, registry);
|
|
179
|
+
if (!extracted) return;
|
|
180
|
+
const { source, sourceMap } = extracted;
|
|
107
181
|
const context = compilation.options.context;
|
|
108
182
|
const root = compilation.compiler.root;
|
|
109
183
|
const cachedAbsolutify = makePathsAbsolute.bindContextCache(context, root);
|
|
@@ -117,7 +191,7 @@ const getTaskForFile = (
|
|
|
117
191
|
return {
|
|
118
192
|
file,
|
|
119
193
|
asset,
|
|
120
|
-
source,
|
|
194
|
+
source: /** @type {string} */ (source),
|
|
121
195
|
assetInfo,
|
|
122
196
|
sourceMap,
|
|
123
197
|
modules,
|
|
@@ -127,6 +201,29 @@ const getTaskForFile = (
|
|
|
127
201
|
|
|
128
202
|
const PLUGIN_NAME = "SourceMapDevToolPlugin";
|
|
129
203
|
|
|
204
|
+
/**
|
|
205
|
+
* Maps a configuration value (string, RegExp, function, nullish, or array of
|
|
206
|
+
* such) into a JSON-serializable form. Functions and RegExps are turned into
|
|
207
|
+
* their `.toString()` representation so that changes to inline callbacks
|
|
208
|
+
* invalidate caches; everything else is returned as-is so that the surrounding
|
|
209
|
+
* `JSON.stringify` does the escaping.
|
|
210
|
+
*
|
|
211
|
+
* The result is used through `JSON.stringify` to build cache identifiers, so
|
|
212
|
+
* we deliberately avoid any homemade `|` / `,` separators that could collide
|
|
213
|
+
* with characters appearing inside user-provided values such as `publicPath`,
|
|
214
|
+
* template strings, or `sourceRoot`.
|
|
215
|
+
* @param {EXPECTED_ANY} value option value
|
|
216
|
+
* @returns {EXPECTED_ANY} JSON-serializable representation
|
|
217
|
+
*/
|
|
218
|
+
const toCacheKeyValue = (value) => {
|
|
219
|
+
if (value === undefined || value === null) return value;
|
|
220
|
+
if (Array.isArray(value)) return value.map(toCacheKeyValue);
|
|
221
|
+
if (value instanceof RegExp || typeof value === "function") {
|
|
222
|
+
return value.toString();
|
|
223
|
+
}
|
|
224
|
+
return value;
|
|
225
|
+
};
|
|
226
|
+
|
|
130
227
|
class SourceMapDevToolPlugin {
|
|
131
228
|
/**
|
|
132
229
|
* Creates an instance of SourceMapDevToolPlugin.
|
|
@@ -136,7 +233,7 @@ class SourceMapDevToolPlugin {
|
|
|
136
233
|
constructor(options = {}) {
|
|
137
234
|
/** @type {undefined | null | false | string} */
|
|
138
235
|
this.sourceMapFilename = options.filename;
|
|
139
|
-
/** @type {false |
|
|
236
|
+
/** @type {false | SourceMappingURLComment} */
|
|
140
237
|
this.sourceMappingURLComment =
|
|
141
238
|
options.append === false
|
|
142
239
|
? false
|
|
@@ -153,6 +250,28 @@ class SourceMapDevToolPlugin {
|
|
|
153
250
|
this.namespace = options.namespace || "";
|
|
154
251
|
/** @type {SourceMapDevToolPluginOptions} */
|
|
155
252
|
this.options = options;
|
|
253
|
+
// Cache salt derived from output-affecting options, so that two
|
|
254
|
+
// SourceMapDevToolPlugin instances (or `devtool` + a plugin) operating
|
|
255
|
+
// on the same asset don't share a cache entry. We serialize via
|
|
256
|
+
// `JSON.stringify` rather than a homemade separator so that any
|
|
257
|
+
// special characters (e.g. `|` inside a publicPath or sourceRoot)
|
|
258
|
+
// can't accidentally make two different option sets collide.
|
|
259
|
+
/** @type {string} */
|
|
260
|
+
this._cacheSalt = JSON.stringify([
|
|
261
|
+
toCacheKeyValue(options.filename),
|
|
262
|
+
toCacheKeyValue(options.append),
|
|
263
|
+
toCacheKeyValue(this.moduleFilenameTemplate),
|
|
264
|
+
toCacheKeyValue(this.fallbackModuleFilenameTemplate),
|
|
265
|
+
toCacheKeyValue(this.namespace),
|
|
266
|
+
options.module !== false,
|
|
267
|
+
options.columns !== false,
|
|
268
|
+
Boolean(options.noSources),
|
|
269
|
+
Boolean(options.debugIds),
|
|
270
|
+
options.sourceRoot || "",
|
|
271
|
+
toCacheKeyValue(options.ignoreList),
|
|
272
|
+
options.publicPath || "",
|
|
273
|
+
options.fileContext || ""
|
|
274
|
+
]);
|
|
156
275
|
}
|
|
157
276
|
|
|
158
277
|
/**
|
|
@@ -195,6 +314,14 @@ class SourceMapDevToolPlugin {
|
|
|
195
314
|
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
|
|
196
315
|
new SourceMapDevToolModuleOptionsPlugin(options).apply(compilation);
|
|
197
316
|
|
|
317
|
+
// All SourceMapDevToolPlugin instances on the same compilation share
|
|
318
|
+
// a registry of pristine asset sources, so the second instance to
|
|
319
|
+
// run can still recover the original map after the first instance
|
|
320
|
+
// has replaced the asset with a `RawSource`. The registry lives on a
|
|
321
|
+
// module-scoped `WeakMap` keyed by compilation so it is released
|
|
322
|
+
// automatically and never pollutes the compilation object.
|
|
323
|
+
const originalSources = getOriginalSourceRegistry(compilation);
|
|
324
|
+
|
|
198
325
|
compilation.hooks.processAssets.tapAsync(
|
|
199
326
|
{
|
|
200
327
|
name: PLUGIN_NAME,
|
|
@@ -239,18 +366,22 @@ class SourceMapDevToolPlugin {
|
|
|
239
366
|
const asset =
|
|
240
367
|
/** @type {Readonly<Asset>} */
|
|
241
368
|
(compilation.getAsset(file));
|
|
242
|
-
if (asset.info.related && asset.info.related.sourceMap) {
|
|
243
|
-
fileIndex++;
|
|
244
|
-
return callback();
|
|
245
|
-
}
|
|
246
369
|
|
|
247
370
|
const chunk = fileToChunk.get(file);
|
|
248
371
|
const sourceMapNamespace = compilation.getPath(this.namespace, {
|
|
249
372
|
chunk
|
|
250
373
|
});
|
|
251
374
|
|
|
375
|
+
// The cache item identifier must include the per-instance
|
|
376
|
+
// salt so two SourceMapDevToolPlugin instances that target
|
|
377
|
+
// the same `file` don't collide in the persistent cache —
|
|
378
|
+
// they'd otherwise write different content to the same key
|
|
379
|
+
// and invalidate every pack on each build. We encode via
|
|
380
|
+
// `JSON.stringify` so that special characters (e.g. `|`)
|
|
381
|
+
// in an asset filename can't be spoofed to collide with the
|
|
382
|
+
// salt portion of the identifier.
|
|
252
383
|
const cacheItem = cache.getItemCache(
|
|
253
|
-
file,
|
|
384
|
+
JSON.stringify([file, this._cacheSalt]),
|
|
254
385
|
cache.mergeEtags(
|
|
255
386
|
cache.getLazyHashedEtag(asset.source),
|
|
256
387
|
sourceMapNamespace
|
|
@@ -265,6 +396,16 @@ class SourceMapDevToolPlugin {
|
|
|
265
396
|
* If presented in cache, reassigns assets. Cache assets already have source maps.
|
|
266
397
|
*/
|
|
267
398
|
if (cacheEntry) {
|
|
399
|
+
// Pin the still-unwrapped asset source in the registry
|
|
400
|
+
// before `compilation.updateAsset` replaces it. This is a
|
|
401
|
+
// pointer assignment — no source-map extraction work — and
|
|
402
|
+
// it lets a subsequent SourceMapDevToolPlugin instance
|
|
403
|
+
// extract the original map on demand even though the
|
|
404
|
+
// persistent cache hit lets us skip processing here.
|
|
405
|
+
if (!originalSources.has(file)) {
|
|
406
|
+
originalSources.set(file, asset.source);
|
|
407
|
+
}
|
|
408
|
+
|
|
268
409
|
const { assets, assetsInfo } = cacheEntry;
|
|
269
410
|
for (const cachedFile of Object.keys(assets)) {
|
|
270
411
|
if (cachedFile === file) {
|
|
@@ -313,7 +454,8 @@ class SourceMapDevToolPlugin {
|
|
|
313
454
|
columns: options.columns
|
|
314
455
|
},
|
|
315
456
|
compilation,
|
|
316
|
-
cacheItem
|
|
457
|
+
cacheItem,
|
|
458
|
+
originalSources
|
|
317
459
|
);
|
|
318
460
|
|
|
319
461
|
if (task) {
|
|
@@ -446,12 +588,21 @@ class SourceMapDevToolPlugin {
|
|
|
446
588
|
"attach SourceMap"
|
|
447
589
|
);
|
|
448
590
|
|
|
449
|
-
const moduleFilenames =
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
591
|
+
const moduleFilenames =
|
|
592
|
+
/** @type {string[]} */
|
|
593
|
+
(modules.map((m) => moduleToSourceNameMapping.get(m)));
|
|
594
|
+
// We deliberately do NOT mutate `sourceMap` in place: the
|
|
595
|
+
// task's `sourceMap` reference may be shared with a
|
|
596
|
+
// `SourceMapSource` whose internal map cache is the same
|
|
597
|
+
// object (webpack-sources keeps it cached). A second
|
|
598
|
+
// `SourceMapDevToolPlugin` instance that reads the original
|
|
599
|
+
// source through the registry would otherwise see our
|
|
600
|
+
// rewrites. Instead we build a fresh `outputSourceMap` for
|
|
601
|
+
// the .map file and leave the original alone.
|
|
602
|
+
/** @type {number[] | undefined} */
|
|
603
|
+
let ignoreList;
|
|
453
604
|
if (options.ignoreList) {
|
|
454
|
-
const
|
|
605
|
+
const list = moduleFilenames.reduce(
|
|
455
606
|
/** @type {(acc: number[], sourceName: string, idx: number) => number[]} */ (
|
|
456
607
|
(acc, sourceName, idx) => {
|
|
457
608
|
const rule = /** @type {Rules} */ (
|
|
@@ -467,35 +618,29 @@ class SourceMapDevToolPlugin {
|
|
|
467
618
|
),
|
|
468
619
|
[]
|
|
469
620
|
);
|
|
470
|
-
if (
|
|
471
|
-
sourceMap.ignoreList = ignoreList;
|
|
472
|
-
}
|
|
621
|
+
if (list.length > 0) ignoreList = list;
|
|
473
622
|
}
|
|
474
623
|
|
|
475
|
-
if (options.noSources) {
|
|
476
|
-
sourceMap.sourcesContent = undefined;
|
|
477
|
-
}
|
|
478
|
-
sourceMap.sourceRoot = options.sourceRoot || "";
|
|
479
|
-
sourceMap.file = file;
|
|
480
624
|
const usesContentHash =
|
|
481
625
|
sourceMapFilename &&
|
|
482
626
|
CONTENT_HASH_DETECT_REGEXP.test(sourceMapFilename);
|
|
483
627
|
|
|
484
628
|
resetRegexpState(CONTENT_HASH_DETECT_REGEXP);
|
|
485
629
|
|
|
630
|
+
let outputFile = file;
|
|
486
631
|
// If SourceMap and asset uses contenthash, avoid a circular dependency by hiding hash in `file`
|
|
487
632
|
if (usesContentHash && task.assetInfo.contenthash) {
|
|
488
633
|
const contenthash = task.assetInfo.contenthash;
|
|
489
634
|
const pattern = Array.isArray(contenthash)
|
|
490
635
|
? contenthash.map(quoteMeta).join("|")
|
|
491
636
|
: quoteMeta(contenthash);
|
|
492
|
-
|
|
637
|
+
outputFile = outputFile.replace(
|
|
493
638
|
new RegExp(pattern, "g"),
|
|
494
639
|
(m) => "x".repeat(m.length)
|
|
495
640
|
);
|
|
496
641
|
}
|
|
497
642
|
|
|
498
|
-
/** @type {false |
|
|
643
|
+
/** @type {false | SourceMappingURLComment} */
|
|
499
644
|
let currentSourceMappingURLComment = sourceMappingURLComment;
|
|
500
645
|
const cssExtensionDetected =
|
|
501
646
|
CSS_EXTENSION_DETECT_REGEXP.test(file);
|
|
@@ -512,18 +657,48 @@ class SourceMapDevToolPlugin {
|
|
|
512
657
|
);
|
|
513
658
|
}
|
|
514
659
|
|
|
660
|
+
/** @type {string | undefined} */
|
|
661
|
+
let debugIdValue;
|
|
515
662
|
if (options.debugIds) {
|
|
516
|
-
const debugId = generateDebugId(source,
|
|
517
|
-
|
|
663
|
+
const debugId = generateDebugId(source, outputFile);
|
|
664
|
+
debugIdValue = debugId;
|
|
518
665
|
|
|
519
666
|
const debugIdComment = `\n//# debugId=${debugId}`;
|
|
520
|
-
currentSourceMappingURLComment
|
|
521
|
-
currentSourceMappingURLComment
|
|
522
|
-
|
|
523
|
-
|
|
667
|
+
if (currentSourceMappingURLComment === false) {
|
|
668
|
+
currentSourceMappingURLComment = debugIdComment;
|
|
669
|
+
} else if (
|
|
670
|
+
typeof currentSourceMappingURLComment === "function"
|
|
671
|
+
) {
|
|
672
|
+
// Wrap the user's append function so the debug-id
|
|
673
|
+
// comment is prepended at call time. Template-string
|
|
674
|
+
// concatenation would coerce the function to a string
|
|
675
|
+
// and lose its dynamic behavior.
|
|
676
|
+
const wrappedFn = currentSourceMappingURLComment;
|
|
677
|
+
currentSourceMappingURLComment = (pathData, assetInfo) =>
|
|
678
|
+
`${debugIdComment}${wrappedFn(pathData, assetInfo)}`;
|
|
679
|
+
} else {
|
|
680
|
+
currentSourceMappingURLComment = `${debugIdComment}${currentSourceMappingURLComment}`;
|
|
681
|
+
}
|
|
524
682
|
}
|
|
525
683
|
|
|
526
|
-
|
|
684
|
+
/** @type {RawSourceMap} */
|
|
685
|
+
const outputSourceMap = {
|
|
686
|
+
...sourceMap,
|
|
687
|
+
sources: moduleFilenames,
|
|
688
|
+
sourceRoot: options.sourceRoot || "",
|
|
689
|
+
file: outputFile
|
|
690
|
+
};
|
|
691
|
+
if (ignoreList !== undefined) {
|
|
692
|
+
outputSourceMap.ignoreList = ignoreList;
|
|
693
|
+
}
|
|
694
|
+
if (options.noSources) {
|
|
695
|
+
outputSourceMap.sourcesContent = undefined;
|
|
696
|
+
}
|
|
697
|
+
if (debugIdValue !== undefined) {
|
|
698
|
+
outputSourceMap.debugId = debugIdValue;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
const sourceMapString = JSON.stringify(outputSourceMap);
|
|
527
702
|
if (sourceMapFilename) {
|
|
528
703
|
const filename = file;
|
|
529
704
|
const sourceMapContentHash = usesContentHash
|
|
@@ -567,8 +742,34 @@ class SourceMapDevToolPlugin {
|
|
|
567
742
|
})
|
|
568
743
|
);
|
|
569
744
|
}
|
|
745
|
+
// Preserve any existing related.sourceMap entries from
|
|
746
|
+
// earlier SourceMapDevToolPlugin runs on the same asset so
|
|
747
|
+
// that all generated maps remain discoverable via asset
|
|
748
|
+
// info (the schema allows string or string[]).
|
|
749
|
+
const existingSourceMap =
|
|
750
|
+
task.assetInfo.related &&
|
|
751
|
+
task.assetInfo.related.sourceMap;
|
|
752
|
+
/** @type {string | string[]} */
|
|
753
|
+
let relatedSourceMap;
|
|
754
|
+
if (
|
|
755
|
+
existingSourceMap === undefined ||
|
|
756
|
+
existingSourceMap === null
|
|
757
|
+
) {
|
|
758
|
+
relatedSourceMap = sourceMapFile;
|
|
759
|
+
} else if (Array.isArray(existingSourceMap)) {
|
|
760
|
+
relatedSourceMap = existingSourceMap.includes(
|
|
761
|
+
sourceMapFile
|
|
762
|
+
)
|
|
763
|
+
? existingSourceMap
|
|
764
|
+
: [...existingSourceMap, sourceMapFile];
|
|
765
|
+
} else {
|
|
766
|
+
relatedSourceMap =
|
|
767
|
+
existingSourceMap === sourceMapFile
|
|
768
|
+
? existingSourceMap
|
|
769
|
+
: [existingSourceMap, sourceMapFile];
|
|
770
|
+
}
|
|
570
771
|
const assetInfo = {
|
|
571
|
-
related: { sourceMap:
|
|
772
|
+
related: { sourceMap: relatedSourceMap }
|
|
572
773
|
};
|
|
573
774
|
assets[file] = asset;
|
|
574
775
|
assetsInfo[file] = assetInfo;
|
package/lib/Template.js
CHANGED
|
@@ -63,7 +63,7 @@ const MATCH_PADDED_HYPHENS_REPLACE_REGEX = /^-|-$/g;
|
|
|
63
63
|
* Defines the render manifest entry templated type used by this module.
|
|
64
64
|
* @typedef {object} RenderManifestEntryTemplated
|
|
65
65
|
* @property {() => Source} render
|
|
66
|
-
* @property {
|
|
66
|
+
* @property {string | import("./TemplatedPathPlugin").TemplatePathFn<EXPECTED_ANY>} filenameTemplate
|
|
67
67
|
* @property {PathData=} pathOptions
|
|
68
68
|
* @property {AssetInfo=} info
|
|
69
69
|
* @property {string} identifier
|
|
@@ -18,6 +18,8 @@ const getMimeTypes = memoize(() => require("./util/mimeTypes"));
|
|
|
18
18
|
/** @typedef {import("./ChunkGraph").ModuleId} ModuleId */
|
|
19
19
|
/** @typedef {import("./Compilation").AssetInfo} AssetInfo */
|
|
20
20
|
/** @typedef {import("./Compilation").PathData} PathData */
|
|
21
|
+
/** @typedef {import("./Compilation").PathDataChunk} PathDataChunk */
|
|
22
|
+
/** @typedef {import("./Compilation").PathDataModule} PathDataModule */
|
|
21
23
|
/** @typedef {import("./Compiler")} Compiler */
|
|
22
24
|
|
|
23
25
|
const REGEXP = /\[\\*([\w:]+)\\*\]/g;
|
|
@@ -138,13 +140,29 @@ const deprecated = (fn, message, code) => {
|
|
|
138
140
|
);
|
|
139
141
|
};
|
|
140
142
|
|
|
141
|
-
/**
|
|
142
|
-
|
|
143
|
+
/**
|
|
144
|
+
* Callback used to compute a path from contextual data. The type parameter
|
|
145
|
+
* narrows the `pathData` shape when the caller knows it operates in a chunk
|
|
146
|
+
* (`PathDataChunk`) or module (`PathDataModule`) context — defaults to the
|
|
147
|
+
* fully-optional `PathData` for backward compatibility.
|
|
148
|
+
* @template {PathData} [T=PathData]
|
|
149
|
+
* @typedef {(pathData: T, assetInfo?: AssetInfo) => string} TemplatePathFn
|
|
150
|
+
*/
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Either a raw template string (e.g. `"[name].[contenthash].js"`) or a
|
|
154
|
+
* generic `TemplatePathFn`. Method signatures that need to thread a narrowed
|
|
155
|
+
* `PathData` shape spell the function side out as `TemplatePathFn<T>`
|
|
156
|
+
* directly — `TemplatePath` itself stays a plain alias so local JSDoc
|
|
157
|
+
* re-imports keep a single shared identity.
|
|
158
|
+
* @typedef {string | TemplatePathFn} TemplatePath
|
|
159
|
+
*/
|
|
143
160
|
|
|
144
161
|
/**
|
|
145
162
|
* Returns the interpolated path.
|
|
146
|
-
* @
|
|
147
|
-
* @param {
|
|
163
|
+
* @template {PathData} [T=PathData]
|
|
164
|
+
* @param {string | TemplatePathFn<T>} path the raw path
|
|
165
|
+
* @param {T} data context data
|
|
148
166
|
* @param {AssetInfo=} assetInfo extra info about the asset (will be written to)
|
|
149
167
|
* @returns {string} the interpolated path
|
|
150
168
|
*/
|
|
@@ -9,11 +9,11 @@ const { RawSource } = require("webpack-sources");
|
|
|
9
9
|
const ConcatenationScope = require("../ConcatenationScope");
|
|
10
10
|
const Generator = require("../Generator");
|
|
11
11
|
const {
|
|
12
|
+
ASSET_URL_TYPE,
|
|
13
|
+
ASSET_URL_TYPES,
|
|
12
14
|
CSS_TYPE,
|
|
13
|
-
CSS_URL_TYPE,
|
|
14
|
-
CSS_URL_TYPES,
|
|
15
15
|
HTML_TYPE,
|
|
16
|
-
|
|
16
|
+
JAVASCRIPT_AND_ASSET_URL_TYPES,
|
|
17
17
|
JAVASCRIPT_TYPE,
|
|
18
18
|
JAVASCRIPT_TYPES,
|
|
19
19
|
NO_TYPES
|
|
@@ -80,7 +80,7 @@ class AssetSourceGenerator extends Generator {
|
|
|
80
80
|
}
|
|
81
81
|
return new RawSource(sourceContent);
|
|
82
82
|
}
|
|
83
|
-
case
|
|
83
|
+
case ASSET_URL_TYPE: {
|
|
84
84
|
if (!originalSource) {
|
|
85
85
|
return null;
|
|
86
86
|
}
|
|
@@ -151,9 +151,9 @@ class AssetSourceGenerator extends Generator {
|
|
|
151
151
|
sourceTypes.has(JAVASCRIPT_TYPE) &&
|
|
152
152
|
(sourceTypes.has(CSS_TYPE) || sourceTypes.has(HTML_TYPE))
|
|
153
153
|
) {
|
|
154
|
-
return
|
|
154
|
+
return JAVASCRIPT_AND_ASSET_URL_TYPES;
|
|
155
155
|
} else if (sourceTypes.has(CSS_TYPE) || sourceTypes.has(HTML_TYPE)) {
|
|
156
|
-
return
|
|
156
|
+
return ASSET_URL_TYPES;
|
|
157
157
|
}
|
|
158
158
|
return JAVASCRIPT_TYPES;
|
|
159
159
|
}
|
|
@@ -10,15 +10,15 @@ const { RawSource } = require("webpack-sources");
|
|
|
10
10
|
const ConcatenationScope = require("../ConcatenationScope");
|
|
11
11
|
const Generator = require("../Generator");
|
|
12
12
|
const {
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
ASSET_AND_ASSET_URL_TYPES,
|
|
14
|
+
ASSET_AND_JAVASCRIPT_AND_ASSET_URL_TYPES,
|
|
15
15
|
ASSET_AND_JAVASCRIPT_TYPES,
|
|
16
16
|
ASSET_TYPES,
|
|
17
|
+
ASSET_URL_TYPE,
|
|
18
|
+
ASSET_URL_TYPES,
|
|
17
19
|
CSS_TYPE,
|
|
18
|
-
CSS_URL_TYPE,
|
|
19
|
-
CSS_URL_TYPES,
|
|
20
20
|
HTML_TYPE,
|
|
21
|
-
|
|
21
|
+
JAVASCRIPT_AND_ASSET_URL_TYPES,
|
|
22
22
|
JAVASCRIPT_TYPE,
|
|
23
23
|
JAVASCRIPT_TYPES,
|
|
24
24
|
NO_TYPES
|
|
@@ -373,7 +373,7 @@ class AssetGenerator extends Generator {
|
|
|
373
373
|
assetPath = JSON.stringify(path + filename);
|
|
374
374
|
} else if (
|
|
375
375
|
generatorOptions.publicPath !== undefined &&
|
|
376
|
-
type ===
|
|
376
|
+
type === ASSET_URL_TYPE
|
|
377
377
|
) {
|
|
378
378
|
const { path, info } = runtimeTemplate.compilation.getAssetPathWithInfo(
|
|
379
379
|
generatorOptions.publicPath,
|
|
@@ -394,7 +394,7 @@ class AssetGenerator extends Generator {
|
|
|
394
394
|
{ expr: RuntimeGlobals.publicPath },
|
|
395
395
|
filename
|
|
396
396
|
);
|
|
397
|
-
} else if (type ===
|
|
397
|
+
} else if (type === ASSET_URL_TYPE) {
|
|
398
398
|
const compilation = runtimeTemplate.compilation;
|
|
399
399
|
const path =
|
|
400
400
|
compilation.outputOptions.publicPath === "auto"
|
|
@@ -560,7 +560,7 @@ class AssetGenerator extends Generator {
|
|
|
560
560
|
/** @type {string} */
|
|
561
561
|
let content;
|
|
562
562
|
|
|
563
|
-
const needContent = type === JAVASCRIPT_TYPE || type ===
|
|
563
|
+
const needContent = type === JAVASCRIPT_TYPE || type === ASSET_URL_TYPE;
|
|
564
564
|
const data = getData ? getData() : undefined;
|
|
565
565
|
|
|
566
566
|
if (
|
|
@@ -613,7 +613,7 @@ class AssetGenerator extends Generator {
|
|
|
613
613
|
contentHash
|
|
614
614
|
);
|
|
615
615
|
|
|
616
|
-
if (data && (type === JAVASCRIPT_TYPE || type ===
|
|
616
|
+
if (data && (type === JAVASCRIPT_TYPE || type === ASSET_URL_TYPE)) {
|
|
617
617
|
data.set("url", { ...data.get("url"), [type]: assetPath });
|
|
618
618
|
}
|
|
619
619
|
|
|
@@ -657,7 +657,7 @@ class AssetGenerator extends Generator {
|
|
|
657
657
|
runtimeRequirements.add(RuntimeGlobals.module);
|
|
658
658
|
|
|
659
659
|
return new RawSource(`${module.moduleArgument}.exports = ${content};`);
|
|
660
|
-
} else if (type ===
|
|
660
|
+
} else if (type === ASSET_URL_TYPE) {
|
|
661
661
|
return null;
|
|
662
662
|
}
|
|
663
663
|
|
|
@@ -710,9 +710,9 @@ class AssetGenerator extends Generator {
|
|
|
710
710
|
sourceTypes.has(JAVASCRIPT_TYPE) &&
|
|
711
711
|
(sourceTypes.has(CSS_TYPE) || sourceTypes.has(HTML_TYPE))
|
|
712
712
|
) {
|
|
713
|
-
return
|
|
713
|
+
return JAVASCRIPT_AND_ASSET_URL_TYPES;
|
|
714
714
|
} else if (sourceTypes.has(CSS_TYPE) || sourceTypes.has(HTML_TYPE)) {
|
|
715
|
-
return
|
|
715
|
+
return ASSET_URL_TYPES;
|
|
716
716
|
}
|
|
717
717
|
return JAVASCRIPT_TYPES;
|
|
718
718
|
}
|
|
@@ -725,9 +725,9 @@ class AssetGenerator extends Generator {
|
|
|
725
725
|
sourceTypes.has(JAVASCRIPT_TYPE) &&
|
|
726
726
|
(sourceTypes.has(CSS_TYPE) || sourceTypes.has(HTML_TYPE))
|
|
727
727
|
) {
|
|
728
|
-
return
|
|
728
|
+
return ASSET_AND_JAVASCRIPT_AND_ASSET_URL_TYPES;
|
|
729
729
|
} else if (sourceTypes.has(CSS_TYPE) || sourceTypes.has(HTML_TYPE)) {
|
|
730
|
-
return
|
|
730
|
+
return ASSET_AND_ASSET_URL_TYPES;
|
|
731
731
|
}
|
|
732
732
|
return ASSET_AND_JAVASCRIPT_TYPES;
|
|
733
733
|
}
|
|
@@ -20,13 +20,12 @@ const memoize = require("../util/memoize");
|
|
|
20
20
|
/** @typedef {import("../../declarations/WebpackOptions").AssetGeneratorDataUrl} AssetGeneratorDataUrl */
|
|
21
21
|
/** @typedef {import("../../declarations/WebpackOptions").AssetModuleOutputPath} AssetModuleOutputPath */
|
|
22
22
|
/** @typedef {import("../../declarations/WebpackOptions").RawPublicPath} RawPublicPath */
|
|
23
|
-
/** @typedef {import("../../declarations/WebpackOptions").
|
|
23
|
+
/** @typedef {import("../../declarations/WebpackOptions").AssetModuleFilename} AssetModuleFilename */
|
|
24
24
|
/** @typedef {import("../Compilation").AssetInfo} AssetInfo */
|
|
25
25
|
/** @typedef {import("../Compiler")} Compiler */
|
|
26
26
|
/** @typedef {import("../Module").BuildInfo} BuildInfo */
|
|
27
27
|
/** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */
|
|
28
28
|
/** @typedef {import("../NormalModule")} NormalModule */
|
|
29
|
-
/** @typedef {import("../NormalModule").NormalModuleCreateData} NormalModuleCreateData */
|
|
30
29
|
|
|
31
30
|
/**
|
|
32
31
|
* Returns definition.
|
|
@@ -98,10 +97,7 @@ class AssetModulesPlugin {
|
|
|
98
97
|
.for(type)
|
|
99
98
|
.tap(PLUGIN_NAME, (createData, _resolveData) => {
|
|
100
99
|
// TODO create the module via new AssetModule with its own properties
|
|
101
|
-
const module = new NormalModule(
|
|
102
|
-
/** @type {NormalModuleCreateData} */
|
|
103
|
-
(createData)
|
|
104
|
-
);
|
|
100
|
+
const module = new NormalModule(createData);
|
|
105
101
|
if (this.options.sideEffectFree) {
|
|
106
102
|
module.factoryMeta = { sideEffectFree: true };
|
|
107
103
|
}
|
|
@@ -227,7 +223,7 @@ class AssetModulesPlugin {
|
|
|
227
223
|
}
|
|
228
224
|
}
|
|
229
225
|
|
|
230
|
-
/** @type {undefined |
|
|
226
|
+
/** @type {undefined | AssetModuleFilename} */
|
|
231
227
|
let filename;
|
|
232
228
|
/** @type {undefined | RawPublicPath} */
|
|
233
229
|
let publicPath;
|