webpack 5.107.0 → 5.107.2

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.
Files changed (64) hide show
  1. package/lib/BannerPlugin.js +3 -4
  2. package/lib/Chunk.js +21 -25
  3. package/lib/ChunkGroup.js +57 -15
  4. package/lib/Compilation.js +33 -11
  5. package/lib/Compiler.js +27 -3
  6. package/lib/ContextModuleFactory.js +45 -38
  7. package/lib/EvalSourceMapDevToolPlugin.js +0 -1
  8. package/lib/ExportsInfo.js +30 -34
  9. package/lib/ExternalModule.js +15 -11
  10. package/lib/ExternalModuleFactoryPlugin.js +2 -1
  11. package/lib/Module.js +1 -1
  12. package/lib/ModuleNotFoundError.js +10 -0
  13. package/lib/ModuleSourceTypeConstants.js +24 -22
  14. package/lib/MultiCompiler.js +14 -0
  15. package/lib/NormalModule.js +531 -53
  16. package/lib/NormalModuleFactory.js +38 -26
  17. package/lib/ProgressPlugin.js +1 -1
  18. package/lib/RuntimePlugin.js +1 -1
  19. package/lib/SourceMapDevToolPlugin.js +335 -57
  20. package/lib/Template.js +1 -1
  21. package/lib/TemplatedPathPlugin.js +22 -4
  22. package/lib/asset/AssetBytesGenerator.js +6 -6
  23. package/lib/asset/AssetGenerator.js +14 -14
  24. package/lib/asset/AssetModulesPlugin.js +3 -7
  25. package/lib/asset/AssetSourceGenerator.js +6 -6
  26. package/lib/buildChunkGraph.js +24 -2
  27. package/lib/cache/getLazyHashedEtag.js +9 -2
  28. package/lib/css/CssModulesPlugin.js +2 -2
  29. package/lib/dependencies/CommonJsImportsParserPlugin.js +108 -1
  30. package/lib/dependencies/CssUrlDependency.js +3 -2
  31. package/lib/dependencies/HarmonyDetectionParserPlugin.js +21 -1
  32. package/lib/dependencies/HarmonyExportInitFragment.js +8 -9
  33. package/lib/dependencies/HtmlInlineScriptDependency.js +3 -14
  34. package/lib/dependencies/HtmlInlineStyleDependency.js +17 -0
  35. package/lib/dependencies/HtmlScriptSrcDependency.js +265 -65
  36. package/lib/dependencies/HtmlSourceDependency.js +21 -2
  37. package/lib/dependencies/WorkerPlugin.js +18 -4
  38. package/lib/hmr/LazyCompilationPlugin.js +104 -0
  39. package/lib/html/HtmlGenerator.js +81 -33
  40. package/lib/html/HtmlModulesPlugin.js +87 -28
  41. package/lib/html/walkHtmlTokens.js +641 -125
  42. package/lib/index.js +2 -0
  43. package/lib/javascript/JavascriptModulesPlugin.js +2 -2
  44. package/lib/javascript/JavascriptParser.js +1 -1
  45. package/lib/library/ModuleLibraryPlugin.js +30 -24
  46. package/lib/node/NodeWatchFileSystem.js +37 -22
  47. package/lib/optimize/ConcatenatedModule.js +3 -2
  48. package/lib/optimize/SideEffectsFlagPlugin.js +1 -2
  49. package/lib/optimize/SplitChunksPlugin.js +4 -4
  50. package/lib/runtime/AutoPublicPathRuntimeModule.js +3 -3
  51. package/lib/runtime/GetChunkFilenameRuntimeModule.js +5 -5
  52. package/lib/sharing/ConsumeSharedPlugin.js +2 -8
  53. package/lib/sharing/ProvideSharedPlugin.js +4 -4
  54. package/lib/util/fs.js +6 -1
  55. package/lib/wasm-async/AsyncWebAssemblyModulesPlugin.js +1 -2
  56. package/package.json +5 -5
  57. package/schemas/WebpackOptions.check.js +1 -1
  58. package/schemas/WebpackOptions.json +11 -9
  59. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  60. package/schemas/plugins/container/ContainerReferencePlugin.json +1 -0
  61. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  62. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  63. package/schemas/plugins/container/ModuleFederationPlugin.json +1 -0
  64. package/types.d.ts +472 -149
