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

Potentially problematic release.


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

package/lib/ChunkGraph.js CHANGED
@@ -46,6 +46,7 @@ const compareModuleIterables = compareIterables(compareModulesByIdentifier);
46
46
 
47
47
  /** @typedef {(c: Chunk, chunkGraph: ChunkGraph) => boolean} ChunkFilterPredicate */
48
48
  /** @typedef {(m: Module) => boolean} ModuleFilterPredicate */
49
+ /** @typedef {[Module, Entrypoint | undefined]} EntryModuleWithChunkGroup */
49
50
 
50
51
  /**
51
52
  * @typedef {Object} ChunkSizeOptions
@@ -1180,8 +1181,6 @@ class ChunkGraph {
1180
1181
  return cgc.dependentHashModules;
1181
1182
  }
1182
1183
 
1183
- /** @typedef {[Module, Entrypoint | undefined]} EntryModuleWithChunkGroup */
1184
-
1185
1184
  /**
1186
1185
  * @param {Chunk} chunk the chunk
1187
1186
  * @returns {Iterable<EntryModuleWithChunkGroup>} iterable of modules (do not modify)
@@ -182,6 +182,7 @@ const { isSourceEqual } = require("./util/source");
182
182
 
183
183
  /**
184
184
  * @typedef {Object} ChunkHashContext
185
+ * @property {CodeGenerationResults} codeGenerationResults results of code generation
185
186
  * @property {RuntimeTemplate} runtimeTemplate the runtime template
186
187
  * @property {ModuleGraph} moduleGraph the module graph
187
188
  * @property {ChunkGraph} chunkGraph the chunk graph
@@ -4137,6 +4138,7 @@ This prevents using hashes of each other and should be avoided.`);
4137
4138
  chunk.updateHash(chunkHash, chunkGraph);
4138
4139
  this.hooks.chunkHash.call(chunk, chunkHash, {
4139
4140
  chunkGraph,
4141
+ codeGenerationResults: this.codeGenerationResults,
4140
4142
  moduleGraph: this.moduleGraph,
4141
4143
  runtimeTemplate: this.runtimeTemplate
4142
4144
  });
@@ -291,15 +291,15 @@ class ExportsInfo {
291
291
  }
292
292
  }
293
293
  for (const exportInfo of this._exports.values()) {
294
+ if (!canMangle && exportInfo.canMangleProvide !== false) {
295
+ exportInfo.canMangleProvide = false;
296
+ changed = true;
297
+ }
294
298
  if (excludeExports && excludeExports.has(exportInfo.name)) continue;
295
299
  if (exportInfo.provided !== true && exportInfo.provided !== null) {
296
300
  exportInfo.provided = null;
297
301
  changed = true;
298
302
  }
299
- if (!canMangle && exportInfo.canMangleProvide !== false) {
300
- exportInfo.canMangleProvide = false;
301
- changed = true;
302
- }
303
303
  if (targetKey) {
304
304
  exportInfo.setTarget(targetKey, targetModule, [exportInfo.name], -1);
305
305
  }
@@ -28,7 +28,10 @@ const LazySet = require("./util/LazySet");
28
28
  const { getScheme } = require("./util/URLAbsoluteSpecifier");
29
29
  const { cachedCleverMerge, cachedSetProperty } = require("./util/cleverMerge");
30
30
  const { join } = require("./util/fs");
31
- const { parseResource } = require("./util/identifier");
31
+ const {
32
+ parseResource,
33
+ parseResourceWithoutFragment
34
+ } = require("./util/identifier");
32
35
 
33
36
  /** @typedef {import("../declarations/WebpackOptions").ModuleOptionsNormalized} ModuleOptions */
34
37
  /** @typedef {import("./Generator")} Generator */
@@ -66,6 +69,11 @@ const { parseResource } = require("./util/identifier");
66
69
 
67
70
  /** @typedef {ResourceData & { data: Record<string, any> }} ResourceDataWithData */
68
71
 
72
+ /** @typedef {Object} ParsedLoaderRequest
73
+ * @property {string} loader loader
74
+ * @property {string|undefined} options options
75
+ */
76
+
69
77
  const EMPTY_RESOLVE_OPTIONS = {};
70
78
  const EMPTY_PARSER_OPTIONS = {};
71
79
  const EMPTY_GENERATOR_OPTIONS = {};
@@ -97,27 +105,6 @@ const stringifyLoadersAndResource = (loaders, resource) => {
97
105
  return str + resource;
98
106
  };
99
107
 
