webpack 5.68.0 → 5.70.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.

Potentially problematic release.


This version of webpack might be problematic. Click here for more details.

Files changed (63) hide show
  1. package/lib/BannerPlugin.js +10 -4
  2. package/lib/ChunkGraph.js +1 -2
  3. package/lib/CleanPlugin.js +64 -18
  4. package/lib/Compilation.js +43 -17
  5. package/lib/ContextModule.js +90 -26
  6. package/lib/ContextModuleFactory.js +65 -21
  7. package/lib/EntryOptionPlugin.js +1 -0
  8. package/lib/ExportsInfo.js +4 -4
  9. package/lib/Generator.js +1 -0
  10. package/lib/ModuleHashingError.js +29 -0
  11. package/lib/NodeStuffPlugin.js +10 -0
  12. package/lib/NormalModule.js +21 -16
  13. package/lib/NormalModuleFactory.js +40 -35
  14. package/lib/ProgressPlugin.js +4 -5
  15. package/lib/RuntimeTemplate.js +1 -0
  16. package/lib/TemplatedPathPlugin.js +48 -23
  17. package/lib/WebpackOptionsApply.js +2 -0
  18. package/lib/asset/AssetGenerator.js +122 -33
  19. package/lib/buildChunkGraph.js +1 -1
  20. package/lib/cache/ResolverCachePlugin.js +89 -28
  21. package/lib/config/browserslistTargetHandler.js +3 -5
  22. package/lib/config/defaults.js +7 -2
  23. package/lib/config/normalization.js +1 -0
  24. package/lib/css/CssLoadingRuntimeModule.js +63 -70
  25. package/lib/css/CssModulesPlugin.js +2 -1
  26. package/lib/debug/ProfilingPlugin.js +3 -4
  27. package/lib/dependencies/ContextDependencyHelpers.js +1 -1
  28. package/lib/dependencies/ContextElementDependency.js +8 -2
  29. package/lib/dependencies/ExportsInfoDependency.js +6 -0
  30. package/lib/dependencies/HarmonyAcceptImportDependency.js +5 -3
  31. package/lib/dependencies/HarmonyExportInitFragment.js +4 -1
  32. package/lib/dependencies/ImportContextDependency.js +0 -2
  33. package/lib/dependencies/ImportMetaContextDependency.js +35 -0
  34. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +252 -0
  35. package/lib/dependencies/ImportMetaContextPlugin.js +59 -0
  36. package/lib/dependencies/LoaderPlugin.js +2 -0
  37. package/lib/dependencies/RequireContextDependency.js +0 -16
  38. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +24 -8
  39. package/lib/index.js +5 -0
  40. package/lib/javascript/JavascriptModulesPlugin.js +27 -2
  41. package/lib/javascript/StartupHelpers.js +3 -2
  42. package/lib/library/AssignLibraryPlugin.js +8 -2
  43. package/lib/node/NodeTargetPlugin.js +1 -0
  44. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +22 -7
  45. package/lib/node/RequireChunkLoadingRuntimeModule.js +22 -7
  46. package/lib/optimize/ConcatenatedModule.js +10 -4
  47. package/lib/schemes/HttpUriPlugin.js +68 -6
  48. package/lib/serialization/FileMiddleware.js +44 -9
  49. package/lib/util/compileBooleanMatcher.js +1 -1
  50. package/lib/util/deterministicGrouping.js +1 -1
  51. package/lib/util/identifier.js +65 -44
  52. package/lib/util/internalSerializables.js +2 -0
  53. package/lib/util/nonNumericOnlyHash.js +22 -0
  54. package/lib/util/semver.js +17 -10
  55. package/lib/web/JsonpChunkLoadingRuntimeModule.js +15 -5
  56. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +30 -20
  57. package/module.d.ts +15 -0
  58. package/package.json +13 -13
  59. package/schemas/WebpackOptions.check.js +1 -1
  60. package/schemas/WebpackOptions.json +17 -1
  61. package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
  62. package/schemas/plugins/schemes/HttpUriPlugin.json +4 -0
  63. package/types.d.ts +203 -91
