webpack 5.21.0 → 5.23.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 (61) hide show
  1. package/lib/ChunkGraph.js +3 -2
  2. package/lib/CodeGenerationResults.js +2 -1
  3. package/lib/Compilation.js +91 -40
  4. package/lib/EvalDevToolModulePlugin.js +4 -0
  5. package/lib/EvalSourceMapDevToolPlugin.js +4 -0
  6. package/lib/ExportsInfo.js +1 -0
  7. package/lib/ExternalModule.js +8 -7
  8. package/lib/FlagDependencyUsagePlugin.js +7 -6
  9. package/lib/JavascriptMetaInfoPlugin.js +62 -0
  10. package/lib/LibManifestPlugin.js +1 -13
  11. package/lib/Module.js +2 -3
  12. package/lib/MultiCompiler.js +170 -77
  13. package/lib/MultiStats.js +9 -6
  14. package/lib/NormalModuleFactory.js +135 -22
  15. package/lib/RuntimeGlobals.js +5 -0
  16. package/lib/RuntimePlugin.js +10 -1
  17. package/lib/Watching.js +70 -27
  18. package/lib/WebpackOptionsApply.js +7 -7
  19. package/lib/config/defaults.js +26 -10
  20. package/lib/config/target.js +1 -1
  21. package/lib/container/ContainerEntryModule.js +2 -1
  22. package/lib/dependencies/AMDDefineDependency.js +1 -1
  23. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +8 -0
  24. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +2 -1
  25. package/lib/dependencies/HarmonyExportInitFragment.js +2 -3
  26. package/lib/dependencies/HarmonyImportSpecifierDependency.js +9 -2
  27. package/lib/dependencies/LoaderPlugin.js +9 -2
  28. package/lib/dependencies/URLDependency.js +35 -13
  29. package/lib/dependencies/URLPlugin.js +3 -1
  30. package/lib/dependencies/WorkerPlugin.js +7 -1
  31. package/lib/hmr/LazyCompilationPlugin.js +2 -2
  32. package/lib/index.js +1 -0
  33. package/lib/javascript/CommonJsChunkFormatPlugin.js +15 -4
  34. package/lib/javascript/JavascriptModulesPlugin.js +143 -78
  35. package/lib/javascript/JavascriptParser.js +1 -0
  36. package/lib/json/JsonGenerator.js +29 -8
  37. package/lib/library/AbstractLibraryPlugin.js +108 -32
  38. package/lib/library/AmdLibraryPlugin.js +12 -6
  39. package/lib/library/AssignLibraryPlugin.js +137 -26
  40. package/lib/library/EnableLibraryPlugin.js +18 -7
  41. package/lib/library/ExportPropertyLibraryPlugin.js +16 -5
  42. package/lib/library/JsonpLibraryPlugin.js +3 -1
  43. package/lib/library/ModuleLibraryPlugin.js +100 -0
  44. package/lib/library/SystemLibraryPlugin.js +1 -1
  45. package/lib/node/NodeTargetPlugin.js +1 -1
  46. package/lib/optimize/ConcatenatedModule.js +54 -35
  47. package/lib/optimize/InnerGraph.js +5 -4
  48. package/lib/runtime/GetChunkFilenameRuntimeModule.js +2 -3
  49. package/lib/runtime/RelativeUrlRuntimeModule.js +41 -0
  50. package/lib/runtime/StartupChunkDependenciesPlugin.js +1 -0
  51. package/lib/serialization/ObjectMiddleware.js +34 -19
  52. package/lib/stats/DefaultStatsFactoryPlugin.js +1 -12
  53. package/lib/stats/DefaultStatsPrinterPlugin.js +19 -6
  54. package/lib/util/IterableHelpers.js +46 -0
  55. package/lib/util/LazyBucketSortedSet.js +3 -2
  56. package/lib/util/SetHelpers.js +11 -0
  57. package/lib/webpack.js +56 -50
  58. package/package.json +3 -3
  59. package/schemas/WebpackOptions.json +8 -1
  60. package/types.d.ts +38 -7
  61. package/lib/FlagUsingEvalPlugin.js +0 -44