100
- /**
101
- * @param {string} resultString resultString
102
- * @returns {{loader: string, options: string|undefined}} parsed loader request
103
- */
104
- const identToLoaderRequest = resultString => {
105
- const idx = resultString.indexOf("?");
106
- if (idx >= 0) {
107
- const loader = resultString.substr(0, idx);
108
- const options = resultString.substr(idx + 1);
109
- return {
110
- loader,
111
- options
112
- };
113
- } else {
114
- return {
115
- loader: resultString,
116
- options: undefined
117
- };
118
- }
119
- };
120
-
121
108
  const needCalls = (times, callback) => {
122
109
  return err => {
123
110
  if (--times === 0) {
@@ -264,6 +251,9 @@ class NormalModuleFactory extends ModuleFactory {
264
251
  const cacheParseResource = parseResource.bindCache(
265
252
  associatedObjectForCache
266
253
  );
254
+ const cachedParseResourceWithoutFragment =
255
+ parseResourceWithoutFragment.bindCache(associatedObjectForCache);
256
+ this._parseResourceWithoutFragment = cachedParseResourceWithoutFragment;
267
257
 
268
258
  this.hooks.factorize.tapAsync(
269
259
  {
@@ -351,7 +341,7 @@ class NormalModuleFactory extends ModuleFactory {
351
341
  let matchResourceData = undefined;
352
342
  /** @type {string} */
353
343
  let unresolvedResource;
354
- /** @type {{loader: string, options: string|undefined}[]} */
344
+ /** @type {ParsedLoaderRequest[]} */
355
345
  let elements;
356
346
  let noPreAutoLoaders = false;
357
347
  let noAutoLoaders = false;
@@ -405,7 +395,13 @@ class NormalModuleFactory extends ModuleFactory {
405
395
  )
406
396
  .split(/!+/);
407
397
  unresolvedResource = rawElements.pop();
408
- elements = rawElements.map(identToLoaderRequest);
398
+ elements = rawElements.map(el => {
399
+ const { path, query } = cachedParseResourceWithoutFragment(el);
400
+ return {
401
+ loader: path,
402
+ options: query ? query.slice(1) : undefined
403
+ };
404
+ });
409
405
  scheme = getScheme(unresolvedResource);
410
406
  } else {
411
407
  unresolvedResource = requestWithoutMatchResource;
@@ -1017,12 +1013,14 @@ If changing the source code is not an option there is also a resolve options cal
1017
1013
  }
1018
1014
  if (err) return callback(err);
1019
1015
 
1020
- const parsedResult = identToLoaderRequest(result);
1016
+ const parsedResult = this._parseResourceWithoutFragment(result);
1021
1017
  const resolved = {
1022
- loader: parsedResult.loader,
1018
+ loader: parsedResult.path,
1023
1019
  options:
1024
1020
  item.options === undefined
1025
- ? parsedResult.options
1021
+ ? parsedResult.query
1022
+ ? parsedResult.query.slice(1)
1023
+ : undefined
1026
1024
  : item.options,
1027
1025
  ident: item.options === undefined ? undefined : item.ident
1028
1026
  };
@@ -96,7 +96,7 @@ const createDefaultHandler = (profile, logger) => {
96
96
  /**
97
97
  * @callback ReportProgress
98
98
  * @param {number} p
99
- * @param {...string[]} [args]
99
+ * @param {...string} [args]
100
100
  * @returns {void}
101
101
  */
102
102
 
@@ -5,6 +5,7 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ const mime = require("mime-types");
8
9
  const { basename, extname } = require("path");
9
10
  const util = require("util");
10
11
  const Chunk = require("./Chunk");
@@ -117,29 +118,53 @@ const replacePathVariables = (path, data, assetInfo) => {
117
118
  // [name] - file
118
119
  // [ext] - .js
119
120
  if (typeof data.filename === "string") {
120
- const { path: file, query, fragment } = parseResource(data.filename);
121
-
122
- const ext = extname(file);
123
- const base = basename(file);
124
- const name = base.slice(0, base.length - ext.length);
125
- const path = file.slice(0, file.length - base.length);
126
-
127
- replacements.set("file", replacer(file));
128
- replacements.set("query", replacer(query, true));
129
- replacements.set("fragment", replacer(fragment, true));
130
- replacements.set("path", replacer(path, true));
131
- replacements.set("base", replacer(base));
132
- replacements.set("name", replacer(name));
133
- replacements.set("ext", replacer(ext, true));
134
- // Legacy
135
- replacements.set(
136
- "filebase",
137
- deprecated(
138
- replacer(base),
139
- "[filebase] is now [base]",
140
- "DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_FILENAME"
141
- )
142
- );
121
+ // check that filename is data uri
122
+ let match = data.filename.match(/^data:([^;,]+)/);
123
+ if (match) {
124
+ const ext = mime.extension(match[1]);
125
+ const emptyReplacer = replacer("", true);
126
+
127
+ replacements.set("file", emptyReplacer);
128
+ replacements.set("query", emptyReplacer);
129
+ replacements.set("fragment", emptyReplacer);
130
+ replacements.set("path", emptyReplacer);
131
+ replacements.set("base", emptyReplacer);
132
+ replacements.set("name", emptyReplacer);
133
+ replacements.set("ext", replacer(ext ? `.${ext}` : "", true));
134
+ // Legacy
135
+ replacements.set(
136
+ "filebase",
137
+ deprecated(
138
+ emptyReplacer,
139
+ "[filebase] is now [base]",
140
+ "DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_FILENAME"
141
+ )
142
+ );
143
+ } else {
144
+ const { path: file, query, fragment } = parseResource(data.filename);
145
+
146
+ const ext = extname(file);
147
+ const base = basename(file);
148
+ const name = base.slice(0, base.length - ext.length);
149
+ const path = file.slice(0, file.length - base.length);
150
+
151
+ replacements.set("file", replacer(file));
152
+ replacements.set("query", replacer(query, true));
153
+ replacements.set("fragment", replacer(fragment, true));
154
+ replacements.set("path", replacer(path, true));
155
+ replacements.set("base", replacer(base));
156
+ replacements.set("name", replacer(name));
157
+ replacements.set("ext", replacer(ext, true));
158
+ // Legacy
159
+ replacements.set(
160
+ "filebase",
161
+ deprecated(
162
+ replacer(base),
163
+ "[filebase] is now [base]",
164
+ "DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_FILENAME"
165
+ )
166
+ );
167
+ }
143
168
  }
144
169
 
145
170
  // Compilation context
@@ -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 */
@@ -232,8 +233,8 @@ class AssetGenerator extends Generator {
232
233
  const fullHash = /** @type {string} */ (
233
234
  hash.digest(runtimeTemplate.outputOptions.hashDigest)
234
235
  );
235
- const contentHash = fullHash.slice(
236
- 0,
236
+ const contentHash = nonNumericOnlyHash(
237
+ fullHash,
237
238
  runtimeTemplate.outputOptions.hashDigestLength
238
239
  );
239
240
  module.buildInfo.fullContentHash = fullHash;
@@ -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
  }
@@ -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) {
@@ -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
  }
@@ -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) !==
package/lib/index.js CHANGED
@@ -11,6 +11,7 @@ const memoize = require("./util/memoize");
11
11
  /** @typedef {import("../declarations/WebpackOptions").Entry} Entry */
12
12
  /** @typedef {import("../declarations/WebpackOptions").EntryNormalized} EntryNormalized */
13
13
  /** @typedef {import("../declarations/WebpackOptions").EntryObject} EntryObject */
14
+ /** @typedef {import("../declarations/WebpackOptions").FileCacheOptions} FileCacheOptions */
14
15
  /** @typedef {import("../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
15
16
  /** @typedef {import("../declarations/WebpackOptions").ModuleOptions} ModuleOptions */
16
17
  /** @typedef {import("../declarations/WebpackOptions").ResolveOptions} ResolveOptions */
@@ -26,11 +27,15 @@ const memoize = require("./util/memoize");
26
27
  /** @typedef {import("../declarations/WebpackOptions").WebpackPluginInstance} WebpackPluginInstance */
27
28
  /** @typedef {import("./Compilation").Asset} Asset */
28
29
  /** @typedef {import("./Compilation").AssetInfo} AssetInfo */
30
+ /** @typedef {import("./Compilation").EntryOptions} EntryOptions */
31
+ /** @typedef {import("./Compiler").AssetEmittedInfo} AssetEmittedInfo */
29
32
  /** @typedef {import("./MultiStats")} MultiStats */
30
33
  /** @typedef {import("./Parser").ParserState} ParserState */
31
34
  /** @typedef {import("./ResolverFactory").ResolvePluginInstance} ResolvePluginInstance */
32
35
  /** @typedef {import("./ResolverFactory").Resolver} Resolver */
33
36
  /** @typedef {import("./Watching")} Watching */
37
+ /** @typedef {import("./cli").Argument} Argument */
38
+ /** @typedef {import("./cli").Problem} Problem */
34
39
  /** @typedef {import("./stats/DefaultStatsFactoryPlugin").StatsAsset} StatsAsset */
35
40
  /** @typedef {import("./stats/DefaultStatsFactoryPlugin").StatsChunk} StatsChunk */
36
41
  /** @typedef {import("./stats/DefaultStatsFactoryPlugin").StatsChunkGroup} StatsChunkGroup */
@@ -24,6 +24,7 @@ const { last, someInIterable } = require("../util/IterableHelpers");
24
24
  const StringXor = require("../util/StringXor");
25
25
  const { compareModulesByIdentifier } = require("../util/comparators");
26
26
  const createHash = require("../util/createHash");
27
+ const nonNumericOnlyHash = require("../util/nonNumericOnlyHash");
27
28
  const { intersectRuntime } = require("../util/runtime");
28
29
  const JavascriptGenerator = require("./JavascriptGenerator");
29
30
  const JavascriptParser = require("./JavascriptParser");
@@ -102,6 +103,7 @@ const printGeneratedCodeForStack = (module, code) => {
102
103
  /**
103
104
  * @typedef {Object} RenderBootstrapContext
104
105
  * @property {Chunk} chunk the chunk
106
+ * @property {CodeGenerationResults} codeGenerationResults results of code generation
105
107
  * @property {RuntimeTemplate} runtimeTemplate the runtime template
106
108
  * @property {ModuleGraph} moduleGraph the module graph
107
109
  * @property {ChunkGraph} chunkGraph the chunk graph
@@ -331,6 +333,7 @@ class JavascriptModulesPlugin {
331
333
  {
332
334
  hash: "0000",
333
335
  chunk,
336
+ codeGenerationResults: context.codeGenerationResults,
334
337
  chunkGraph: context.chunkGraph,
335
338
  moduleGraph: context.moduleGraph,
336
339
  runtimeTemplate: context.runtimeTemplate
@@ -343,6 +346,7 @@ class JavascriptModulesPlugin {
343
346
  compilation.hooks.contentHash.tap("JavascriptModulesPlugin", chunk => {
344
347
  const {
345
348
  chunkGraph,
349
+ codeGenerationResults,
346
350
  moduleGraph,
347
351
  runtimeTemplate,
348
352
  outputOptions: {
@@ -360,6 +364,7 @@ class JavascriptModulesPlugin {
360
364
  {
361
365
  hash: "0000",
362
366
  chunk,
367
+ codeGenerationResults,
363
368
  chunkGraph: compilation.chunkGraph,
364
369
  moduleGraph: compilation.moduleGraph,
365
370
  runtimeTemplate: compilation.runtimeTemplate
@@ -372,6 +377,7 @@ class JavascriptModulesPlugin {
372
377
  }
373
378
  hooks.chunkHash.call(chunk, hash, {
374
379
  chunkGraph,
380
+ codeGenerationResults,
375
381
  moduleGraph,
376
382
  runtimeTemplate
377
383
  });
@@ -398,7 +404,10 @@ class JavascriptModulesPlugin {
398
404
  xor.updateHash(hash);
399
405
  }
400
406
  const digest = /** @type {string} */ (hash.digest(hashDigest));
401
- chunk.contentHash.javascript = digest.substr(0, hashDigestLength);
407
+ chunk.contentHash.javascript = nonNumericOnlyHash(
408
+ digest,
409
+ hashDigestLength
410
+ );
402
411
  });
403
412
  compilation.hooks.additionalTreeRuntimeRequirements.tap(
404
413
  "JavascriptModulesPlugin",
@@ -974,7 +983,13 @@ class JavascriptModulesPlugin {
974
983
  * @returns {{ header: string[], beforeStartup: string[], startup: string[], afterStartup: string[], allowInlineStartup: boolean }} the generated source of the bootstrap code
975
984
  */
976
985
  renderBootstrap(renderContext, hooks) {
977
- const { chunkGraph, moduleGraph, chunk, runtimeTemplate } = renderContext;
986
+ const {
987
+ chunkGraph,
988
+ codeGenerationResults,
989
+ moduleGraph,
990
+ chunk,
991
+ runtimeTemplate
992
+ } = renderContext;
978
993
 
979
994
  const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
980
995
 
@@ -1098,8 +1113,18 @@ class JavascriptModulesPlugin {
1098
1113
  );
1099
1114
  result.allowInlineStartup = false;
1100
1115
  }
1116
+
1117
+ let data;
1118
+ if (codeGenerationResults.has(entryModule, chunk.runtime)) {
1119
+ const result = codeGenerationResults.get(
1120
+ entryModule,
1121
+ chunk.runtime
1122
+ );
1123
+ data = result.data;
1124
+ }
1101
1125
  if (
1102
1126
  result.allowInlineStartup &&
1127
+ (!data || !data.get("topLevelDeclarations")) &&
1103
1128
  (!entryModule.buildInfo ||
1104
1129
  !entryModule.buildInfo.topLevelDeclarations)
1105
1130
  ) {