@@ -12,6 +12,7 @@ const Generator = require("../Generator");
12
12
  const RuntimeGlobals = require("../RuntimeGlobals");
13
13
  const createHash = require("../util/createHash");
14
14
  const { makePathsRelative } = require("../util/identifier");
15
+ const nonNumericOnlyHash = require("../util/nonNumericOnlyHash");
15
16
 
16
17
  /** @typedef {import("webpack-sources").Source} Source */
17
18
  /** @typedef {import("../../declarations/WebpackOptions").AssetGeneratorOptions} AssetGeneratorOptions */
@@ -112,6 +113,7 @@ const decodeDataUriContent = (encoding, content) => {
112
113
 
113
114
  const JS_TYPES = new Set(["javascript"]);
114
115
  const JS_AND_ASSET_TYPES = new Set(["javascript", "asset"]);
116
+ const DEFAULT_ENCODING = "base64";
115
117
 
116
118
  class AssetGenerator extends Generator {
117
119
  /**
@@ -130,6 +132,65 @@ class AssetGenerator extends Generator {
130
132
  this.emit = emit;
131
133
  }
132
134
 
135
+ /**
136
+ * @param {NormalModule} module module
137
+ * @param {RuntimeTemplate} runtimeTemplate runtime template
138
+ * @returns {string} source file name
139
+ */
140
+ getSourceFileName(module, runtimeTemplate) {
141
+ return makePathsRelative(
142
+ runtimeTemplate.compilation.compiler.context,
143
+ module.matchResource || module.resource,
144
+ runtimeTemplate.compilation.compiler.root
145
+ ).replace(/^\.\//, "");
146
+ }
147
+
148
+ /**
149
+ * @param {NormalModule} module module
150
+ * @returns {string} mime type
151
+ */
152
+ getMimeType(module) {
153
+ if (typeof this.dataUrlOptions === "function") {
154
+ throw new Error(
155
+ "This method must not be called when dataUrlOptions is a function"
156
+ );
157
+ }
158
+
159
+ let mimeType = this.dataUrlOptions.mimetype;
160
+ if (mimeType === undefined) {
161
+ const ext = path.extname(module.nameForCondition());
162
+ if (
163
+ module.resourceResolveData &&
164
+ module.resourceResolveData.mimetype !== undefined
165
+ ) {
166
+ mimeType =
167
+ module.resourceResolveData.mimetype +
168
+ module.resourceResolveData.parameters;
169
+ } else if (ext) {
170
+ mimeType = mimeTypes.lookup(ext);
171
+
172
+ if (typeof mimeType !== "string") {
173
+ throw new Error(
174
+ "DataUrl can't be generated automatically, " +
175
+ `because there is no mimetype for "${ext}" in mimetype database. ` +
176
+ 'Either pass a mimetype via "generator.mimetype" or ' +
177
+ 'use type: "asset/resource" to create a resource file instead of a DataUrl'
178
+ );
179
+ }
180
+ }
181
+ }
182
+
183
+ if (typeof mimeType !== "string") {
184
+ throw new Error(
185
+ "DataUrl can't be generated automatically. " +
186
+ 'Either pass a mimetype via "generator.mimetype" or ' +
187
+ 'use type: "asset/resource" to create a resource file instead of a DataUrl'
188
+ );
189
+ }
190
+
191
+ return mimeType;
192
+ }
193
+
133
194
  /**
134
195
  * @param {NormalModule} module module for which the code should be generated
135
196
  * @param {GenerateContext} generateContext context for generate
@@ -169,31 +230,9 @@ class AssetGenerator extends Generator {
169
230
  }
170
231
  }
171
232
  if (encoding === undefined) {
172
- encoding = "base64";
173
- }
174
- let ext;
175
- let mimeType = this.dataUrlOptions.mimetype;
176
- if (mimeType === undefined) {
177
- ext = path.extname(module.nameForCondition());
178
- if (
179
- module.resourceResolveData &&
180
- module.resourceResolveData.mimetype !== undefined
181
- ) {
182
- mimeType =
183
- module.resourceResolveData.mimetype +
184
- module.resourceResolveData.parameters;
185
- } else if (ext) {
186
- mimeType = mimeTypes.lookup(ext);
187
- }
188
- }
189
- if (typeof mimeType !== "string") {
190
- throw new Error(
191
- "DataUrl can't be generated automatically, " +
192
- `because there is no mimetype for "${ext}" in mimetype database. ` +
193
- 'Either pass a mimetype via "generator.mimetype" or ' +
194
- 'use type: "asset/resource" to create a resource file instead of a DataUrl'
195
- );
233
+ encoding = DEFAULT_ENCODING;
196
234
  }
235
+ const mimeType = this.getMimeType(module);
197
236
 
198
237
  let encodedContent;
199
238
 
@@ -232,16 +271,15 @@ class AssetGenerator extends Generator {
232
271
  const fullHash = /** @type {string} */ (
233
272
  hash.digest(runtimeTemplate.outputOptions.hashDigest)
234
273
  );
235
- const contentHash = fullHash.slice(
236
- 0,
274
+ const contentHash = nonNumericOnlyHash(
275
+ fullHash,
237
276
  runtimeTemplate.outputOptions.hashDigestLength
238
277
  );
239
278
  module.buildInfo.fullContentHash = fullHash;
240
- const sourceFilename = makePathsRelative(
241
- runtimeTemplate.compilation.compiler.context,
242
- module.matchResource || module.resource,
243
- runtimeTemplate.compilation.compiler.root
244
- ).replace(/^\.\//, "");
279
+ const sourceFilename = this.getSourceFileName(
280
+ module,
281
+ runtimeTemplate
282
+ );
245
283
  let { path: filename, info: assetInfo } =
246
284
  runtimeTemplate.compilation.getAssetPathWithInfo(
247
285
  assetModuleFilename,
@@ -367,8 +405,59 @@ class AssetGenerator extends Generator {
367
405
  * @param {Hash} hash hash that will be modified
368
406
  * @param {UpdateHashContext} updateHashContext context for updating hash
369
407
  */
370
- updateHash(hash, { module }) {
371
- hash.update(module.buildInfo.dataUrl ? "data-url" : "resource");
408
+ updateHash(hash, { module, runtime, runtimeTemplate, chunkGraph }) {
409
+ if (module.buildInfo.dataUrl) {
410
+ hash.update("data-url");
411
+ // this.dataUrlOptions as function should be pure and only depend on input source and filename
412
+ // therefore it doesn't need to be hashed
413
+ if (typeof this.dataUrlOptions === "function") {
414
+ const ident = /** @type {{ ident?: string }} */ (this.dataUrlOptions)
415
+ .ident;
416
+ if (ident) hash.update(ident);
417
+ } else {
418
+ if (
419
+ this.dataUrlOptions.encoding &&
420
+ this.dataUrlOptions.encoding !== DEFAULT_ENCODING
421
+ ) {
422
+ hash.update(this.dataUrlOptions.encoding);
423
+ }
424
+ if (this.dataUrlOptions.mimetype)
425
+ hash.update(this.dataUrlOptions.mimetype);
426
+ // computed mimetype depends only on module filename which is already part of the hash
427
+ }
428
+ } else {
429
+ hash.update("resource");
430
+
431
+ const pathData = {
432
+ module,
433
+ runtime,
434
+ filename: this.getSourceFileName(module, runtimeTemplate),
435
+ chunkGraph,
436
+ contentHash: runtimeTemplate.contentHashReplacement
437
+ };
438
+
439
+ if (typeof this.publicPath === "function") {
440
+ hash.update("path");
441
+ const assetInfo = {};
442
+ hash.update(this.publicPath(pathData, assetInfo));
443
+ hash.update(JSON.stringify(assetInfo));
444
+ } else if (this.publicPath) {
445
+ hash.update("path");
446
+ hash.update(this.publicPath);
447
+ } else {
448
+ hash.update("no-path");
449
+ }
450
+
451
+ const assetModuleFilename =
452
+ this.filename || runtimeTemplate.outputOptions.assetModuleFilename;
453
+ const { path: filename, info } =
454
+ runtimeTemplate.compilation.getAssetPathWithInfo(
455
+ assetModuleFilename,
456
+ pathData
457
+ );
458
+ hash.update(filename);
459
+ hash.update(JSON.stringify(info));
460
+ }
372
461
  }
373
462
  }
374
463
 
@@ -905,7 +905,7 @@ const visitModules = (
905
905
  const module = it.value;
906
906
  if (
907
907
  availableModules.has(module) ||
908
- availableModules.plus.has(m)
908
+ availableModules.plus.has(module)
909
909
  ) {
910
910
  cachedMinAvailableModules.add(module);
911
911
  }
@@ -128,6 +128,13 @@ class ResolverCachePlugin {
128
128
  fileDependencies: new LazySet(),
129
129
  contextDependencies: new LazySet()
130
130
  };
131
+ let yieldResult;
132
+ let withYield = false;
133
+ if (typeof newResolveContext.yield === "function") {
134
+ yieldResult = [];
135
+ withYield = true;
136
+ newResolveContext.yield = obj => yieldResult.push(obj);
137
+ }
131
138
  const propagate = key => {
132
139
  if (resolveContext[key]) {
133
140
  addAllToSet(resolveContext[key], newResolveContext[key]);
@@ -155,15 +162,22 @@ class ResolverCachePlugin {
155
162
  snapshotOptions,
156
163
  (err, snapshot) => {
157
164
  if (err) return callback(err);
165
+ const resolveResult = withYield ? yieldResult : result;
166
+ // since we intercept resolve hook
167
+ // we still can get result in callback
168
+ if (withYield && result) yieldResult.push(result);
158
169
  if (!snapshot) {
159
- if (result) return callback(null, result);
170
+ if (resolveResult) return callback(null, resolveResult);
160
171
  return callback();
161
172
  }
162
- itemCache.store(new CacheEntry(result, snapshot), storeErr => {
163
- if (storeErr) return callback(storeErr);
164
- if (result) return callback(null, result);
165
- callback();
166
- });
173
+ itemCache.store(
174
+ new CacheEntry(resolveResult, snapshot),
175
+ storeErr => {
176
+ if (storeErr) return callback(storeErr);
177
+ if (resolveResult) return callback(null, resolveResult);
178
+ callback();
179
+ }
180
+ );
167
181
  }
168
182
  );
169
183
  }
@@ -173,6 +187,8 @@ class ResolverCachePlugin {
173
187
  factory(type, hook) {
174
188
  /** @type {Map<string, (function(Error=, Object=): void)[]>} */
175
189
  const activeRequests = new Map();
190
+ /** @type {Map<string, [function(Error=, Object=): void, function(Error=, Object=): void][]>} */
191
+ const activeRequestsWithYield = new Map();
176
192
  hook.tap(
177
193
  "ResolverCachePlugin",
178
194
  /**
@@ -197,29 +213,67 @@ class ResolverCachePlugin {
197
213
  if (request._ResolverCachePluginCacheMiss || !fileSystemInfo) {
198
214
  return callback();
199
215
  }
200
- const identifier = `${type}${optionsIdent}${objectToString(
201
- request,
202
- !cacheWithContext
203
- )}`;
204
- const activeRequest = activeRequests.get(identifier);
205
- if (activeRequest) {
206
- activeRequest.push(callback);
207
- return;
216
+ const withYield = typeof resolveContext.yield === "function";
217
+ const identifier = `${type}${
218
+ withYield ? "|yield" : "|default"
219
+ }${optionsIdent}${objectToString(request, !cacheWithContext)}`;
220
+
221
+ if (withYield) {
222
+ const activeRequest = activeRequestsWithYield.get(identifier);
223
+ if (activeRequest) {
224
+ activeRequest[0].push(callback);
225
+ activeRequest[1].push(resolveContext.yield);
226
+ return;
227
+ }
228
+ } else {
229
+ const activeRequest = activeRequests.get(identifier);
230
+ if (activeRequest) {
231
+ activeRequest.push(callback);
232
+ return;
233
+ }
208
234
  }
209
235
  const itemCache = cache.getItemCache(identifier, null);
210
- let callbacks;
211
- const done = (err, result) => {
212
- if (callbacks === undefined) {
213
- callback(err, result);
214
- callbacks = false;
215
- } else {
216
- for (const callback of callbacks) {
217
- callback(err, result);
218
- }
219
- activeRequests.delete(identifier);
220
- callbacks = false;
221
- }
222
- };
236
+ let callbacks, yields;
237
+ const done = withYield
238
+ ? (err, result) => {
239
+ if (callbacks === undefined) {
240
+ if (err) {
241
+ callback(err);
242
+ } else {
243
+ if (result)
244
+ for (const r of result) resolveContext.yield(r);
245
+ callback(null, null);
246
+ }
247
+ yields = undefined;
248
+ callbacks = false;
249
+ } else {
250
+ if (err) {
251
+ for (const cb of callbacks) cb(err);
252
+ } else {
253
+ for (let i = 0; i < callbacks.length; i++) {
254
+ const cb = callbacks[i];
255
+ const yield_ = yields[i];
256
+ if (result) for (const r of result) yield_(r);
257
+ cb(null, null);
258
+ }
259
+ }
260
+ activeRequestsWithYield.delete(identifier);
261
+ yields = undefined;
262
+ callbacks = false;
263
+ }
264
+ }
265
+ : (err, result) => {
266
+ if (callbacks === undefined) {
267
+ callback(err, result);
268
+ callbacks = false;
269
+ } else {
270
+ for (const callback of callbacks) {
271
+ callback(err, result);
272
+ }
273
+ activeRequests.delete(identifier);
274
+ callbacks = false;
275
+ }
276
+ };
223
277
  /**
224
278
  * @param {Error=} err error if any
225
279
  * @param {CacheEntry=} cacheEntry cache entry
@@ -276,7 +330,14 @@ class ResolverCachePlugin {
276
330
  }
277
331
  };
278
332
  itemCache.get(processCacheResult);
279
- if (callbacks === undefined) {
333
+ if (withYield && callbacks === undefined) {
334
+ callbacks = [callback];
335
+ yields = [resolveContext.yield];
336
+ activeRequestsWithYield.set(
337
+ identifier,
338
+ /** @type {[any, any]} */ ([callbacks, yields])
339
+ );
340
+ } else if (callbacks === undefined) {
280
341
  callbacks = [callback];
281
342
  activeRequests.set(identifier, callbacks);
282
343
  }
@@ -121,8 +121,7 @@ const resolve = browsers => {
121
121
  // baidu: Not supported
122
122
  // and_uc: Not supported
123
123
  // kaios: Not supported
124
- // Since Node.js 13.14.0 no warning about usage, but it was added 8.5.0 with some limitations and it was improved in 12.0.0 and 13.2.0
125
- node: [13, 14]
124
+ node: [12, 17]
126
125
  });
127
126
 
128
127
  return {
@@ -248,8 +247,7 @@ const resolve = browsers => {
248
247
  // baidu: Not supported
249
248
  // and_uc: Not supported
250
249
  // kaios: Not supported
251
- // Since Node.js 13.14.0 no warning about usage, but it was added 8.5.0 with some limitations and it was improved in 12.0.0 and 13.2.0
252
- node: [13, 14]
250
+ node: [12, 17]
253
251
  }),
254
252
  dynamicImport: es6DynamicImport,
255
253
  dynamicImportInWorker: es6DynamicImport && !anyNode,
@@ -272,7 +270,7 @@ const resolve = browsers => {
272
270
  // baidu: Unknown support
273
271
  // and_uc: Unknown support
274
272
  // kaios: Unknown support
275
- node: [12, 0]
273
+ node: 12
276
274
  }),
277
275
  optionalChaining: rawChecker({
278
276
  chrome: 80,
@@ -907,6 +907,7 @@ const applyOutputDefaults = (
907
907
  D(output, "strictModuleExceptionHandling", false);
908
908
 
909
909
  const optimistic = v => v || v === undefined;
910
+ const conditionallyOptimistic = (v, c) => (v === undefined && c) || v;
910
911
  F(
911
912
  output.environment,
912
913
  "arrowFunction",
@@ -920,8 +921,12 @@ const applyOutputDefaults = (
920
921
  );
921
922
  F(output.environment, "forOf", () => tp && optimistic(tp.forOf));
922
923
  F(output.environment, "bigIntLiteral", () => tp && tp.bigIntLiteral);
923
- F(output.environment, "dynamicImport", () => tp && tp.dynamicImport);
924
- F(output.environment, "module", () => tp && tp.module);
924
+ F(output.environment, "dynamicImport", () =>
925
+ conditionallyOptimistic(tp && tp.dynamicImport, output.module)
926
+ );
927
+ F(output.environment, "module", () =>
928
+ conditionallyOptimistic(tp && tp.module, output.module)
929
+ );
925
930
 
926
931
  const { trustedTypes } = output;
927
932
  if (trustedTypes) {
@@ -488,6 +488,7 @@ const getNormalizedEntryStatic = entry => {
488
488
  filename: value.filename,
489
489
  layer: value.layer,
490
490
  runtime: value.runtime,
491
+ baseUri: value.baseUri,
491
492
  publicPath: value.publicPath,
492
493
  chunkLoading: value.chunkLoading,
493
494
  asyncChunks: value.asyncChunks,
@@ -274,78 +274,71 @@ class CssLoadingRuntimeModule extends RuntimeModule {
274
274
  "",
275
275
  withLoading
276
276
  ? Template.asString([
277
- `${fn}.css = ${runtimeTemplate.basicFunction(
278
- "chunkId, promises",
279
- hasCssMatcher !== false
280
- ? [
281
- "// css chunk loading",
282
- `var installedChunkData = ${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;`,
283
- 'if(installedChunkData !== 0) { // 0 means "already installed".',
284
- Template.indent([
285
- "",
286
- '// a Promise means "currently loading".',
287
- "if(installedChunkData) {",
288
- Template.indent([
289
- "promises.push(installedChunkData[2]);"
290
- ]),
291
- "} else {",
292
- Template.indent([
293
- hasCssMatcher === true
294
- ? "if(true) { // all chunks have CSS"
295
- : `if(${hasCssMatcher("chunkId")}) {`,
277
+ `${fn}.css = ${runtimeTemplate.basicFunction("chunkId, promises", [
278
+ "// css chunk loading",
279
+ `var installedChunkData = ${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;`,
280
+ 'if(installedChunkData !== 0) { // 0 means "already installed".',
281
+ Template.indent([
282
+ "",
283
+ '// a Promise means "currently loading".',
284
+ "if(installedChunkData) {",
285
+ Template.indent(["promises.push(installedChunkData[2]);"]),
286
+ "} else {",
287
+ Template.indent([
288
+ hasCssMatcher === true
289
+ ? "if(true) { // all chunks have CSS"
290
+ : `if(${hasCssMatcher("chunkId")}) {`,
291
+ Template.indent([
292
+ "// setup Promise in chunk cache",
293
+ `var promise = new Promise(${runtimeTemplate.expressionFunction(
294
+ `installedChunkData = installedChunks[chunkId] = [resolve, reject]`,
295
+ "resolve, reject"
296
+ )});`,
297
+ "promises.push(installedChunkData[2] = promise);",
298
+ "",
299
+ "// start chunk loading",
300
+ `var url = ${RuntimeGlobals.publicPath} + ${RuntimeGlobals.getChunkCssFilename}(chunkId);`,
301
+ "// create error before stack unwound to get useful stacktrace later",
302
+ "var error = new Error();",
303
+ `var loadingEnded = ${runtimeTemplate.basicFunction(
304
+ "event",
305
+ [
306
+ `if(${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId)) {`,
296
307
  Template.indent([
297
- "// setup Promise in chunk cache",
298
- `var promise = new Promise(${runtimeTemplate.expressionFunction(
299
- `installedChunkData = installedChunks[chunkId] = [resolve, reject]`,
300
- "resolve, reject"
301
- )});`,
302
- "promises.push(installedChunkData[2] = promise);",
303
- "",
304
- "// start chunk loading",
305
- `var url = ${RuntimeGlobals.publicPath} + ${RuntimeGlobals.getChunkCssFilename}(chunkId);`,
306
- "// create error before stack unwound to get useful stacktrace later",
307
- "var error = new Error();",
308
- `var loadingEnded = ${runtimeTemplate.basicFunction(
309
- "event",
310
- [
311
- `if(${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId)) {`,
312
- Template.indent([
313
- "installedChunkData = installedChunks[chunkId];",
314
- "if(installedChunkData !== 0) installedChunks[chunkId] = undefined;",
315
- "if(installedChunkData) {",
316
- Template.indent([
317
- 'if(event.type !== "load") {',
318
- Template.indent([
319
- "var errorType = event && event.type;",
320
- "var realSrc = event && event.target && event.target.src;",
321
- "error.message = 'Loading css chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';",
322
- "error.name = 'ChunkLoadError';",
323
- "error.type = errorType;",
324
- "error.request = realSrc;",
325
- "installedChunkData[1](error);"
326
- ]),
327
- "} else {",
328
- Template.indent([
329
- `loadCssChunkData(${RuntimeGlobals.moduleFactories}, link, chunkId);`,
330
- "installedChunkData[0]();"
331
- ]),
332
- "}"
333
- ]),
334
- "}"
335
- ]),
336
- "}"
337
- ]
338
- )};`,
339
- "var link = loadStylesheet(chunkId, url, loadingEnded);"
308
+ "installedChunkData = installedChunks[chunkId];",
309
+ "if(installedChunkData !== 0) installedChunks[chunkId] = undefined;",
310
+ "if(installedChunkData) {",
311
+ Template.indent([
312
+ 'if(event.type !== "load") {',
313
+ Template.indent([
314
+ "var errorType = event && event.type;",
315
+ "var realSrc = event && event.target && event.target.src;",
316
+ "error.message = 'Loading css chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';",
317
+ "error.name = 'ChunkLoadError';",
318
+ "error.type = errorType;",
319
+ "error.request = realSrc;",
320
+ "installedChunkData[1](error);"
321
+ ]),
322
+ "} else {",
323
+ Template.indent([
324
+ `loadCssChunkData(${RuntimeGlobals.moduleFactories}, link, chunkId);`,
325
+ "installedChunkData[0]();"
326
+ ]),
327
+ "}"
328
+ ]),
329
+ "}"
340
330
  ]),
341
- "} else installedChunks[chunkId] = 0;"
342
- ]),
343
- "}"
344
- ]),
345
- "}"
346
- ]
347
- : "installedChunks[chunkId] = 0;"
348
- )};`
331
+ "}"
332
+ ]
333
+ )};`,
334
+ "var link = loadStylesheet(chunkId, url, loadingEnded);"
335
+ ]),
336
+ "} else installedChunks[chunkId] = 0;"
337
+ ]),
338
+ "}"
339
+ ]),
340
+ "}"
341
+ ])};`
349
342
  ])
350
343
  : "// no chunk loading",
351
344
  "",
@@ -19,6 +19,7 @@ const { compareModulesByIdentifier } = require("../util/comparators");
19
19
  const createSchemaValidation = require("../util/create-schema-validation");
20
20
  const createHash = require("../util/createHash");
21
21
  const memoize = require("../util/memoize");
22
+ const nonNumericOnlyHash = require("../util/nonNumericOnlyHash");
22
23
  const CssExportsGenerator = require("./CssExportsGenerator");
23
24
  const CssGenerator = require("./CssGenerator");
24
25
  const CssParser = require("./CssParser");
@@ -201,7 +202,7 @@ class CssModulesPlugin {
201
202
  hash.update(chunkGraph.getModuleHash(module, chunk.runtime));
202
203
  }
203
204
  const digest = /** @type {string} */ (hash.digest(hashDigest));
204
- chunk.contentHash.css = digest.substr(0, hashDigestLength);
205
+ chunk.contentHash.css = nonNumericOnlyHash(digest, hashDigestLength);
205
206
  });
206
207
  compilation.hooks.renderManifest.tap(plugin, (result, options) => {
207
208
  const { chunkGraph } = compilation;
@@ -343,7 +343,8 @@ const interceptAllJavascriptModulesPluginHooks = (compilation, tracer) => {
343
343
  };
344
344
 
345
345
  const makeInterceptorFor = (instance, tracer) => hookName => ({
346
- register: ({ name, type, context, fn }) => {
346
+ register: tapInfo => {
347
+ const { name, type, fn } = tapInfo;
347
348
  const newFn =
348
349
  // Don't tap our own hooks to ensure stream can close cleanly
349
350
  name === pluginName
@@ -354,9 +355,7 @@ const makeInterceptorFor = (instance, tracer) => hookName => ({
354
355
  fn
355
356
  });
356
357
  return {
357
- name,
358
- type,
359
- context,
358
+ ...tapInfo,
360
359
  fn: newFn
361
360
  };
362
361
  }
@@ -37,7 +37,7 @@ const splitContextFromPrefix = prefix => {
37
37
  };
38
38
  };
39
39
 
40
- /** @typedef {Partial<Omit<ContextDependencyOptions, "resource"|"recursive"|"regExp">>} PartialContextDependencyOptions */
40
+ /** @typedef {Partial<Omit<ContextDependencyOptions, "resource">>} PartialContextDependencyOptions */
41
41
 
42
42
  /** @typedef {{ new(options: ContextDependencyOptions, range: [number, number], valueRange: [number, number]): ContextDependency }} ContextDependencyConstructor */
43
43
 
@@ -53,12 +53,18 @@ class ContextElementDependency extends ModuleDependency {
53
53
  }
54
54
 
55
55
  serialize(context) {
56
- context.write(this.referencedExports);
56
+ const { write } = context;
57
+ write(this._typePrefix);
58
+ write(this._category);
59
+ write(this.referencedExports);
57
60
  super.serialize(context);
58
61
  }
59
62
 
60
63
  deserialize(context) {
61
- this.referencedExports = context.read();
64
+ const { read } = context;
65
+ this._typePrefix = read();
66
+ this._category = read();
67
+ this.referencedExports = read();
62
68
  super.deserialize(context);
63
69
  }
64
70
  }
@@ -46,6 +46,12 @@ const getProperty = (moduleGraph, module, exportName, property, runtime) => {
46
46
  }
47
47
  }
48
48
  switch (property) {
49
+ case "canMangle": {
50
+ const exportsInfo = moduleGraph.getExportsInfo(module);
51
+ const exportInfo = exportsInfo.getExportInfo(exportName);
52
+ if (exportInfo) return exportInfo.canMangle;
53
+ return exportsInfo.otherExportsInfo.canMangle;
54
+ }
49
55
  case "used":
50
56
  return (
51
57
  moduleGraph.getExportsInfo(module).getUsed(exportName, runtime) !==