@@ -6,8 +6,10 @@
6
6
  "use strict";
7
7
 
8
8
  const { ConcatSource } = require("webpack-sources");
9
+ const { UsageState } = require("../ExportsInfo");
9
10
  const Template = require("../Template");
10
11
  const propertyAccess = require("../util/propertyAccess");
12
+ const { getEntryRuntime } = require("../util/runtime");
11
13
  const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
12
14
 
13
15
  /** @typedef {import("webpack-sources").Source} Source */
@@ -16,7 +18,9 @@ const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
16
18
  /** @typedef {import("../Chunk")} Chunk */
17
19
  /** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
18
20
  /** @typedef {import("../Compiler")} Compiler */
21
+ /** @typedef {import("../Module")} Module */
19
22
  /** @typedef {import("../javascript/JavascriptModulesPlugin").RenderContext} RenderContext */
23
+ /** @typedef {import("../javascript/JavascriptModulesPlugin").StartupRenderContext} StartupRenderContext */
20
24
  /** @typedef {import("../util/Hash")} Hash */
21
25
  /** @template T @typedef {import("./AbstractLibraryPlugin").LibraryContext<T>} LibraryContext<T> */
22
26
 
@@ -93,11 +97,9 @@ const accessWithInit = (accessor, existingLength, initLast = false) => {
93
97
  /**
94
98
  * @typedef {Object} AssignLibraryPluginParsed
95
99
  * @property {string | string[]} name
100
+ * @property {string | string[] | undefined} export
96
101
  */
97
102
 
98
- const COMMON_LIBRARY_NAME_MESSAGE =
99
- "Common configuration options that specific library names are 'output.library[.name]', 'entry.xyz.library[.name]', 'ModuleFederationPlugin.name' and 'ModuleFederationPlugin.library[.name]'.";
100
-
101
103
  /**
102
104
  * @typedef {AssignLibraryPluginParsed} T
103
105
  * @extends {AbstractLibraryPlugin<AssignLibraryPluginParsed>}
@@ -126,69 +128,175 @@ class AssignLibraryPlugin extends AbstractLibraryPlugin {
126
128
  if (this.unnamed === "error") {
127
129
  if (typeof name !== "string" && !Array.isArray(name)) {
128
130
  throw new Error(
129
- `Library name must be a string or string array. ${COMMON_LIBRARY_NAME_MESSAGE}`
131
+ `Library name must be a string or string array. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
130
132
  );
131
133
  }
132
134
  } else {
133
135
  if (name && typeof name !== "string" && !Array.isArray(name)) {
134
136
  throw new Error(
135
- `Library name must be a string, string array or unset. ${COMMON_LIBRARY_NAME_MESSAGE}`
137
+ `Library name must be a string, string array or unset. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
136
138
  );
137
139
  }
138
140
  }
139
141
  return {
140
- name: /** @type {string|string[]=} */ (name)
142
+ name: /** @type {string|string[]=} */ (name),
143
+ export: library.export
141
144
  };
142
145
  }
143
146
 
144
147
  /**
145
- * @param {Source} source source
146
- * @param {RenderContext} renderContext render context
148
+ * @param {Module} module the exporting entry module
149
+ * @param {string} entryName the name of the entrypoint
147
150
  * @param {LibraryContext<T>} libraryContext context
148
- * @returns {Source} source with library export
151
+ * @returns {void}
149
152
  */