@@ -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
- ASSET_AND_CSS_URL_TYPES,
14
- ASSET_AND_JAVASCRIPT_AND_CSS_URL_TYPES,
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
- JAVASCRIPT_AND_CSS_URL_TYPES,
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 === CSS_URL_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 === CSS_URL_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 === CSS_URL_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 === CSS_URL_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 === CSS_URL_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 JAVASCRIPT_AND_CSS_URL_TYPES;
713
+ return JAVASCRIPT_AND_ASSET_URL_TYPES;
714
714
  } else if (sourceTypes.has(CSS_TYPE) || sourceTypes.has(HTML_TYPE)) {
715
- return CSS_URL_TYPES;
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 ASSET_AND_JAVASCRIPT_AND_CSS_URL_TYPES;
728
+ return ASSET_AND_JAVASCRIPT_AND_ASSET_URL_TYPES;
729
729
  } else if (sourceTypes.has(CSS_TYPE) || sourceTypes.has(HTML_TYPE)) {
730
- return ASSET_AND_CSS_URL_TYPES;
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").FilenameTemplate} FilenameTemplate */
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 | FilenameTemplate} */
226
+ /** @type {undefined | AssetModuleFilename} */
231
227
  let filename;
232
228
  /** @type {undefined | RawPublicPath} */
233
229
  let publicPath;
@@ -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
- JAVASCRIPT_AND_CSS_URL_TYPES,
16
+ JAVASCRIPT_AND_ASSET_URL_TYPES,
17
17
  JAVASCRIPT_TYPE,
18
18
  JAVASCRIPT_TYPES,
19
19
  NO_TYPES
@@ -79,7 +79,7 @@ class AssetSourceGenerator extends Generator {
79
79
  }
80
80
  return new RawSource(sourceContent);
81
81
  }
