@depup/webpack 5.110.1-depup.0 → 5.110.3-depup.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +4 -4
  2. package/changes.json +3 -3
  3. package/lib/ChunkGraph.js +20 -18
  4. package/lib/Compilation.js +1 -1
  5. package/lib/ConcatenationScope.js +25 -35
  6. package/lib/DotenvPlugin.js +41 -13
  7. package/lib/ExportsInfo.js +10 -0
  8. package/lib/FlagDependencyUsagePlugin.js +8 -2
  9. package/lib/NormalModule.js +13 -20
  10. package/lib/RuntimePlugin.js +3 -0
  11. package/lib/RuntimeTemplate.js +437 -432
  12. package/lib/async-modules/AsyncModuleHelpers.js +10 -4
  13. package/lib/config/defaults.js +26 -16
  14. package/lib/config/normalization.js +18 -8
  15. package/lib/css/CssLoadingRuntimeModule.js +32 -13
  16. package/lib/css/CssModulesPlugin.js +9 -17
  17. package/lib/css/data.js +13 -3
  18. package/lib/css/syntax.js +78 -10
  19. package/lib/dependencies/CommonJsRequireDependency.js +18 -4
  20. package/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +20 -7
  21. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +10 -4
  22. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +2 -0
  23. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +143 -17
  24. package/lib/dependencies/HarmonyImportDependency.js +94 -41
  25. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +93 -14
  26. package/lib/dependencies/HarmonyImportSideEffectDependency.js +114 -0
  27. package/lib/dependencies/HtmlEntryDependency.js +12 -2
  28. package/lib/dependencies/ImportContextDependency.js +43 -3
  29. package/lib/dependencies/ImportDependency.js +8 -29
  30. package/lib/dependencies/ImportParserPlugin.js +24 -14
  31. package/lib/dependencies/RequireHeaderDependency.js +20 -21
  32. package/lib/dependencies/WorkerAndWorkletPlugin.js +1 -0
  33. package/lib/dependencies/WorkerDependency.js +6 -12
  34. package/lib/dependencies/WorkletDependency.js +7 -11
  35. package/lib/dependencies/importOptionsCheck.js +47 -0
  36. package/lib/errors/DotenvFileError.js +29 -0
  37. package/lib/errors/ImportedBindingAssignmentError.js +30 -0
  38. package/lib/esm/ModuleChunkLoadingPlugin.js +6 -9
  39. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +7 -1
  40. package/lib/html/HtmlModulesPlugin.js +84 -38
  41. package/lib/html/syntax.js +417 -169
  42. package/lib/javascript/JavascriptModulesPlugin.js +5 -10
  43. package/lib/loaders/LoaderRunner.js +33 -5
  44. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +8 -15
  45. package/lib/optimize/ConcatenatedModule.js +46 -7
  46. package/lib/optimize/ConstExportsPlugin.js +5 -0
  47. package/lib/optimize/InlineExports.js +121 -0
  48. package/lib/optimize/RealContentHashPlugin.js +111 -35
  49. package/lib/prefetch/ResourceHintPlugin.js +12 -13
  50. package/lib/runtime/AsyncModuleRuntimeModule.js +5 -1
  51. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +11 -1
  52. package/lib/schemes/HttpUriPlugin.js +22 -5
  53. package/lib/serialization/FileMiddleware.js +15 -2
  54. package/lib/typescript/TypeScriptPlugin.js +8 -10
  55. package/lib/util/ArrayQueue.js +3 -3
  56. package/lib/util/SourceProcessor.js +24 -8
  57. package/lib/util/URLAbsoluteSpecifier.js +3 -1
  58. package/lib/util/conventions.js +5 -1
  59. package/lib/util/createMappings.js +25 -3
  60. package/lib/util/internalSerializables.js +2 -0
  61. package/lib/util/removeBOM.js +82 -1
  62. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +5 -3
  63. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +5 -3
  64. package/lib/wasm-async/UniversalCompileAsyncWasmPlugin.js +7 -12
  65. package/lib/web/FetchCompileAsyncWasmPlugin.js +10 -6
  66. package/lib/web/FetchCompileWasmPlugin.js +4 -2
  67. package/package.json +7 -7
  68. package/schemas/WebpackOptions.check.js +1 -1
  69. package/schemas/WebpackOptions.json +9 -10
  70. package/types.d.ts +95 -27