150
- render(source, { chunkGraph, moduleGraph, chunk }, { options, compilation }) {
151
- const prefix =
152
- this.prefix === "global"
153
- ? [compilation.outputOptions.globalObject]
154
- : this.prefix;
153
+ finishEntryModule(
154
+ module,
155
+ entryName,
156
+ { options, compilation, compilation: { moduleGraph } }
157
+ ) {
158
+ const runtime = getEntryRuntime(compilation, entryName);
159
+ if (options.export) {
160
+ const exportsInfo = moduleGraph.getExportInfo(
161
+ module,
162
+ Array.isArray(options.export) ? options.export[0] : options.export
163
+ );
164
+ exportsInfo.setUsed(UsageState.Used, runtime);
165
+ exportsInfo.canMangleUse = false;
166
+ } else {
167
+ const exportsInfo = moduleGraph.getExportsInfo(module);
168
+ exportsInfo.setUsedInUnknownWay(runtime);
169
+ }
170
+ moduleGraph.addExtraReason(module, "used as library export");
171
+ }
172
+
173
+ _getPrefix(compilation) {
174
+ return this.prefix === "global"
175
+ ? [compilation.outputOptions.globalObject]
176
+ : this.prefix;
177
+ }
178
+
179
+ _getResolvedFullName(options, chunk, compilation) {
180
+ const prefix = this._getPrefix(compilation);
155
181
  const fullName = options.name ? prefix.concat(options.name) : prefix;
156
- const fullNameResolved = fullName.map(n =>
182
+ return fullName.map(n =>
157
183
  compilation.getPath(n, {
158
184
  chunk
159
185
  })
160
186
  );
161
- const result = new ConcatSource();
187
+ }
188
+
189
+ /**
190
+ * @param {Source} source source
191
+ * @param {RenderContext} renderContext render context
192
+ * @param {LibraryContext<T>} libraryContext context
193
+ * @returns {Source} source with library export
194
+ */
195
+ render(source, { chunk }, { options, compilation }) {
196
+ const fullNameResolved = this._getResolvedFullName(
197
+ options,
198
+ chunk,
199
+ compilation
200
+ );
162
201
  if (this.declare) {
163
202
  const base = fullNameResolved[0];
164
203
  if (!isNameValid(base)) {
165
204
  throw new Error(
166
205
  `Library name base (${base}) must be a valid identifier when using a var declaring library type. Either use a valid identifier (e. g. ${Template.toIdentifier(
167
206
  base
168
- )}) or use a different library type (e. g. 'type: "global"', which assign a property on the global scope instead of declaring a variable). ${COMMON_LIBRARY_NAME_MESSAGE}`
207
+ )}) or use a different library type (e. g. 'type: "global"', which assign a property on the global scope instead of declaring a variable). ${
208
+ AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE
209
+ }`
169
210
  );
170
211
  }
171
- result.add(`${this.declare} ${base};`);
212
+ source = new ConcatSource(`${this.declare} ${base};\n`, source);
172
213
  }
214
+ return source;
215
+ }
216
+
217
+ /**
218
+ * @param {Module} module the exporting entry module
219
+ * @param {RenderContext} renderContext render context
220
+ * @param {LibraryContext<T>} libraryContext context
221
+ * @returns {string | undefined} bailout reason
222
+ */
223
+ embedInRuntimeBailout(module, { chunk }, { options, compilation }) {
224
+ const topLevelDeclarations =
225
+ module.buildInfo && module.buildInfo.topLevelDeclarations;
226
+ if (!topLevelDeclarations)
227
+ return "it doesn't tell about top level declarations.";
228
+ const fullNameResolved = this._getResolvedFullName(
229
+ options,
230
+ chunk,
231
+ compilation
232
+ );
233
+ const base = fullNameResolved[0];
234
+ if (topLevelDeclarations.has(base))
235
+ return `it declares '${base}' on top-level, which conflicts with the current library output.`;
236
+ }
237
+
238
+ /**
239
+ * @param {Source} source source
240
+ * @param {Module} module module
241
+ * @param {StartupRenderContext} renderContext render context
242
+ * @param {LibraryContext<T>} libraryContext context
243
+ * @returns {Source} source with library export
244
+ */
245
+ renderStartup(source, module, { chunk }, { options, compilation }) {
246
+ const fullNameResolved = this._getResolvedFullName(
247
+ options,
248
+ chunk,
249
+ compilation
250
+ );
251
+ const exportAccess = options.export
252
+ ? propertyAccess(
253
+ Array.isArray(options.export) ? options.export : [options.export]
254
+ )
255
+ : "";
256
+ const result = new ConcatSource(source);
173
257
  if (options.name ? this.named === "copy" : this.unnamed === "copy") {
174
258
  result.add(
175
- `(function(e, a) { for(var i in a) e[i] = a[i]; if(a.__esModule) Object.defineProperty(e, "__esModule", { value: true }); }(${accessWithInit(
259
+ `var __webpack_export_target__ = ${accessWithInit(
176
260
  fullNameResolved,
177
- prefix.length,
261
+ this._getPrefix(compilation).length,
178
262
  true
179
- )},\n`
263
+ )};\n`
264
+ );
265
+ let exports = "__webpack_exports__";
266
+ if (exportAccess) {
267
+ result.add(
268
+ `var __webpack_exports_export__ = __webpack_exports__${exportAccess};\n`
269
+ );
270
+ exports = "__webpack_exports_export__";
271
+ }
272
+ result.add(
273
+ `for(var i in ${exports}) __webpack_export_target__[i] = ${exports}[i];\n`
274
+ );
275
+ result.add(
276
+ `if(${exports}.__esModule) Object.defineProperty(__webpack_export_target__, "__esModule", { value: true });\n`
180
277
  );
181
- result.add(source);
182
- result.add("\n))");
183
278
  } else {
184
279
  result.add(
185
- `${accessWithInit(fullNameResolved, prefix.length, false)} =\n`
280
+ `${accessWithInit(
281
+ fullNameResolved,
282
+ this._getPrefix(compilation).length,
283
+ false
284
+ )} = __webpack_exports__${exportAccess};\n`
186
285
  );
187
- result.add(source);
188
286
  }
189
287
  return result;
190
288
  }
191
289
 
290
+ /**
291
+ * @param {Chunk} chunk the chunk
292
+ * @param {Set<string>} set runtime requirements
293
+ * @param {LibraryContext<T>} libraryContext context
294
+ * @returns {void}
295
+ */
296
+ runtimeRequirements(chunk, set, libraryContext) {
297
+ // we don't need to return exports from runtime
298
+ }
299
+
192
300
  /**
193
301
  * @param {Chunk} chunk the chunk
194
302
  * @param {Hash} hash hash
@@ -208,13 +316,16 @@ class AssignLibraryPlugin extends AbstractLibraryPlugin {
208
316
  chunk
209
317
  })
210
318
  );
211
- if (!options.name && this.unnamed === "copy") {
319
+ if (options.name ? this.named === "copy" : this.unnamed === "copy") {
212
320
  hash.update("copy");
213
321
  }
214
322
  if (this.declare) {
215
323
  hash.update(this.declare);
216
324
  }
217
325
  hash.update(fullNameResolved.join("."));
326
+ if (options.export) {
327
+ hash.update(`${options.export}`);
328
+ }
218
329
  }
219
330
  }
220
331
 
@@ -70,11 +70,13 @@ class EnableLibraryPlugin {
70
70
  enabled.add(type);
71
71
 
72
72
  if (typeof type === "string") {
73
- const ExportPropertyTemplatePlugin = require("./ExportPropertyLibraryPlugin");
74
- new ExportPropertyTemplatePlugin({
75
- type,
76
- nsObjectUsed: type !== "module"
77
- }).apply(compiler);
73
+ const enableExportProperty = () => {
74
+ const ExportPropertyTemplatePlugin = require("./ExportPropertyLibraryPlugin");
75
+ new ExportPropertyTemplatePlugin({
76
+ type,
77
+ nsObjectUsed: type !== "module"
78
+ }).apply(compiler);
79
+ };
78
80
  switch (type) {
79
81
  case "var": {
80
82
  //@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
@@ -179,6 +181,7 @@ class EnableLibraryPlugin {
179
181
  }
180
182
  case "amd":
181
183
  case "amd-require": {
184
+ enableExportProperty();
182
185
  const AmdLibraryPlugin = require("./AmdLibraryPlugin");
183
186
  new AmdLibraryPlugin({
184
187
  type,
@@ -188,6 +191,7 @@ class EnableLibraryPlugin {
188
191
  }
189
192
  case "umd":
190
193
  case "umd2": {
194
+ enableExportProperty();
191
195
  const UmdLibraryPlugin = require("./UmdLibraryPlugin");
192
196
  new UmdLibraryPlugin({
193
197
  type,
@@ -196,6 +200,7 @@ class EnableLibraryPlugin {
196
200
  break;
197
201
  }
198
202
  case "system": {
203
+ enableExportProperty();
199
204
  const SystemLibraryPlugin = require("./SystemLibraryPlugin");
200
205
  new SystemLibraryPlugin({
201
206
  type
@@ -203,15 +208,21 @@ class EnableLibraryPlugin {
203
208
  break;
204
209
  }
205
210
  case "jsonp": {
211
+ enableExportProperty();
206
212
  const JsonpLibraryPlugin = require("./JsonpLibraryPlugin");
207
213
  new JsonpLibraryPlugin({
208
214
  type
209
215
  }).apply(compiler);
210
216
  break;
211
217
  }
212
- case "module":
213
- // TODO implement module library
218
+ case "module": {
219
+ enableExportProperty();
220
+ const ModuleLibraryPlugin = require("./ModuleLibraryPlugin");
221
+ new ModuleLibraryPlugin({
222
+ type
223
+ }).apply(compiler);
214
224
  break;
225
+ }
215
226
  default:
216
227
  throw new Error(`Unsupported library type ${type}.
217
228
  Plugins which provide custom library types must call EnableLibraryPlugin.setEnabled(compiler, type) to disable this error.`);
@@ -14,9 +14,10 @@ const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
14
14
  /** @typedef {import("webpack-sources").Source} Source */
15
15
  /** @typedef {import("../../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
16
16
  /** @typedef {import("../../declarations/WebpackOptions").LibraryType} LibraryType */
17
+ /** @typedef {import("../Chunk")} Chunk */
17
18
  /** @typedef {import("../Compiler")} Compiler */
18
19
  /** @typedef {import("../Module")} Module */
19
- /** @typedef {import("../javascript/JavascriptModulesPlugin").RenderContext} RenderContext */
20
+ /** @typedef {import("../javascript/JavascriptModulesPlugin").StartupRenderContext} StartupRenderContext */
20
21
  /** @template T @typedef {import("./AbstractLibraryPlugin").LibraryContext<T>} LibraryContext<T> */
21
22
 
22
23
  /**
@@ -84,17 +85,27 @@ class ExportPropertyLibraryPlugin extends AbstractLibraryPlugin {
84
85
  }
85
86
  moduleGraph.addExtraReason(module, "used as library export");
86
87
  }
88
+
89
+ /**
90
+ * @param {Chunk} chunk the chunk
91
+ * @param {Set<string>} set runtime requirements
92
+ * @param {LibraryContext<T>} libraryContext context
93
+ * @returns {void}
94
+ */
95
+ runtimeRequirements(chunk, set, libraryContext) {}
96
+
87
97
  /**
88
98
  * @param {Source} source source
89
- * @param {RenderContext} renderContext render context
99
+ * @param {Module} module module
100
+ * @param {StartupRenderContext} renderContext render context
90
101
  * @param {LibraryContext<T>} libraryContext context
91
102
  * @returns {Source} source with library export
92
103
  */
93
- render(source, renderContext, { options }) {
104
+ renderStartup(source, module, renderContext, { options }) {
94
105
  if (!options.export) return source;
95
- const postfix = propertyAccess(
106
+ const postfix = `__webpack_exports__ = __webpack_exports__${propertyAccess(
96
107
  Array.isArray(options.export) ? options.export : [options.export]
97
- );
108
+ )};\n`;
98
109
  return new ConcatSource(source, postfix);
99
110
  }
100
111
  }
@@ -50,7 +50,9 @@ class JsonpLibraryPlugin extends AbstractLibraryPlugin {
50
50
  parseOptions(library) {
51
51
  const { name } = library;
52
52
  if (typeof name !== "string") {
53
- throw new Error("Jsonp library name must be a simple string");
53
+ throw new Error(
54
+ `Jsonp library name must be a simple string. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
55
+ );
54
56
  }
55
57
  return {
56
58
  name: /** @type {string} */ (name)
@@ -0,0 +1,100 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Tobias Koppers @sokra
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const { ConcatSource } = require("webpack-sources");
9
+ const Template = require("../Template");
10
+ const propertyAccess = require("../util/propertyAccess");
11
+ const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
12
+
13
+ /** @typedef {import("webpack-sources").Source} Source */
14
+ /** @typedef {import("../../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
15
+ /** @typedef {import("../../declarations/WebpackOptions").LibraryType} LibraryType */
16
+ /** @typedef {import("../Chunk")} Chunk */
17
+ /** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
18
+ /** @typedef {import("../Compiler")} Compiler */
19
+ /** @typedef {import("../Module")} Module */
20
+ /** @typedef {import("../javascript/JavascriptModulesPlugin").StartupRenderContext} StartupRenderContext */
21
+ /** @typedef {import("../util/Hash")} Hash */
22
+ /** @template T @typedef {import("./AbstractLibraryPlugin").LibraryContext<T>} LibraryContext<T> */
23
+
24
+ /**
25
+ * @typedef {Object} ModuleLibraryPluginOptions
26
+ * @property {LibraryType} type
27
+ */
28
+
29
+ /**
30
+ * @typedef {Object} ModuleLibraryPluginParsed
31
+ * @property {string} name
32
+ */
33
+
34
+ /**
35
+ * @typedef {ModuleLibraryPluginParsed} T
36
+ * @extends {AbstractLibraryPlugin<ModuleLibraryPluginParsed>}
37
+ */
38
+ class ModuleLibraryPlugin extends AbstractLibraryPlugin {
39
+ /**
40
+ * @param {ModuleLibraryPluginOptions} options the plugin options
41
+ */
42
+ constructor(options) {
43
+ super({
44
+ pluginName: "ModuleLibraryPlugin",
45
+ type: options.type
46
+ });
47
+ }
48
+
49
+ /**
50
+ * @param {LibraryOptions} library normalized library option
51
+ * @returns {T | false} preprocess as needed by overriding
52
+ */
53
+ parseOptions(library) {
54
+ const { name } = library;
55
+ if (name) {
56
+ throw new Error(
57
+ `Library name must unset. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
58
+ );
59
+ }
60
+ return {
61
+ name: /** @type {string} */ (name)
62
+ };
63
+ }
64
+
65
+ /**
66
+ * @param {Source} source source
67
+ * @param {Module} module module
68
+ * @param {StartupRenderContext} renderContext render context
69
+ * @param {LibraryContext<T>} libraryContext context
70
+ * @returns {Source} source with library export
71
+ */
72
+ renderStartup(
73
+ source,
74
+ module,
75
+ { moduleGraph, chunk },
76
+ { options, compilation }
77
+ ) {
78
+ const result = new ConcatSource(source);
79
+ const exportsInfo = moduleGraph.getExportsInfo(module);
80
+ const exports = [];
81
+ for (const exportInfo of exportsInfo.orderedExports) {
82
+ if (!exportInfo.provided) continue;
83
+ const varName = `__webpack_exports__${Template.toIdentifier(
84
+ exportInfo.name
85
+ )}`;
86
+ result.add(
87
+ `var ${varName} = __webpack_exports__${propertyAccess([
88
+ exportInfo.getUsedName(exportInfo.name, chunk.runtime)
89
+ ])};\n`
90
+ );
91
+ exports.push(`${varName} as ${exportInfo.name}`);
92
+ }
93
+ if (exports.length > 0) {
94
+ result.add(`export { ${exports.join(", ")} };\n`);
95
+ }
96
+ return result;
97
+ }
98
+ }
99
+
100
+ module.exports = ModuleLibraryPlugin;
@@ -55,7 +55,7 @@ class SystemLibraryPlugin extends AbstractLibraryPlugin {
55
55
  const { name } = library;
56
56
  if (name && typeof name !== "string") {
57
57
  throw new Error(
58
- "System.js library name must be a simple string or unset"
58
+ `System.js library name must be a simple string or unset. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
59
59
  );
60
60
  }
61
61
  return {
@@ -52,7 +52,7 @@ const builtins = [
52
52
  "util",
53
53
  "v8",
54
54
  "vm",
55
- "wasi", // cSpell:ignore wasi
55
+ "wasi",
56
56
  "worker_threads",
57
57
  "zlib"
58
58
  ];
@@ -133,41 +133,43 @@ const {
133
133
  * @property {ConcatenatedModuleInfo | ExternalModuleInfo} target
134
134
  */
135
135
 
136
- const RESERVED_NAMES = [
137
- // internal names (should always be renamed)
138
- ConcatenationScope.DEFAULT_EXPORT,
139
- ConcatenationScope.NAMESPACE_OBJECT_EXPORT,
140
-
141
- // keywords
142
- "abstract,arguments,async,await,boolean,break,byte,case,catch,char,class,const,continue",
143
- "debugger,default,delete,do,double,else,enum,eval,export,extends,false,final,finally,float",
144
- "for,function,goto,if,implements,import,in,instanceof,int,interface,let,long,native,new,null",
145
- "package,private,protected,public,return,short,static,super,switch,synchronized,this,throw",
146
- "throws,transient,true,try,typeof,var,void,volatile,while,with,yield",
147
-
148
- // commonjs
149
- "module,__dirname,__filename,exports",
150
-
151
- // js globals
152
- "Array,Date,eval,function,hasOwnProperty,Infinity,isFinite,isNaN,isPrototypeOf,length,Math",
153
- "NaN,name,Number,Object,prototype,String,toString,undefined,valueOf",
154
-
155
- // browser globals
156
- "alert,all,anchor,anchors,area,assign,blur,button,checkbox,clearInterval,clearTimeout",
157
- "clientInformation,close,closed,confirm,constructor,crypto,decodeURI,decodeURIComponent",
158
- "defaultStatus,document,element,elements,embed,embeds,encodeURI,encodeURIComponent,escape",
159
- "event,fileUpload,focus,form,forms,frame,innerHeight,innerWidth,layer,layers,link,location",
160
- "mimeTypes,navigate,navigator,frames,frameRate,hidden,history,image,images,offscreenBuffering",
161
- "open,opener,option,outerHeight,outerWidth,packages,pageXOffset,pageYOffset,parent,parseFloat",
162
- "parseInt,password,pkcs11,plugin,prompt,propertyIsEnum,radio,reset,screenX,screenY,scroll",
163
- "secure,select,self,setInterval,setTimeout,status,submit,taint,text,textarea,top,unescape",
164
- "untaint,window",
165
-
166
- // window events
167
- "onblur,onclick,onerror,onfocus,onkeydown,onkeypress,onkeyup,onmouseover,onload,onmouseup,onmousedown,onsubmit"
168
- ]
169
- .join(",")
170
- .split(",");
136
+ const RESERVED_NAMES = new Set(
137
+ [
138
+ // internal names (should always be renamed)
139
+ ConcatenationScope.DEFAULT_EXPORT,
140
+ ConcatenationScope.NAMESPACE_OBJECT_EXPORT,
141
+
142
+ // keywords
143
+ "abstract,arguments,async,await,boolean,break,byte,case,catch,char,class,const,continue",
144
+ "debugger,default,delete,do,double,else,enum,eval,export,extends,false,final,finally,float",
145
+ "for,function,goto,if,implements,import,in,instanceof,int,interface,let,long,native,new,null",
146
+ "package,private,protected,public,return,short,static,super,switch,synchronized,this,throw",
147
+ "throws,transient,true,try,typeof,var,void,volatile,while,with,yield",
148
+
149
+ // commonjs/amd
150
+ "module,__dirname,__filename,exports,require,define",
151
+
152
+ // js globals
153
+ "Array,Date,eval,function,hasOwnProperty,Infinity,isFinite,isNaN,isPrototypeOf,length,Math",
154
+ "NaN,name,Number,Object,prototype,String,toString,undefined,valueOf",
155
+
156
+ // browser globals
157
+ "alert,all,anchor,anchors,area,assign,blur,button,checkbox,clearInterval,clearTimeout",
158
+ "clientInformation,close,closed,confirm,constructor,crypto,decodeURI,decodeURIComponent",
159
+ "defaultStatus,document,element,elements,embed,embeds,encodeURI,encodeURIComponent,escape",
160
+ "event,fileUpload,focus,form,forms,frame,innerHeight,innerWidth,layer,layers,link,location",
161
+ "mimeTypes,navigate,navigator,frames,frameRate,hidden,history,image,images,offscreenBuffering",
162
+ "open,opener,option,outerHeight,outerWidth,packages,pageXOffset,pageYOffset,parent,parseFloat",
163
+ "parseInt,password,pkcs11,plugin,prompt,propertyIsEnum,radio,reset,screenX,screenY,scroll",
164
+ "secure,select,self,setInterval,setTimeout,status,submit,taint,text,textarea,top,unescape",
165
+ "untaint,window",
166
+
167
+ // window events
168
+ "onblur,onclick,onerror,onfocus,onkeydown,onkeypress,onkeyup,onmouseover,onload,onmouseup,onmousedown,onsubmit"
169
+ ]
170
+ .join(",")
171
+ .split(",")
172
+ );
171
173
 
172
174
  const bySourceOrder = (a, b) => {
173
175
  const aOrder = a.sourceOrder;
@@ -761,6 +763,7 @@ class ConcatenatedModule extends Module {
761
763
  fileDependencies: new LazySet(),
762
764
  contextDependencies: new LazySet(),
763
765
  missingDependencies: new LazySet(),
766
+ topLevelDeclarations: new Set(),
764
767
  assets: undefined
765
768
  };
766
769
  this.buildMeta = rootModule.buildMeta;
@@ -802,6 +805,22 @@ class ConcatenatedModule extends Module {
802
805
  }
803
806
  }
804
807
 
808
+ // populate topLevelDeclarations
809
+ if (m.buildInfo.topLevelDeclarations) {
810
+ const topLevelDeclarations = this.buildInfo.topLevelDeclarations;
811
+ if (topLevelDeclarations !== undefined) {
812
+ for (const decl of m.buildInfo.topLevelDeclarations) {
813
+ // reserved names will always be renamed
814
+ if (RESERVED_NAMES.has(decl)) continue;
815
+ // TODO actually this is incorrect since with renaming there could be more
816
+ // We should do the renaming during build
817
+ topLevelDeclarations.add(decl);
818
+ }
819
+ }
820
+ } else {
821
+ this.buildInfo.topLevelDeclarations = undefined;
822
+ }
823
+
805
824
  // populate assets
806
825
  if (m.buildInfo.assets) {
807
826
  if (this.buildInfo.assets === undefined) {
@@ -102,10 +102,11 @@ exports.addUsage = (state, symbol, usage) => {
102
102
  * @returns {void}
103
103
  */
104
104
  exports.addVariableUsage = (parser, name, usage) => {
105
- const symbol = /** @type {TopLevelSymbol} */ (parser.getTagData(
106
- name,
107
- topLevelSymbolTag
108
- ));
105
+ const symbol =
106
+ /** @type {TopLevelSymbol} */ (parser.getTagData(
107
+ name,
108
+ topLevelSymbolTag
109
+ )) || exports.tagTopLevelSymbol(parser, name);
109
110
  if (symbol) {
110
111
  exports.addUsage(parser.state, symbol, usage);
111
112
  }
@@ -7,6 +7,7 @@
7
7
  const RuntimeGlobals = require("../RuntimeGlobals");
8
8
  const RuntimeModule = require("../RuntimeModule");
9
9
  const Template = require("../Template");
10
+ const { first } = require("../util/SetHelpers");
10
11
 
11
12
  /** @typedef {import("../Chunk")} Chunk */
12
13
  /** @typedef {import("../Compilation")} Compilation */
@@ -259,9 +260,7 @@ class GetChunkFilenameRuntimeModule extends RuntimeModule {
259
260
  Array.from(staticUrls, ([url, ids]) => {
260
261
  const condition =
261
262
  ids.size === 1
262
- ? `chunkId === ${JSON.stringify(
263
- ids.values().next().value
264
- )}`
263
+ ? `chunkId === ${JSON.stringify(first(ids))}`
265
264
  : `{${Array.from(
266
265
  ids,
267
266
  id => `${JSON.stringify(id)}:1`