82
- case CSS_URL_TYPE: {
82
+ case ASSET_URL_TYPE: {
83
83
  if (!originalSource) {
84
84
  return null;
85
85
  }
@@ -150,9 +150,9 @@ class AssetSourceGenerator extends Generator {
150
150
  sourceTypes.has(JAVASCRIPT_TYPE) &&
151
151
  (sourceTypes.has(CSS_TYPE) || sourceTypes.has(HTML_TYPE))
152
152
  ) {
153
- return JAVASCRIPT_AND_CSS_URL_TYPES;
153
+ return JAVASCRIPT_AND_ASSET_URL_TYPES;
154
154
  } else if (sourceTypes.has(CSS_TYPE) || sourceTypes.has(HTML_TYPE)) {
155
- return CSS_URL_TYPES;
155
+ return ASSET_URL_TYPES;
156
156
  }
157
157
  return JAVASCRIPT_TYPES;
158
158
  }
@@ -16,6 +16,7 @@ const { getEntryRuntime, mergeRuntime } = require("./util/runtime");
16
16
  /** @typedef {import("./DependenciesBlock")} DependenciesBlock */
17
17
  /** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */
18
18
  /** @typedef {import("./Entrypoint")} Entrypoint */
19
+ /** @typedef {import("./Entrypoint").EntryOptions} EntryOptions */
19
20
  /** @typedef {import("./Module")} Module */
20
21
  /** @typedef {import("./ModuleGraph")} ModuleGraph */
21
22
  /** @typedef {import("./ModuleGraphConnection").ConnectionState} ConnectionState */
@@ -581,7 +582,27 @@ const visitModules = (
581
582
  }
582
583
  } else {
583
584
  entrypoint = /** @type {Entrypoint} */ (cgi.chunkGroup);
584
- // TODO merge entryOptions
585
+ // Fill in options the existing entrypoint hasn't set yet. We never
586
+ // overwrite: blocks that dedupe to one entrypoint (e.g. several
587
+ // workers pointing at the same module) legitimately carry distinct
588
+ // values such as `runtime`, so the first block to create the
589
+ // entrypoint wins and later ones only contribute missing keys.
590
+ // `name` is excluded: it is the entrypoint's identity, fixed at
591
+ // creation (and used to key namedChunkGroups), so back-filling it
592
+ // from a block that deduped in via its module would leave
593
+ // `entrypoint.name` out of sync and make module codegen
594
+ // order-dependent, which breaks persistent caching.
595
+ const existingOptions = entrypoint.options;
596
+ for (const key_ of Object.keys(entryOptions)) {
597
+ const key =
598
+ /** @type {keyof EntryOptions} */
599
+ (key_);
600
+ if (key === "name") continue;
601
+ if (entryOptions[key] === undefined) continue;
602
+ if (existingOptions[key] !== undefined) continue;
603
+ /** @type {EntryOptions[keyof EntryOptions]} */
604
+ (existingOptions[key]) = entryOptions[key];
605
+ }
585
606
  entrypoint.addOrigin(
586
607
  module,
587
608
  /** @type {DependencyLocation} */ (b.loc),
@@ -1290,7 +1311,8 @@ const connectChunkGroups = (
1290
1311
  // connections and modules can only create one version
1291
1312
  // TODO maybe decide this per runtime
1292
1313
  if (
1293
- // TODO is this needed?
1314
+ // Blocks with nested blocks must stay connected — skipping orphans the
1315
+ // nested block's chunk group from this block's chunk group parent.
1294
1316
  !blocksWithNestedBlocks.has(block) &&
1295
1317
  connections.every(({ chunkGroup, originChunkGroupInfo }) =>
1296
1318
  areModulesAvailable(
@@ -25,7 +25,7 @@ class LazyHashedEtag {
25
25
  * @param {HashFunction} hashFunction the hash function to use
26
26
  */
27
27
  constructor(obj, hashFunction = DEFAULTS.HASH_FUNCTION) {
28
- /** @type {HashableObject} */
28
+ /** @type {HashableObject | undefined} */
29
29
  this._obj = obj;
30
30
  /** @type {undefined | string} */
31
31
  this._hash = undefined;
@@ -40,8 +40,15 @@ class LazyHashedEtag {
40
40
  toString() {
41
41
  if (this._hash === undefined) {
42
42
  const hash = createHash(this._hashFunction);
43
- this._obj.updateHash(hash);
43
+ /** @type {HashableObject} */
44
+ (this._obj).updateHash(hash);
44
45
  this._hash = hash.digest("base64");
46
+ // Drop the captured object once the hash is memoized. The hash is
47
+ // never reset, so we never need `_obj` again — and many callers
48
+ // (e.g. `SourceMapDevToolPlugin`, `RealContentHashPlugin`) capture
49
+ // a heavy `CachedSource` here that would otherwise stay reachable
50
+ // through this etag for the lifetime of the compilation cache.
51
+ this._obj = undefined;
45
52
  }
46
53
  return this._hash;
47
54
  }
@@ -58,7 +58,7 @@ const CssParser = require("./CssParser");
58
58
  /** @typedef {import("../Module").BuildInfo} BuildInfo */
59
59
  /** @typedef {import("../Module").RuntimeRequirements} RuntimeRequirements */
60
60
  /** @typedef {import("../Template").RuntimeTemplate} RuntimeTemplate */
61
- /** @typedef {import("../TemplatedPathPlugin").TemplatePath} TemplatePath */
61
+ /** @typedef {import("../Chunk").ChunkFilenameTemplate} ChunkFilenameTemplate */
62
62
  /** @typedef {import("../util/Hash")} Hash */
63
63
  /** @typedef {import("../Module").BuildMeta} BuildMeta */
64
64
 
@@ -1152,7 +1152,7 @@ class CssModulesPlugin {
1152
1152
  * Gets chunk filename template.
1153
1153
  * @param {Chunk} chunk chunk
1154
1154
  * @param {OutputOptions} outputOptions output options
1155
- * @returns {TemplatePath} used filename template
1155
+ * @returns {ChunkFilenameTemplate} used filename template
1156
1156
  */
1157
1157
  static getChunkFilenameTemplate(chunk, outputOptions) {
1158
1158
  if (chunk.cssFilenameTemplate) {
@@ -48,6 +48,22 @@ const RequireResolveHeaderDependency = require("./RequireResolveHeaderDependency
48
48
  * @property {string} context
49
49
  */
50
50
 
51
+ /**
52
+ * Per-`const NAME = require(LITERAL)` binding state used to forward
53
+ * member-access references on `NAME` to the `CommonJsRequireDependency`
54
+ * created for the `require()` call.
55
+ * @typedef {object} RequireBindingData
56
+ * @property {RawReferencedExports} referencedExports mutable list shared with the dependency; pushed to as `NAME.x.y` accesses are walked
57
+ * @property {InstanceType<typeof import("./CommonJsRequireDependency")> | null} dep dependency for the `require()` call (assigned during walk)
58
+ */
59
+
60
+ /** @type {WeakMap<CallExpression, RequireBindingData>} */
61
+ const requireBindingData = new WeakMap();
62
+
63
+ const REQUIRE_BINDING_TAG = Symbol(
64
+ "CommonJsImportsParserPlugin require binding"
65
+ );
66
+
51
67
  const PLUGIN_NAME = "CommonJsImportsParserPlugin";
52
68
 
53
69
  /**
@@ -152,10 +168,18 @@ const createRequireCallHandler = (parser, options, getContext) => {
152
168
  */
153
169
  const processRequireItem = (expr, param) => {
154
170
  if (param.isString()) {
155
- const referencedExports = getRequireReferencedExportsFromDestructuring(
171
+ let referencedExports = getRequireReferencedExportsFromDestructuring(
156
172
  parser,
157
173
  expr
158
174
  );
175
+ const binding = requireBindingData.get(
176
+ /** @type {CallExpression} */ (expr)
177
+ );
178
+ if (binding && !referencedExports) {
179
+ // `const NAME = require(LITERAL)` — let later member-access walks
180
+ // on `NAME` populate the dependency's referenced exports.
181
+ referencedExports = binding.referencedExports;
182
+ }
159
183
  const dep = new CommonJsRequireDependency(
160
184
  /** @type {string} */ (param.string),
161
185
  /** @type {Range} */ (param.range),
@@ -163,6 +187,7 @@ const createRequireCallHandler = (parser, options, getContext) => {
163
187
  referencedExports,
164
188
  /** @type {Range} */ (expr.range)
165
189
  );
190
+ if (binding) binding.dep = dep;
166
191
  dep.loc = /** @type {DependencyLocation} */ (expr.loc);
167
192
  dep.optional = Boolean(parser.scope.inTry);
168
193
  parser.state.current.addDependency(dep);
@@ -662,6 +687,88 @@ class CommonJsImportsParserPlugin {
662
687
  .tap(PLUGIN_NAME, callChainHandler);
663
688
  // #endregion
664
689
 
690
+ // #region Require bound to a const variable
691
+ // Track `const NAME = require(LITERAL)` so that static member accesses on
692
+ // `NAME` (e.g. `NAME.foo`, `NAME.foo()`) are forwarded to the same
693
+ // `CommonJsRequireDependency` as referenced exports — enabling tree
694
+ // shaking of CommonJS modules that are imported into a named binding
695
+ // rather than destructured.
696
+ parser.hooks.preDeclarator.tap(PLUGIN_NAME, (declarator, statement) => {
697
+ if (statement.kind !== "const") return;
698
+ if (declarator.id.type !== "Identifier") return;
699
+ if (!declarator.init || declarator.init.type !== "CallExpression") {
700
+ return;
701
+ }
702
+ const init = declarator.init;
703
+ if (
704
+ init.callee.type !== "Identifier" ||
705
+ init.callee.name !== "require" ||
706
+ init.arguments.length !== 1
707
+ ) {
708
+ return;
709
+ }
710
+ const arg = init.arguments[0];
711
+ if (arg.type !== "Literal" || typeof arg.value !== "string") return;
712
+ // Only attach binding state when `require` resolves to the free
713
+ // `require` (i.e. it isn't shadowed in the current scope).
714
+ const requireInfo = parser.getFreeInfoFromVariable("require");
715
+ if (!requireInfo || requireInfo.name !== "require") return;
716
+ /** @type {RequireBindingData} */
717
+ const binding = {
718
+ referencedExports: [],
719
+ dep: null
720
+ };
721
+ requireBindingData.set(init, binding);
722
+ parser.tagVariable(declarator.id.name, REQUIRE_BINDING_TAG, binding);
723
+ return true;
724
+ });
725
+
726
+ parser.hooks.expression.for(REQUIRE_BINDING_TAG).tap(PLUGIN_NAME, () => {
727
+ const binding =
728
+ /** @type {RequireBindingData} */
729
+ (parser.currentTagData);
730
+ if (binding && binding.dep) {
731
+ // `NAME` is read as a value (not as the object of a static member
732
+ // chain), so we have to assume the whole exports object is used.
733
+ binding.dep.referencedExports = null;
734
+ }
735
+ });
736
+
737
+ parser.hooks.expressionMemberChain
738
+ .for(REQUIRE_BINDING_TAG)
739
+ .tap(PLUGIN_NAME, (_expr, members) => {
740
+ const binding =
741
+ /** @type {RequireBindingData} */
742
+ (parser.currentTagData);
743
+ if (binding && binding.dep && binding.dep.referencedExports) {
744
+ binding.dep.referencedExports.push(members);
745
+ }
746
+ // Returning truthy suppresses the parser's fallback chain (which
747
+ // would otherwise walk `NAME` as a bare expression and trigger our
748
+ // `expression` hook above, marking the whole namespace as used).
749
+ return true;
750
+ });
751
+
752
+ parser.hooks.callMemberChain
753
+ .for(REQUIRE_BINDING_TAG)
754
+ .tap(PLUGIN_NAME, (expr, members) => {
755
+ const binding =
756
+ /** @type {RequireBindingData} */
757
+ (parser.currentTagData);
758
+ if (binding && binding.dep && binding.dep.referencedExports) {
759
+ if (members.length === 0) {
760
+ // `NAME(...)` — calling the require result directly; the
761
+ // whole exports object is observable.
762
+ binding.dep.referencedExports = null;
763
+ } else {
764
+ binding.dep.referencedExports.push(members);
765
+ }
766
+ }
767
+ if (expr.arguments) parser.walkExpressions(expr.arguments);
768
+ return true;
769
+ });
770
+ // #endregion
771
+
665
772
  // #region Require.resolve
666
773
  /**
667
774
  * Processes the provided expr.
@@ -5,6 +5,7 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ const { ASSET_URL_TYPE } = require("../ModuleSourceTypeConstants");
8
9
  const RawDataUrlModule = require("../asset/RawDataUrlModule");
9
10
  const makeSerializable = require("../util/makeSerializable");
10
11
  const memoize = require("../util/memoize");
@@ -208,8 +209,8 @@ CssUrlDependency.Template = class CssUrlDependencyTemplate extends (
208
209
  const data = codeGen.data;
209
210
  if (!data) return "data:,";
210
211
  const url = data.get("url");
211
- if (!url || !url["css-url"]) return "data:,";
212
- return url["css-url"];
212
+ if (!url || !url[ASSET_URL_TYPE]) return "data:,";
213
+ return url[ASSET_URL_TYPE];
213
214
  }
214
215
  };
215
216
 
@@ -92,6 +92,19 @@ module.exports = class HarmonyDetectionParserPlugin {
92
92
  }
93
93
  };
94
94
 
95
+ /**
96
+ * Walks call arguments so import bindings used inside callbacks are
97
+ * still tracked, then skips default AMD/CommonJS handling.
98
+ * @param {import("estree").CallExpression} expr call expression
99
+ * @returns {boolean | undefined} true if in harmony
100
+ */
101
+ const walkArgumentsAndSkipInHarmony = (expr) => {
102
+ if (HarmonyExports.isEnabled(parser.state)) {
103
+ if (expr.arguments) parser.walkExpressions(expr.arguments);
104
+ return true;
105
+ }
106
+ };
107
+
95
108
  const nonHarmonyIdentifiers = ["define", "exports"];
96
109
  for (const identifier of nonHarmonyIdentifiers) {
97
110
  parser.hooks.evaluateTypeof
@@ -100,7 +113,14 @@ module.exports = class HarmonyDetectionParserPlugin {
100
113
  parser.hooks.typeof.for(identifier).tap(PLUGIN_NAME, skipInHarmony);
101
114
  parser.hooks.evaluate.for(identifier).tap(PLUGIN_NAME, nullInHarmony);
102
115
  parser.hooks.expression.for(identifier).tap(PLUGIN_NAME, skipInHarmony);
103
- parser.hooks.call.for(identifier).tap(PLUGIN_NAME, skipInHarmony);
116
+ parser.hooks.call
117
+ .for(identifier)
118
+ .tap(
119
+ PLUGIN_NAME,
120
+ identifier === "define"
121
+ ? walkArgumentsAndSkipInHarmony
122
+ : skipInHarmony
123
+ );
104
124
  }
105
125
  }
106
126
  };
@@ -161,9 +161,6 @@ class HarmonyExportInitFragment extends InitFragment {
161
161
  * @returns {string | Source | undefined} the source code that will be included as initialization code
162
162
  */
163
163
  getContent({ runtimeTemplate, runtimeRequirements }) {
164
- runtimeRequirements.add(RuntimeGlobals.exports);
165
- runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
166
-
167
164
  const unusedPart =
168
165
  this.unusedExports.size > 1
169
166
  ? `/* unused harmony exports ${joinIterableWithComma(
@@ -184,12 +181,14 @@ class HarmonyExportInitFragment extends InitFragment {
184
181
  )}: ${runtimeTemplate.returningFunction(value)}`
185
182
  );
186
183
  }
187
- const definePart =
188
- this.exportMap.size > 0
189
- ? `/* harmony export */ ${RuntimeGlobals.definePropertyGetters}(${
190
- this.exportsArgument
191
- }, {${definitions.join(",")}\n/* harmony export */ });\n`
192
- : "";
184
+ let definePart = "";
185
+ if (this.exportMap.size > 0) {
186
+ runtimeRequirements.add(RuntimeGlobals.exports);
187
+ runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
188
+ definePart = `/* harmony export */ ${RuntimeGlobals.definePropertyGetters}(${
189
+ this.exportsArgument
190
+ }, {${definitions.join(",")}\n/* harmony export */ });\n`;
191
+ }
193
192
  return `${definePart}${unusedPart}`;
194
193
  }
195
194
  }
@@ -4,8 +4,8 @@
4
4
 
5
5
  "use strict";
6
6
 
7
+ const HtmlGenerator = require("../html/HtmlGenerator");
7
8
  const makeSerializable = require("../util/makeSerializable");
8
- const CssUrlDependency = require("./CssUrlDependency");
9
9
  const ModuleDependency = require("./ModuleDependency");
10
10
 
11
11
  /** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
@@ -101,19 +101,8 @@ HtmlInlineScriptDependency.Template = class HtmlInlineScriptDependencyTemplate e
101
101
 
102
102
  if (entrypoint) {
103
103
  const chunk = /** @type {Chunk} */ (entrypoint.getEntrypointChunk());
104
- const outputOptions = runtimeTemplate.outputOptions;
105
- const filenameTemplate =
106
- chunk.filenameTemplate ||
107
- (chunk.canBeInitial()
108
- ? outputOptions.filename
109
- : outputOptions.chunkFilename);
110
-
111
- const filename = compilation.getPath(filenameTemplate, {
112
- chunk,
113
- contentHashType: "javascript"
114
- });
115
-
116
- url = `${CssUrlDependency.PUBLIC_PATH_AUTO}${filename}`;
104
+ // Defer chunk-URL substitution to renderManifest — chunk hashes aren't ready yet.
105
+ url = HtmlGenerator.makeChunkUrlSentinel(chunk, "javascript");
117
106
  }
118
107
 
119
108
  // Insert ` src="…"` right after `<script` so the inline body is
@@ -10,12 +10,15 @@ const ModuleDependency = require("./ModuleDependency");
10
10
 
11
11
  /** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
12
12
  /** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */
13
+ /** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
13
14
  /** @typedef {import("../Dependency")} Dependency */
14
15
  /** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
15
16
  /** @typedef {import("../Module")} Module */
17
+ /** @typedef {import("../Module").BuildInfo} BuildInfo */
16
18
  /** @typedef {import("../javascript/JavascriptParser").Range} Range */
17
19
  /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
18
20
  /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
21
+ /** @typedef {import("../util/Hash")} Hash */
19
22
  /** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
20
23
 
21
24
  /**
@@ -45,6 +48,20 @@ class HtmlInlineStyleDependency extends ModuleDependency {
45
48
  return "html-style";
46
49
  }
47
50
 
51
+ /**
52
+ * Updates the hash with the data contributed by this instance.
53
+ * @param {Hash} hash hash to be updated
54
+ * @param {UpdateHashContext} context context
55
+ * @returns {void}
56
+ */
57
+ updateHash(hash, context) {
58
+ // Recurse so the inline CSS's transitive deps (e.g. `url(asset)`) propagate up.
59
+ const { chunkGraph } = context;
60
+ const module = chunkGraph.moduleGraph.getModule(this);
61
+ if (!module) return;
62
+ module.updateHash(hash, context);
63
+ }
64
+
48
65
  /**
49
66
  * Serializes this instance into the provided serializer context.
50
67
  * @param {ObjectSerializerContext} context context