@@ -13,6 +13,8 @@ const makeSerializable = require("../util/makeSerializable");
13
13
  const HarmonyImportDependency = require("./HarmonyImportDependency");
14
14
  const { ImportPhaseUtils } = require("./ImportPhase");
15
15
 
16
+ const { ExportPresenceModes } = HarmonyImportDependency;
17
+
16
18
  /** @import { ReplaceSource } from "webpack-sources" */
17
19
  /** @import { GetConditionFn, LazyUntil } from "../Dependency" */
18
20
  /** @import { DependencyTemplateContext } from "../DependencyTemplate" */
@@ -20,6 +22,19 @@ const { ImportPhaseUtils } = require("./ImportPhase");
20
22
  /** @import { ConnectionState } from "../ModuleGraphConnection" */
21
23
  /** @import { ImportAttributes } from "../javascript/JavascriptParser" */
22
24
  /** @import { ImportPhaseType } from "./ImportPhase" */
25
+ /** @import { Ids, ExportPresenceMode } from "./HarmonyImportDependency" */
26
+ /** @import { JavascriptModuleBuildMeta } from "../javascript/JavascriptModule" */
27
+ /** @import WebpackError from "../errors/WebpackError" */
28
+ /** @import { ObjectSerializerContext, ObjectDeserializerContext } from "../serialization/ObjectMiddleware" */
29
+
30
+ /**
31
+ * Specifiers the module declares but never reads, with the presence level to
32
+ * report them at. Allocated only for a module that has one, so the common
33
+ * import pays a single empty slot.
34
+ * @typedef {object} UnusedSpecifiers
35
+ * @property {ExportPresenceMode} exportPresenceMode
36
+ * @property {[Ids, string][]} specifiers
37
+ */
23
38
 
24
39
  class HarmonyImportSideEffectDependency extends HarmonyImportDependency {
25
40
  /**
@@ -31,12 +46,111 @@ class HarmonyImportSideEffectDependency extends HarmonyImportDependency {
31
46
  */
32
47
  constructor(request, sourceOrder, phase, attributes) {
33
48
  super(request, sourceOrder, phase, attributes);
49
+ /** @type {UnusedSpecifiers | undefined} */
50
+ this.unusedSpecifiers = undefined;
34
51
  }
35
52
 
36
53
  get type() {
37
54
  return "harmony side effect evaluation";
38
55
  }
39
56
 
57
+ /**
58
+ * Returns warnings.
59
+ * @param {ModuleGraph} moduleGraph module graph
60
+ * @returns {WebpackError[] | null | undefined} warnings
61
+ */
62
+ getWarnings(moduleGraph) {
63
+ if (
64
+ this._getEffectiveExportPresenceLevel(moduleGraph) !==
65
+ ExportPresenceModes.WARN
66
+ ) {
67
+ return null;
68
+ }
69
+ return this._getUnusedSpecifierErrors(moduleGraph);
70
+ }
71
+
72
+ /**
73
+ * Get effective export presence level.
74
+ * @param {ModuleGraph} moduleGraph module graph
75
+ * @returns {ExportPresenceMode} effective mode
76
+ */
77
+ _getEffectiveExportPresenceLevel(moduleGraph) {
78
+ if (this.unusedSpecifiers === undefined) return ExportPresenceModes.NONE;
79
+ const mode = this.unusedSpecifiers.exportPresenceMode;
80
+ if (mode !== ExportPresenceModes.AUTO) return mode;
81
+ const buildMeta =
82
+ /** @type {JavascriptModuleBuildMeta} */
83
+ (
84
+ /** @type {Module} */
85
+ (moduleGraph.getParentModule(this)).buildMeta
86
+ );
87
+ return buildMeta.strictHarmonyModule
88
+ ? ExportPresenceModes.ERROR
89
+ : ExportPresenceModes.WARN;
90
+ }
91
+
92
+ /**
93
+ * Returns errors.
94
+ * @param {ModuleGraph} moduleGraph module graph
95
+ * @returns {WebpackError[] | null | undefined} errors
96
+ */
97
+ getErrors(moduleGraph) {
98
+ if (
99
+ this._getEffectiveExportPresenceLevel(moduleGraph) !==
100
+ ExportPresenceModes.ERROR
101
+ ) {
102
+ return null;
103
+ }
104
+ return this._getUnusedSpecifierErrors(moduleGraph);
105
+ }
106
+
107
+ /**
108
+ * Linking errors for specifiers the module declares but never references.
109
+ * The spec resolves every import entry, so a name that does not exist is a
110
+ * link error whether or not the binding is read.
111
+ * @param {ModuleGraph} moduleGraph module graph
112
+ * @returns {WebpackError[] | undefined} errors
113
+ */
114
+ _getUnusedSpecifierErrors(moduleGraph) {
115
+ // Both callers resolve the presence level first, which is NONE without
116
+ // specifiers, so this only runs when there are some.
117
+ const { specifiers } = /** @type {UnusedSpecifiers} */ (
118
+ this.unusedSpecifiers
119
+ );
120
+ /** @type {WebpackError[] | undefined} */
121
+ let errors;
122
+ for (const [ids, name] of specifiers) {
123
+ const linkingErrors = this.getLinkingErrors(
124
+ moduleGraph,
125
+ ids,
126
+ `(imported as '${name}')`
127
+ );
128
+ if (linkingErrors) {
129
+ if (errors === undefined) errors = linkingErrors;
130
+ else errors.push(...linkingErrors);
131
+ }
132
+ }
133
+ return errors;
134
+ }
135
+
136
+ /**
137
+ * Serializes this instance into the provided serializer context.
138
+ * @param {ObjectSerializerContext} context context
139
+ */
140
+ serialize(context) {
141
+ context.write(this.unusedSpecifiers);
142
+ super.serialize(context);
143
+ }
144
+
145
+ /**
146
+ * Restores this instance from the provided deserializer context.
147
+ * @param {ObjectDeserializerContext} context context
148
+ */
149
+ deserialize(context) {
150
+ this.unusedSpecifiers = context.read();
151
+ super.deserialize(context);
152
+ }
153
+
40
154
  /**
41
155
  * Returns the export name this dependency requests from its target module (lazy barrel optimization).
42
156
  * @returns {string | true | null} export name, true for all exports, null for none
@@ -194,7 +194,12 @@ const getEntrypointChunksInLoadOrder = (entrypoint) => {
194
194
  const chunksLoadedByAncestorTags = new Set();
195
195
  /** @type {Set<import("../ChunkGroup")>} */
196
196
  const visitedGroups = new Set();
197
- const walk = (/** @type {import("../ChunkGroup")} */ group) => {
197
+ /**
198
+ * Collects the chunks an ancestor entry's own tags already load.
199
+ * @param {import("../ChunkGroup")} group chunk group to walk up from
200
+ * @returns {void}
201
+ */
202
+ const walk = (group) => {
198
203
  if (visitedGroups.has(group)) return;
199
204
  visitedGroups.add(group);
200
205
  for (const parent of group.parentsIterable) {
@@ -220,7 +225,12 @@ const getEntrypointChunksInLoadOrder = (entrypoint) => {
220
225
  const ordered = [];
221
226
  /** @type {Set<Chunk>} */
222
227
  const seen = new Set();
223
- const push = (/** @type {Chunk | null | undefined} */ chunk) => {
228
+ /**
229
+ * Appends a chunk once, skipping the ones an ancestor entry already loads.
230
+ * @param {Chunk | null | undefined} chunk chunk to append
231
+ * @returns {void}
232
+ */
233
+ const push = (chunk) => {
224
234
  if (!chunk || seen.has(chunk) || chunk === entryChunk) return;
225
235
  if (chunksLoadedByAncestorTags.has(chunk)) return;
226
236
  seen.add(chunk);
@@ -8,11 +8,13 @@
8
8
  const makeSerializable = require("../util/makeSerializable");
9
9
  const ContextDependency = require("./ContextDependency");
10
10
  const ContextDependencyTemplateAsRequireCall = require("./ContextDependencyTemplateAsRequireCall");
11
+ const importOptionsCheck = require("./importOptionsCheck");
11
12
 
12
13
  /** @import { Range } from "../javascript/JavascriptParser" */
13
- /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext<[Range]>} ObjectDeserializerContext */
14
- /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext<[Range]>} ObjectSerializerContext */
14
+ /** @import { ObjectDeserializerContext, ObjectSerializerContext } from "../serialization/ObjectMiddleware" */
15
15
  /** @import { ContextDependencyOptions } from "./ContextDependency" */
16
+ /** @import { ReplaceSource } from "webpack-sources" */
17
+ /** @import { DependencyTemplateContext } from "../DependencyTemplate" */
16
18
 
17
19
  class ImportContextDependency extends ContextDependency {
18
20
  /**
@@ -26,6 +28,8 @@ class ImportContextDependency extends ContextDependency {
26
28
 
27
29
  this.range = range;
28
30
  this.valueRange = valueRange;
31
+ /** @type {Range | undefined} */
32
+ this.optionsRange = undefined;
29
33
  }
30
34
 
31
35
  get type() {
@@ -56,6 +60,7 @@ class ImportContextDependency extends ContextDependency {
56
60
  */
57
61
  serialize(context) {
58
62
  context.write(this.valueRange);
63
+ context.write(this.optionsRange);
59
64
 
60
65
  super.serialize(context);
61
66
  }
@@ -66,6 +71,7 @@ class ImportContextDependency extends ContextDependency {
66
71
  */
67
72
  deserialize(context) {
68
73
  this.valueRange = context.read();
74
+ this.optionsRange = context.read();
69
75
 
70
76
  super.deserialize(context.rest);
71
77
  }
@@ -76,6 +82,40 @@ makeSerializable(
76
82
  "webpack/lib/dependencies/ImportContextDependency"
77
83
  );
78
84
 
79
- ImportContextDependency.Template = ContextDependencyTemplateAsRequireCall;
85
+ ImportContextDependency.Template = class ImportContextDependencyTemplate extends (
86
+ ContextDependencyTemplateAsRequireCall
87
+ ) {
88
+ /**
89
+ * Rewrites the call around its request, dropping anything the original one
90
+ * carried after it. Overridden where a later argument must be kept.
91
+ * @param {ContextDependency} dep the dependency
92
+ * @param {ReplaceSource} source the current replace source which can be modified
93
+ * @param {string} moduleExports the expression the request is passed to
94
+ * @param {DependencyTemplateContext} templateContext the context object
95
+ * @returns {void}
96
+ */
97
+ replaceCall(dep, source, moduleExports, templateContext) {
98
+ const optionsRange = /** @type {ImportContextDependency} */ (dep)
99
+ .optionsRange;
100
+ if (optionsRange === undefined) {
101
+ super.replaceCall(dep, source, moduleExports, templateContext);
102
+ return;
103
+ }
104
+ // Request then options, in that order; their own source is kept so
105
+ // nested dependencies in them still get their replacements.
106
+ const range = /** @type {Range} */ (dep.range);
107
+ const valueRange = /** @type {Range} */ (dep.valueRange);
108
+ const check = importOptionsCheck(
109
+ templateContext.runtimeTemplate,
110
+ ["r", "o"],
111
+ `${moduleExports}(r)`
112
+ );
113
+ source.replace(range[0], valueRange[0] - 1, `(${check})(`);
114
+ // The options range excludes any parentheses the source had, so a comma
115
+ // expression would otherwise split into arguments of its own.
116
+ source.replace(valueRange[1], optionsRange[0] - 1, ", (");
117
+ source.replace(optionsRange[1], range[1] - 1, "))");
118
+ }
119
+ };
80
120
 
81
121
  module.exports = ImportContextDependency;
@@ -6,11 +6,11 @@
6
6
  "use strict";
7
7
 
8
8
  const Dependency = require("../Dependency");
9
- const Template = require("../Template");
10
9
  const makeSerializable = require("../util/makeSerializable");
11
10
  const HarmonyImportGuard = require("./HarmonyImportGuard");
12
11
  const { ImportPhaseUtils } = require("./ImportPhase");
13
12
  const ModuleDependency = require("./ModuleDependency");
13
+ const importOptionsCheck = require("./importOptionsCheck");
14
14
 
15
15
  /** @import { ReplaceSource } from "webpack-sources" */
16
16
  /** @import AsyncDependenciesBlock from "../AsyncDependenciesBlock" */
@@ -226,35 +226,14 @@ ImportDependency.Template = class ImportDependencyTemplate extends (
226
226
  }
227
227
 
228
228
  // A non-static second argument must still be evaluated (for its side
229
- // effects and evaluation order) and validated per spec. Keep it in place
230
- // and wrap it in an inline validator that mirrors the runtime checks of
231
- // the spec's `import(specifier, options)` evaluation.
229
+ // effects and evaluation order) and checked per spec, so keep it in place
230
+ // and wrap it.
232
231
  if (dep.optionsRange) {
233
- const validator = runtimeTemplate.basicFunction("o", [
234
- "try {",
235
- Template.indent([
236
- "if (o !== undefined) {",
237
- Template.indent([
238
- 'if ((typeof o !== "object" && typeof o !== "function") || o === null) throw new TypeError("The second argument to import() must be an object");',
239
- 'var a = o["with"];',
240
- "if (a !== undefined) {",
241
- Template.indent([
242
- 'if ((typeof a !== "object" && typeof a !== "function") || a === null) throw new TypeError("The \'with\' option must be an object");',
243
- "for (var k = Object.keys(a), i = 0; i < k.length; i++) {",
244
- Template.indent([
245
- 'if (typeof a[k[i]] !== "string") throw new TypeError("Import attribute values must be strings");'
246
- ]),
247
- "}"
248
- ]),
249
- "}"
250
- ]),
251
- "}"
252
- ]),
253
- "} catch (e) { return Promise.reject(e); }",
254
- `return ${content};`
255
- ]);
256
- source.replace(dep.range[0], dep.optionsRange[0] - 1, `(${validator})(`);
257
- source.replace(dep.optionsRange[1], dep.range[1] - 1, ")");
232
+ const check = importOptionsCheck(runtimeTemplate, ["o"], content);
233
+ // The options range excludes any parentheses the source had, so a
234
+ // comma expression would otherwise split into arguments of its own.
235
+ source.replace(dep.range[0], dep.optionsRange[0] - 1, `(${check})((`);
236
+ source.replace(dep.optionsRange[1], dep.range[1] - 1, "))");
258
237
  return;
259
238
  }
260
239
 
@@ -209,20 +209,18 @@ const isStaticStringAttributes = (node) => {
209
209
  : key.type === "Literal"
210
210
  ? key.value
211
211
  : undefined;
212
- if (keyName === "with" || keyName === "assert") {
213
- const value = prop.value;
214
- if (value.type !== "ObjectExpression") return false;
215
- for (const attr of value.properties) {
216
- if (attr.type !== "Property" || attr.kind !== "init" || attr.computed) {
217
- return false;
218
- }
219
- const attrValue = attr.value;
220
- if (
221
- attrValue.type !== "Literal" ||
222
- typeof attrValue.value !== "string"
223
- ) {
224
- return false;
225
- }
212
+ // Any other key is an expression webpack cannot account for, and its
213
+ // value still evaluates, so the argument has to stay.
214
+ if (keyName !== "with" && keyName !== "assert") return false;
215
+ const value = prop.value;
216
+ if (value.type !== "ObjectExpression") return false;
217
+ for (const attr of value.properties) {
218
+ if (attr.type !== "Property" || attr.kind !== "init" || attr.computed) {
219
+ return false;
220
+ }
221
+ const attrValue = attr.value;
222
+ if (attrValue.type !== "Literal" || typeof attrValue.value !== "string") {
223
+ return false;
226
224
  }
227
225
  }
228
226
  }
@@ -676,6 +674,18 @@ class ImportParserPlugin {
676
674
  parser
677
675
  );
678
676
  if (!dep) return;
677
+ // The context module ignores the options argument, but the spec
678
+ // evaluates it, so anything but a static attributes object stays.
679
+ const optionsNode = expr.options;
680
+ if (
681
+ optionsNode &&
682
+ optionsNode.range &&
683
+ !isStaticStringAttributes(optionsNode)
684
+ ) {
685
+ /** @type {ImportContextDependency} */ (dep).optionsRange =
686
+ /** @type {Range} */ (optionsNode.range);
687
+ parser.walkExpression(optionsNode);
688
+ }
679
689
  dep.loc = parser.getLocation(expr);
680
690
  dep.optional = Boolean(parser.scope.inTry);
681
691
  parser.state.current.addDependency(dep);
@@ -76,30 +76,29 @@ RequireHeaderDependency.Template = class RequireHeaderDependencyTemplate extends
76
76
  { moduleGraph, runtime, runtimeRequirements, concatenationScope }
77
77
  ) {
78
78
  const dep = /** @type {RequireHeaderDependency} */ (dependency);
79
-
80
- // the paired require dependency already replaced the whole call
81
- if (
82
- concatenationScope !== undefined &&
83
- concatenationScope.isInsideReplacedRequire(dep.range[0])
84
- ) {
85
- return;
86
- }
87
-
88
79
  const requireDep = dep.requireDependency;
89
- // Skip when the paired call became `0`; dead-branch still needs the header.
90
80
  if (requireDep) {
91
81
  const connection = moduleGraph.getConnection(requireDep);
92
- if (
93
- connection &&
94
- !connection.isTargetActive(runtime) &&
95
- requireDep.isEvaluationOnly()
96
- ) {
97
- const guards = requireDep.branchGuards;
98
- if (
99
- guards === undefined ||
100
- !HarmonyImportGuard.isDeadByGuards(guards, moduleGraph, runtime)
101
- ) {
102
- return;
82
+ if (connection) {
83
+ if (connection.isTargetActive(runtime)) {
84
+ if (
85
+ concatenationScope !== undefined &&
86
+ requireDep.rendersAsConcatenatedReference(
87
+ connection,
88
+ concatenationScope
89
+ )
90
+ ) {
91
+ return;
92
+ }
93
+ } else if (requireDep.isEvaluationOnly()) {
94
+ // Skip when the paired call became `0`; dead-branch still needs the header.
95
+ const guards = requireDep.branchGuards;
96
+ if (
97
+ guards === undefined ||
98
+ !HarmonyImportGuard.isDeadByGuards(guards, moduleGraph, runtime)
99
+ ) {
100
+ return;
101
+ }
103
102
  }
104
103
  }
105
104
  }
@@ -753,6 +753,7 @@ class WorkerAndWorkletPlugin {
753
753
  ) {
754
754
  return;
755
755
  }
756
+ settings.used = true;
756
757
  return handle(expr);
757
758
  });
758
759
  } else {
@@ -136,19 +136,13 @@ WorkerDependency.Template = class WorkerDependencyTemplate extends (
136
136
  // and webpack itself can statically follow the worker. A resource hint doesn't
137
137
  // block it: the `<link>` is emitted at chunk startup instead of wrapping the href,
138
138
  // which would turn the specifier into a non-analyzable expression.
139
- const analyzableSpecifier = runtimeTemplate.supportsAnalyzable(
140
- "url",
139
+ const analyzableSpecifier = runtimeTemplate.getAnalyzableWorkerUrl(
140
+ dep.options.publicPath,
141
+ chunk,
142
+ templateContext.module,
141
143
  chunkGraph,
142
- templateContext.module
143
- )
144
- ? runtimeTemplate._getAnalyzableChunkSpecifier(
145
- dep.options.publicPath,
146
- chunk,
147
- templateContext.module,
148
- chunkGraph,
149
- runtimeRequirements
150
- )
151
- : null;
144
+ runtimeRequirements
145
+ );
152
146
 
153
147
  if (analyzableSpecifier !== null) {
154
148
  // No `<link>` helper is asked for here: this form emits no call, and
@@ -140,17 +140,13 @@ WorkletDependency.Template = class WorkletDependencyTemplate extends (
140
140
  // import.meta.url)` form (literal specifier, no runtime helpers) so other bundlers
141
141
  // and webpack itself can statically follow the worklet. The worklet chunk links its
142
142
  // splits via native `import`, so only the entry chunk is referenced.
143
- const analyzableSpecifier =
144
- runtimeTemplate.supportsAnalyzable("url", chunkGraph, module) &&
145
- entryChunk.id !== null
146
- ? runtimeTemplate._getAnalyzableChunkSpecifier(
147
- dep.options.publicPath,
148
- entryChunk,
149
- module,
150
- chunkGraph,
151
- runtimeRequirements
152
- )
153
- : null;
143
+ const analyzableSpecifier = runtimeTemplate.getAnalyzableWorkerUrl(
144
+ dep.options.publicPath,
145
+ entryChunk,
146
+ module,
147
+ chunkGraph,
148
+ runtimeRequirements
149
+ );
154
150
  if (analyzableSpecifier !== null) {
155
151
  source.replace(
156
152
  dep.callRange[0],
@@ -0,0 +1,47 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Alexander Akait @alexander-akait
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const Template = require("../Template");
9
+
10
+ /** @import RuntimeTemplate from "../RuntimeTemplate" */
11
+
12
+ /**
13
+ * Wraps an import so its arguments evaluate in source order and the options are
14
+ * checked, rejecting rather than throwing. The last parameter holds them.
15
+ * @param {RuntimeTemplate} runtimeTemplate the runtime template
16
+ * @param {string[]} parameters parameter names, the options one last
17
+ * @param {string} content the import expression to return once the check passes
18
+ * @returns {string} the wrapping function
19
+ */
20
+ const importOptionsCheck = (runtimeTemplate, parameters, content) => {
21
+ const options = parameters[parameters.length - 1];
22
+ return runtimeTemplate.basicFunction(parameters.join(", "), [
23
+ "try {",
24
+ Template.indent([
25
+ `if (${options} !== undefined) {`,
26
+ Template.indent([
27
+ `if ((typeof ${options} !== "object" && typeof ${options} !== "function") || ${options} === null) throw new TypeError("The second argument to import() must be an object");`,
28
+ `var a = ${options}["with"];`,
29
+ "if (a !== undefined) {",
30
+ Template.indent([
31
+ 'if ((typeof a !== "object" && typeof a !== "function") || a === null) throw new TypeError("The \'with\' option must be an object");',
32
+ "for (var k = Object.keys(a), i = 0; i < k.length; i++) {",
33
+ Template.indent([
34
+ 'if (typeof a[k[i]] !== "string") throw new TypeError("Import attribute values must be strings");'
35
+ ]),
36
+ "}"
37
+ ]),
38
+ "}"
39
+ ]),
40
+ "}"
41
+ ]),
42
+ "} catch (e) { return Promise.reject(e); }",
43
+ `return ${content};`
44
+ ]);
45
+ };
46
+
47
+ module.exports = importOptionsCheck;
@@ -0,0 +1,29 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Alexander Akait @alexander-akait
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const WebpackError = require("./WebpackError");
9
+
10
+ /**
11
+ * Error for a dotenv file that exists but could not be read. An absent file is
12
+ * normal and reported through `missingDependencies` instead.
13
+ */
14
+ class DotenvFileError extends WebpackError {
15
+ /**
16
+ * @param {string} file path of the dotenv file
17
+ * @param {Error} error underlying file system error
18
+ */
19
+ constructor(file, error) {
20
+ super(`Unable to read the dotenv file ${file}\n${error.message}`);
21
+
22
+ this.name = "DotenvFileError";
23
+ /** @type {string} */
24
+ this.file = file;
25
+ this.error = error;
26
+ }
27
+ }
28
+
29
+ module.exports = DotenvFileError;
@@ -0,0 +1,30 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Alexander Akait @alexander-akait
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const makeSerializable = require("../util/makeSerializable");
9
+ const WebpackError = require("./WebpackError");
10
+
11
+ class ImportedBindingAssignmentError extends WebpackError {
12
+ /**
13
+ * Creates an instance of ImportedBindingAssignmentError.
14
+ * @param {string} name the local name of the namespace binding
15
+ */
16
+ constructor(name) {
17
+ super(
18
+ `Assignment to the imported binding '${name}'. A namespace import is immutable, so this throws a TypeError where the module is a real ES module.`
19
+ );
20
+
21
+ this.name = "ImportedBindingAssignmentError";
22
+ }
23
+ }
24
+
25
+ makeSerializable(
26
+ ImportedBindingAssignmentError,
27
+ "webpack/lib/errors/ImportedBindingAssignmentError"
28
+ );
29
+
30
+ module.exports = ImportedBindingAssignmentError;
@@ -120,15 +120,12 @@ class ModuleChunkLoadingPlugin {
120
120
  if (!isEnabledForChunk(chunk)) return;
121
121
  // A baked url carries where the chunk is, so neither is read for it.
122
122
  // Asked as the runtime module asks, so the two always agree.
123
- if (
124
- compilation.runtimeTemplate.analyzableChunkScriptUrls(
125
- chunk,
126
- chunkGraph,
127
- set
128
- ) !== null
129
- ) {
130
- return;
131
- }
123
+ const baked = compilation.runtimeTemplate.analyzableChunkScriptUrls(
124
+ chunk,
125
+ chunkGraph,
126
+ set
127
+ );
128
+ if (baked !== null && baked.complete) return;
132
129
  set.add(RuntimeGlobals.publicPath);
133
130
  set.add(RuntimeGlobals.getChunkScriptFilename);
134
131
  });
@@ -129,7 +129,7 @@ class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
129
129
  chunk.hasChildByOrder(chunkGraph, "preload", true, chunkHasJs);
130
130
  // Under module output each hinted chunk is a known file, so the urls are written
131
131
  // out and read by id rather than built from the chunk id at runtime.
132
- const chunkUrls =
132
+ const bakedChunkUrls =
133
133
  withPrefetch || withPreload
134
134
  ? runtimeTemplate.analyzableChunkScriptUrls(
135
135
  chunk,
@@ -138,6 +138,12 @@ class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
138
138
  this
139
139
  )
140
140
  : null;
141
+ // A hint is best-effort, so an id an incomplete map lacks is not worth a per-id
142
+ // fallback — only a complete map replaces the runtime name lookup.
143
+ const chunkUrls =
144
+ bakedChunkUrls !== null && bakedChunkUrls.complete
145
+ ? bakedChunkUrls.urls
146
+ : null;
141
147
  const conditionMap = chunkGraph.getChunkConditionMap(chunk, chunkHasJs);
142
148
  const hasJsMatcher = compileBooleanMatcher(conditionMap);
143
149
  const initialChunkIds = getInitialChunkIds(chunk, chunkGraph, chunkHasJs);