webpack 5.14.0 → 5.18.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 (71) hide show
  1. package/bin/webpack.js +0 -0
  2. package/hot/lazy-compilation-node.js +38 -0
  3. package/hot/lazy-compilation-web.js +74 -0
  4. package/lib/AutomaticPrefetchPlugin.js +14 -7
  5. package/lib/CacheFacade.js +1 -0
  6. package/lib/ChunkGraph.js +132 -19
  7. package/lib/CodeGenerationResults.js +43 -8
  8. package/lib/Compilation.js +253 -149
  9. package/lib/Compiler.js +7 -2
  10. package/lib/ContextModule.js +2 -2
  11. package/lib/Dependency.js +1 -7
  12. package/lib/ExportsInfo.js +23 -5
  13. package/lib/ExternalModuleFactoryPlugin.js +46 -3
  14. package/lib/FileSystemInfo.js +192 -137
  15. package/lib/HotModuleReplacementPlugin.js +76 -29
  16. package/lib/IgnoreErrorModuleFactory.js +39 -0
  17. package/lib/Module.js +2 -3
  18. package/lib/NormalModuleFactory.js +27 -8
  19. package/lib/Template.js +32 -23
  20. package/lib/WebpackIsIncludedPlugin.js +85 -0
  21. package/lib/WebpackOptionsApply.js +27 -5
  22. package/lib/cache/PackFileCacheStrategy.js +5 -1
  23. package/lib/config/defaults.js +18 -18
  24. package/lib/config/normalization.js +44 -9
  25. package/lib/debug/ProfilingPlugin.js +20 -1
  26. package/lib/dependencies/AMDDefineDependency.js +1 -1
  27. package/lib/dependencies/AMDPlugin.js +6 -7
  28. package/lib/dependencies/CommonJsImportsParserPlugin.js +43 -1
  29. package/lib/dependencies/CommonJsPlugin.js +1 -6
  30. package/lib/dependencies/ContextDependencyHelpers.js +3 -2
  31. package/lib/dependencies/ExportsInfoDependency.js +0 -20
  32. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +1 -2
  33. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +0 -29
  34. package/lib/dependencies/HarmonyImportDependency.js +0 -41
  35. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +2 -3
  36. package/lib/dependencies/HarmonyImportSpecifierDependency.js +2 -36
  37. package/lib/dependencies/HarmonyModulesPlugin.js +2 -2
  38. package/lib/dependencies/ImportPlugin.js +1 -6
  39. package/lib/dependencies/JsonExportsDependency.js +0 -1
  40. package/lib/dependencies/ModuleDecoratorDependency.js +0 -1
  41. package/lib/dependencies/NullDependency.js +0 -8
  42. package/lib/dependencies/ProvidedDependency.js +0 -1
  43. package/lib/dependencies/StaticExportsDependency.js +0 -12
  44. package/lib/dependencies/SystemPlugin.js +0 -4
  45. package/lib/dependencies/URLDependency.js +45 -3
  46. package/lib/dependencies/URLPlugin.js +33 -7
  47. package/lib/dependencies/WebpackIsIncludedDependency.js +80 -0
  48. package/lib/hmr/LazyCompilationPlugin.js +348 -0
  49. package/lib/hmr/lazyCompilationBackend.js +86 -0
  50. package/lib/javascript/JavascriptModulesPlugin.js +4 -3
  51. package/lib/javascript/JavascriptParser.js +20 -5
  52. package/lib/library/AssignLibraryPlugin.js +13 -4
  53. package/lib/library/EnableLibraryPlugin.js +12 -0
  54. package/lib/optimize/ConcatenatedModule.js +0 -12
  55. package/lib/optimize/InnerGraph.js +32 -0
  56. package/lib/optimize/SplitChunksPlugin.js +4 -1
  57. package/lib/serialization/ObjectMiddleware.js +7 -5
  58. package/lib/sharing/ProvideSharedModule.js +1 -1
  59. package/lib/sharing/ShareRuntimeModule.js +2 -2
  60. package/lib/stats/DefaultStatsPresetPlugin.js +1 -0
  61. package/lib/util/MapHelpers.js +22 -0
  62. package/lib/util/binarySearchBounds.js +86 -0
  63. package/lib/util/createHash.js +13 -7
  64. package/lib/util/internalSerializables.js +2 -0
  65. package/lib/util/processAsyncTree.js +61 -0
  66. package/lib/util/runtime.js +12 -1
  67. package/package.json +3 -3
  68. package/schemas/WebpackOptions.json +330 -140
  69. package/schemas/plugins/container/ContainerPlugin.json +2 -1
  70. package/schemas/plugins/container/ModuleFederationPlugin.json +2 -1
  71. package/types.d.ts +320 -121
@@ -0,0 +1,80 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Ivan Kopeykin @vankop
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const Dependency = require("../Dependency");
9
+ const Template = require("../Template");
10
+ const makeSerializable = require("../util/makeSerializable");
11
+ const ModuleDependency = require("./ModuleDependency");
12
+
13
+ /** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
14
+ /** @typedef {import("../Compilation")} Compilation */
15
+ /** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
16
+ /** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
17
+ /** @typedef {import("../ModuleGraph")} ModuleGraph */
18
+ /** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
19
+
20
+ class WebpackIsIncludedDependency extends ModuleDependency {
21
+ constructor(request, range) {
22
+ super(request);
23
+
24
+ this.weak = true;
25
+ this.range = range;
26
+ }
27
+
28
+ /**
29
+ * Returns list of exports referenced by this dependency
30
+ * @param {ModuleGraph} moduleGraph module graph
31
+ * @param {RuntimeSpec} runtime the runtime for which the module is analysed
32
+ * @returns {(string[] | ReferencedExport)[]} referenced exports
33
+ */
34
+ getReferencedExports(moduleGraph, runtime) {
35
+ // This doesn't use any export
36
+ return Dependency.NO_EXPORTS_REFERENCED;
37
+ }
38
+
39
+ get type() {
40
+ return "__webpack_is_included__";
41
+ }
42
+ }
43
+
44
+ makeSerializable(
45
+ WebpackIsIncludedDependency,
46
+ "webpack/lib/dependencies/WebpackIsIncludedDependency"
47
+ );
48
+
49
+ WebpackIsIncludedDependency.Template = class WebpackIsIncludedDependencyTemplate extends (
50
+ ModuleDependency.Template
51
+ ) {
52
+ /**
53
+ * @param {Dependency} dependency the dependency for which the template should be applied
54
+ * @param {ReplaceSource} source the current replace source which can be modified
55
+ * @param {DependencyTemplateContext} templateContext the context object
56
+ * @returns {void}
57
+ */
58
+ apply(dependency, source, { runtimeTemplate, chunkGraph, moduleGraph }) {
59
+ const dep = /** @type {WebpackIsIncludedDependency} */ (dependency);
60
+ const connection = moduleGraph.getConnection(dep);
61
+ const included = connection
62
+ ? chunkGraph.getNumberOfModuleChunks(connection.module) > 0
63
+ : false;
64
+ const comment = runtimeTemplate.outputOptions.pathinfo
65
+ ? Template.toComment(
66
+ `__webpack_is_included__ ${runtimeTemplate.requestShortener.shorten(
67
+ dep.request
68
+ )}`
69
+ )
70
+ : "";
71
+
72
+ source.replace(
73
+ dep.range[0],
74
+ dep.range[1] - 1,
75
+ `${comment}${JSON.stringify(included)}`
76
+ );
77
+ }
78
+ };
79
+
80
+ module.exports = WebpackIsIncludedDependency;
@@ -0,0 +1,348 @@
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 { RawSource } = require("webpack-sources");
9
+ const AsyncDependenciesBlock = require("../AsyncDependenciesBlock");
10
+ const Dependency = require("../Dependency");
11
+ const Module = require("../Module");
12
+ const ModuleFactory = require("../ModuleFactory");
13
+ const RuntimeGlobals = require("../RuntimeGlobals");
14
+ const Template = require("../Template");
15
+ const CommonJsRequireDependency = require("../dependencies/CommonJsRequireDependency");
16
+ const { registerNotSerializable } = require("../util/serialization");
17
+
18
+ /** @typedef {import("../../declarations/WebpackOptions")} WebpackOptions */
19
+ /** @typedef {import("../Compilation")} Compilation */
20
+ /** @typedef {import("../Compiler")} Compiler */
21
+ /** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
22
+ /** @typedef {import("../Module").BuildMeta} BuildMeta */
23
+ /** @typedef {import("../Module").CodeGenerationContext} CodeGenerationContext */
24
+ /** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */
25
+ /** @typedef {import("../Module").LibIdentOptions} LibIdentOptions */
26
+ /** @typedef {import("../Module").NeedBuildContext} NeedBuildContext */
27
+ /** @typedef {import("../ModuleFactory").ModuleFactoryCreateData} ModuleFactoryCreateData */
28
+ /** @typedef {import("../ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
29
+ /** @typedef {import("../RequestShortener")} RequestShortener */
30
+ /** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
31
+ /** @typedef {import("../WebpackError")} WebpackError */
32
+ /** @typedef {import("../util/Hash")} Hash */
33
+ /** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
34
+
35
+ const TYPES = new Set(["javascript"]);
36
+
37
+ class LazyCompilationDependency extends Dependency {
38
+ constructor(originalModule) {
39
+ super();
40
+ this.originalModule = originalModule;
41
+ }
42
+
43
+ get category() {
44
+ return "esm";
45
+ }
46
+
47
+ get type() {
48
+ return "lazy import()";
49
+ }
50
+
51
+ /**
52
+ * @returns {string | null} an identifier to merge equal requests
53
+ */
54
+ getResourceIdentifier() {
55
+ return this.originalModule.identifier();
56
+ }
57
+ }
58
+
59
+ registerNotSerializable(LazyCompilationDependency);
60
+
61
+ class LazyCompilationProxyModule extends Module {
62
+ constructor(context, originalModule, request, client, data, active) {
63
+ super("lazy-compilation-proxy", context, originalModule.layer);
64
+ this.originalModule = originalModule;
65
+ this.request = request;
66
+ this.client = client;
67
+ this.data = data;
68
+ this.active = active;
69
+ }
70
+
71
+ /**
72
+ * @returns {string} a unique identifier of the module
73
+ */
74
+ identifier() {
75
+ return `lazy-compilation-proxy|${this.originalModule.identifier()}`;
76
+ }
77
+
78
+ /**
79
+ * @param {RequestShortener} requestShortener the request shortener
80
+ * @returns {string} a user readable identifier of the module
81
+ */
82
+ readableIdentifier(requestShortener) {
83
+ return `lazy-compilation-proxy ${this.originalModule.readableIdentifier(
84
+ requestShortener
85
+ )}`;
86
+ }
87
+
88
+ /**
89
+ * Assuming this module is in the cache. Update the (cached) module with
90
+ * the fresh module from the factory. Usually updates internal references
91
+ * and properties.
92
+ * @param {Module} module fresh module
93
+ * @returns {void}
94
+ */
95
+ updateCacheModule(module) {
96
+ super.updateCacheModule(module);
97
+ const m = /** @type {LazyCompilationProxyModule} */ (module);
98
+ this.active = m.active;
99
+ }
100
+
101
+ /**
102
+ * @param {LibIdentOptions} options options
103
+ * @returns {string | null} an identifier for library inclusion
104
+ */
105
+ libIdent(options) {
106
+ return `${this.originalModule.libIdent(options)}!lazy-compilation-proxy`;
107
+ }
108
+
109
+ /**
110
+ * @param {NeedBuildContext} context context info
111
+ * @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
112
+ * @returns {void}
113
+ */
114
+ needBuild(context, callback) {
115
+ callback(null, !this.buildInfo || this.buildInfo.active !== this.active);
116
+ }
117
+
118
+ /**
119
+ * @param {WebpackOptions} options webpack options
120
+ * @param {Compilation} compilation the compilation
121
+ * @param {ResolverWithOptions} resolver the resolver
122
+ * @param {InputFileSystem} fs the file system
123
+ * @param {function(WebpackError=): void} callback callback function
124
+ * @returns {void}
125
+ */
126
+ build(options, compilation, resolver, fs, callback) {
127
+ this.buildInfo = {
128
+ active: this.active
129
+ };
130
+ /** @type {BuildMeta} */
131
+ this.buildMeta = {};
132
+ this.clearDependenciesAndBlocks();
133
+ const dep = new CommonJsRequireDependency(this.client);
134
+ this.addDependency(dep);
135
+ if (this.active) {
136
+ const dep = new LazyCompilationDependency(this.originalModule);
137
+ const block = new AsyncDependenciesBlock({});
138
+ block.addDependency(dep);
139
+ this.addBlock(block);
140
+ }
141
+ callback();
142
+ }
143
+
144
+ /**
145
+ * @returns {Set<string>} types available (do not mutate)
146
+ */
147
+ getSourceTypes() {
148
+ return TYPES;
149
+ }
150
+
151
+ /**
152
+ * @param {string=} type the source type for which the size should be estimated
153
+ * @returns {number} the estimated size of the module (must be non-zero)
154
+ */
155
+ size(type) {
156
+ return 200;
157
+ }
158
+
159
+ /**
160
+ * @param {CodeGenerationContext} context context for code generation
161
+ * @returns {CodeGenerationResult} result
162
+ */
163
+ codeGeneration({ runtimeTemplate, chunkGraph, moduleGraph }) {
164
+ const sources = new Map();
165
+ const runtimeRequirements = new Set();
166
+ runtimeRequirements.add(RuntimeGlobals.module);
167
+ const clientDep = /** @type {CommonJsRequireDependency} */ (this
168
+ .dependencies[0]);
169
+ const clientModule = moduleGraph.getModule(clientDep);
170
+ const block = this.blocks[0];
171
+ const client = Template.asString([
172
+ `var client = ${runtimeTemplate.moduleExports({
173
+ module: clientModule,
174
+ chunkGraph,
175
+ request: clientDep.userRequest,
176
+ runtimeRequirements
177
+ })}`,
178
+ `var data = ${JSON.stringify(this.data)};`
179
+ ]);
180
+ const keepActive = Template.asString([
181
+ `var dispose = client.keepAlive({ data, active: ${JSON.stringify(
182
+ !!block
183
+ )}, module, onError });`
184
+ ]);
185
+ let source;
186
+ if (block) {
187
+ const dep = block.dependencies[0];
188
+ const module = moduleGraph.getModule(dep);
189
+ source = Template.asString([
190
+ client,
191
+ `module.exports = ${runtimeTemplate.moduleNamespacePromise({
192
+ chunkGraph,
193
+ block,
194
+ module,
195
+ request: this.request,
196
+ strict: false, // TODO this should be inherited from the original module
197
+ message: "import()",
198
+ runtimeRequirements
199
+ })};`,
200
+ "if (module.hot) {",
201
+ Template.indent([
202
+ "module.hot.accept();",
203
+ `module.hot.accept(${JSON.stringify(
204
+ chunkGraph.getModuleId(module)
205
+ )}, function() { module.hot.invalidate(); });`,
206
+ "module.hot.dispose(function(data) { delete data.resolveSelf; dispose(data); });",
207
+ "if (module.hot.data && module.hot.data.resolveSelf) module.hot.data.resolveSelf(module.exports);"
208
+ ]),
209
+ "}",
210
+ "function onError() { /* ignore */ }",
211
+ keepActive
212
+ ]);
213
+ } else {
214
+ source = Template.asString([
215
+ client,
216
+ "var resolveSelf, onError;",
217
+ `module.exports = new Promise(function(resolve, reject) { resolveSelf = resolve; onError = reject; });`,
218
+ "if (module.hot) {",
219
+ Template.indent([
220
+ "module.hot.accept();",
221
+ "if (module.hot.data && module.hot.data.resolveSelf) module.hot.data.resolveSelf(module.exports);",
222
+ "module.hot.dispose(function(data) { data.resolveSelf = resolveSelf; dispose(data); });"
223
+ ]),
224
+ "}",
225
+ keepActive
226
+ ]);
227
+ }
228
+ sources.set("javascript", new RawSource(source));
229
+ return {
230
+ sources,
231
+ runtimeRequirements
232
+ };
233
+ }
234
+
235
+ /**
236
+ * @param {Hash} hash the hash used to track dependencies
237
+ * @param {UpdateHashContext} context context
238
+ * @returns {void}
239
+ */
240
+ updateHash(hash, context) {
241
+ super.updateHash(hash, context);
242
+ hash.update(this.active ? "active" : "");
243
+ hash.update(JSON.stringify(this.data));
244
+ }
245
+ }
246
+
247
+ registerNotSerializable(LazyCompilationProxyModule);
248
+
249
+ class LazyCompilationDependencyFactory extends ModuleFactory {
250
+ constructor(factory) {
251
+ super();
252
+ this._factory = factory;
253
+ }
254
+
255
+ /**
256
+ * @param {ModuleFactoryCreateData} data data object
257
+ * @param {function(Error=, ModuleFactoryResult=): void} callback callback
258
+ * @returns {void}
259
+ */
260
+ create(data, callback) {
261
+ const dependency = /** @type {LazyCompilationDependency} */ (data
262
+ .dependencies[0]);
263
+ callback(null, {
264
+ module: dependency.originalModule
265
+ });
266
+ }
267
+ }
268
+
269
+ class LazyCompilationPlugin {
270
+ /**
271
+ * @param {Object} options options
272
+ * @param {(function(Compiler, string, function(Error?, any?): void): void) | function(Compiler, string): Promise<any>} options.backend the backend
273
+ * @param {string} options.client the client reference
274
+ * @param {boolean} options.entries true, when entries are lazy compiled
275
+ */
276
+ constructor({ backend, client, entries }) {
277
+ this.backend = backend;
278
+ this.client = client;
279
+ this.entries = entries;
280
+ }
281
+ /**
282
+ * Apply the plugin
283
+ * @param {Compiler} compiler the compiler instance
284
+ * @returns {void}
285
+ */
286
+ apply(compiler) {
287
+ let backend;
288
+ compiler.hooks.beforeCompile.tapAsync(
289
+ "LazyCompilationPlugin",
290
+ (params, callback) => {
291
+ if (backend !== undefined) return callback();
292
+ const promise = this.backend(compiler, this.client, (err, result) => {
293
+ if (err) return callback(err);
294
+ backend = result;
295
+ callback();
296
+ });
297
+ if (promise && promise.then) {
298
+ promise.then(b => {
299
+ backend = b;
300
+ callback();
301
+ }, callback);
302
+ }
303
+ }
304
+ );
305
+ compiler.hooks.thisCompilation.tap(
306
+ "LazyCompilationPlugin",
307
+ (compilation, { normalModuleFactory }) => {
308
+ normalModuleFactory.hooks.module.tap(
309
+ "LazyCompilationPlugin",
310
+ (originalModule, createData, resolveData) => {
311
+ if (
312
+ resolveData.dependencies.every(
313
+ dep =>
314
+ dep.type === "import()" ||
315
+ (this.entries && dep.type === "entry")
316
+ ) &&
317
+ !/webpack[/\\]hot[/\\]|webpack-dev-server[/\\]client/.test(
318
+ resolveData.request
319
+ )
320
+ ) {
321
+ const moduleInfo = backend.module(originalModule);
322
+ if (!moduleInfo) return;
323
+ const { client, data, active } = moduleInfo;
324
+
325
+ return new LazyCompilationProxyModule(
326
+ compiler.context,
327
+ originalModule,
328
+ resolveData.request,
329
+ client,
330
+ data,
331
+ active
332
+ );
333
+ }
334
+ }
335
+ );
336
+ compilation.dependencyFactories.set(
337
+ LazyCompilationDependency,
338
+ new LazyCompilationDependencyFactory()
339
+ );
340
+ }
341
+ );
342
+ compiler.hooks.shutdown.tapAsync("LazyCompilationPlugin", callback => {
343
+ backend.dispose(callback);
344
+ });
345
+ }
346
+ }
347
+
348
+ module.exports = LazyCompilationPlugin;
@@ -0,0 +1,86 @@
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 http = require("http");
9
+
10
+ /** @typedef {import("../Compiler")} Compiler */
11
+
12
+ /**
13
+ * @param {Compiler} compiler compiler
14
+ * @param {string} client client reference
15
+ * @param {function(Error?, any?): void} callback callback
16
+ * @returns {void}
17
+ */
18
+ module.exports = (compiler, client, callback) => {
19
+ const logger = compiler.getInfrastructureLogger("LazyCompilationBackend");
20
+ const activeModules = new Map();
21
+ const prefix = "/lazy-compilation-using-";
22
+ const server = http.createServer((req, res) => {
23
+ const keys = req.url.slice(prefix.length).split("@");
24
+ req.socket.on("close", () => {
25
+ setTimeout(() => {
26
+ for (const key of keys) {
27
+ const oldValue = activeModules.get(key) || 0;
28
+ activeModules.set(key, oldValue - 1);
29
+ if (oldValue === 1) {
30
+ logger.log(
31
+ `${key} is no longer in use. Next compilation will skip this module.`
32
+ );
33
+ }
34
+ }
35
+ }, 120000);
36
+ });
37
+ req.socket.setNoDelay(true);
38
+ res.writeHead(200, {
39
+ "content-type": "text/event-stream",
40
+ "Access-Control-Allow-Origin": "*"
41
+ });
42
+ res.write("\n");
43
+ let moduleActivated = false;
44
+ for (const key of keys) {
45
+ const oldValue = activeModules.get(key) || 0;
46
+ activeModules.set(key, oldValue + 1);
47
+ if (oldValue === 0) {
48
+ logger.log(`${key} is now in use and will be compiled.`);
49
+ moduleActivated = true;
50
+ }
51
+ }
52
+ if (moduleActivated && compiler.watching) compiler.watching.invalidate();
53
+ });
54
+ server.listen(err => {
55
+ if (err) return callback(err);
56
+ const addr = server.address();
57
+ if (typeof addr === "string") throw new Error("addr must not be a string");
58
+ const urlBase =
59
+ addr.address === "::" || addr.address === "0.0.0.0"
60
+ ? `http://localhost:${addr.port}`
61
+ : addr.family === "IPv6"
62
+ ? `http://[${addr.address}]:${addr.port}`
63
+ : `http://${addr.address}:${addr.port}`;
64
+ logger.log(
65
+ `Server-Sent-Events server for lazy compilation open at ${urlBase}.`
66
+ );
67
+ callback(null, {
68
+ dispose(callback) {
69
+ server.close(callback);
70
+ },
71
+ module(originalModule) {
72
+ const key = `${encodeURIComponent(
73
+ originalModule.identifier().replace(/\\/g, "/").replace(/@/g, "_")
74
+ ).replace(/%(2F|3A|24|26|2B|2C|3B|3D|3A)/g, decodeURIComponent)}`;
75
+ const active = activeModules.get(key) > 0;
76
+ return {
77
+ client: `webpack/hot/lazy-compilation-${
78
+ compiler.options.externalsPresets.node ? "node" : "web"
79
+ }.js?${encodeURIComponent(urlBase + prefix)}`,
80
+ data: key,
81
+ active
82
+ };
83
+ }
84
+ });
85
+ });
86
+ };
@@ -848,6 +848,7 @@ class JavascriptModulesPlugin {
848
848
  buf.push("");
849
849
  }
850
850
 
851
+ const maybeReturn = returnExportsFromRuntime ? "return " : "";
851
852
  if (!runtimeRequirements.has(RuntimeGlobals.startupNoDefault)) {
852
853
  if (chunkGraph.getNumberOfEntryModules(chunk) > 0) {
853
854
  /** @type {string[]} */
@@ -933,7 +934,7 @@ class JavascriptModulesPlugin {
933
934
  );
934
935
  buf.push("");
935
936
  startup.push("// run startup");
936
- startup.push(`return ${RuntimeGlobals.startup}();`);
937
+ startup.push(`${maybeReturn}${RuntimeGlobals.startup}();`);
937
938
  } else if (runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore)) {
938
939
  buf.push("// the startup function");
939
940
  buf.push(
@@ -951,7 +952,7 @@ class JavascriptModulesPlugin {
951
952
  startup.push("// startup");
952
953
  startup.push(Template.asString(buf2));
953
954
  afterStartup.push("// run runtime startup");
954
- afterStartup.push(`return ${RuntimeGlobals.startup}();`);
955
+ afterStartup.push(`${maybeReturn}${RuntimeGlobals.startup}();`);
955
956
  } else {
956
957
  startup.push("// startup");
957
958
  startup.push(Template.asString(buf2));
@@ -980,7 +981,7 @@ class JavascriptModulesPlugin {
980
981
  `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()}`
981
982
  );
982
983
  startup.push("// run startup");
983
- startup.push(`return ${RuntimeGlobals.startup}();`);
984
+ startup.push(`${maybeReturn}${RuntimeGlobals.startup}();`);
984
985
  }
985
986
  return result;
986
987
  }
@@ -10,6 +10,7 @@ const { SyncBailHook, HookMap } = require("tapable");
10
10
  const vm = require("vm");
11
11
  const Parser = require("../Parser");
12
12
  const StackedMap = require("../util/StackedMap");
13
+ const binarySearchBounds = require("../util/binarySearchBounds");
13
14
  const memoize = require("../util/memoize");
14
15
  const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
15
16
 
@@ -2625,13 +2626,17 @@ class JavascriptParser extends Parser {
2625
2626
  }
2626
2627
 
2627
2628
  walkCallExpression(expression) {
2629
+ const isSimpleFunction = fn => {
2630
+ return fn.params.every(p => p.type === "Identifier");
2631
+ };
2628
2632
  if (
2629
2633
  expression.callee.type === "MemberExpression" &&
2630
2634
  expression.callee.object.type.endsWith("FunctionExpression") &&
2631
2635
  !expression.callee.computed &&
2632
2636
  (expression.callee.property.name === "call" ||
2633
2637
  expression.callee.property.name === "bind") &&
2634
- expression.arguments.length > 0
2638
+ expression.arguments.length > 0 &&
2639
+ isSimpleFunction(expression.callee.object)
2635
2640
  ) {
2636
2641
  // (function(…) { }.call/bind(?, …))
2637
2642
  this._walkIIFE(
@@ -2639,7 +2644,10 @@ class JavascriptParser extends Parser {
2639
2644
  expression.arguments.slice(1),
2640
2645
  expression.arguments[0]
2641
2646
  );
2642
- } else if (expression.callee.type.endsWith("FunctionExpression")) {
2647
+ } else if (
2648
+ expression.callee.type.endsWith("FunctionExpression") &&
2649
+ isSimpleFunction(expression.callee)
2650
+ ) {
2643
2651
  // (function(…) { }(…))
2644
2652
  this._walkIIFE(expression.callee, expression.arguments, null);
2645
2653
  } else {
@@ -3376,9 +3384,16 @@ class JavascriptParser extends Parser {
3376
3384
  }
3377
3385
 
3378
3386
  getComments(range) {
3379
- return this.comments.filter(
3380
- comment => comment.range[0] >= range[0] && comment.range[1] <= range[1]
3381
- );
3387
+ const [rangeStart, rangeEnd] = range;
3388
+ const compare = (comment, needle) => comment.range[0] - needle;
3389
+ let idx = binarySearchBounds.ge(this.comments, rangeStart, compare);
3390
+ let commentsInRange = [];
3391
+ while (this.comments[idx] && this.comments[idx].range[1] <= rangeEnd) {
3392
+ commentsInRange.push(this.comments[idx]);
3393
+ idx++;
3394
+ }
3395
+
3396
+ return commentsInRange;
3382
3397
  }
3383
3398
 
3384
3399
  /**
@@ -87,6 +87,7 @@ const accessWithInit = (accessor, existingLength, initLast = false) => {
87
87
  * @property {string[] | "global"} prefix name prefix
88
88
  * @property {string | false} declare declare name as variable
89
89
  * @property {"error"|"copy"|"assign"} unnamed behavior for unnamed library name
90
+ * @property {"copy"|"assign"=} named behavior for named library name
90
91
  */
91
92
 
92
93
  /**
@@ -94,6 +95,9 @@ const accessWithInit = (accessor, existingLength, initLast = false) => {
94
95
  * @property {string | string[]} name
95
96
  */
96
97
 
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
+
97
101
  /**
98
102
  * @typedef {AssignLibraryPluginParsed} T
99
103
  * @extends {AbstractLibraryPlugin<AssignLibraryPluginParsed>}
@@ -110,6 +114,7 @@ class AssignLibraryPlugin extends AbstractLibraryPlugin {
110
114
  this.prefix = options.prefix;
111
115
  this.declare = options.declare;
112
116
  this.unnamed = options.unnamed;
117
+ this.named = options.named || "assign";
113
118
  }
114
119
 
115
120
  /**
@@ -120,11 +125,15 @@ class AssignLibraryPlugin extends AbstractLibraryPlugin {
120
125
  const { name } = library;
121
126
  if (this.unnamed === "error") {
122
127
  if (typeof name !== "string" && !Array.isArray(name)) {
123
- throw new Error("Library name must be a string or string array");
128
+ throw new Error(
129
+ `Library name must be a string or string array. ${COMMON_LIBRARY_NAME_MESSAGE}`
130
+ );
124
131
  }
125
132
  } else {
126
133
  if (name && typeof name !== "string" && !Array.isArray(name)) {
127
- throw new Error("Library name must be a string, string array or unset");
134
+ throw new Error(
135
+ `Library name must be a string, string array or unset. ${COMMON_LIBRARY_NAME_MESSAGE}`
136
+ );
128
137
  }
129
138
  }
130
139
  return {
@@ -156,12 +165,12 @@ class AssignLibraryPlugin extends AbstractLibraryPlugin {
156
165
  throw new Error(
157
166
  `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(
158
167
  base
159
- )}) or use a different library type (e. g. 'type: "global"', which assign a property on the global scope instead of declaring a variable). Common configuration options that specific library names are 'output.library[.name]', 'entry.xyz.library[.name]', 'ModuleFederationPlugin.name' and 'ModuleFederationPlugin.library[.name]'.`
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}`
160
169
  );
161
170
  }
162
171
  result.add(`${this.declare} ${base};`);
163
172
  }
164
- if (!options.name && this.unnamed === "copy") {
173
+ if (options.name ? this.named === "copy" : this.unnamed === "copy") {
165
174
  result.add(
166
175
  `(function(e, a) { for(var i in a) e[i] = a[i]; if(a.__esModule) Object.defineProperty(e, "__esModule", { value: true }); }(${accessWithInit(
167
176
  fullNameResolved,
@@ -87,6 +87,18 @@ class EnableLibraryPlugin {
87
87
  }).apply(compiler);
88
88
  break;
89
89
  }
90
+ case "assign-properties": {
91
+ //@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
92
+ const AssignLibraryPlugin = require("./AssignLibraryPlugin");
93
+ new AssignLibraryPlugin({
94
+ type,
95
+ prefix: [],
96
+ declare: false,
97
+ unnamed: "error",
98
+ named: "copy"
99
+ }).apply(compiler);
100
+ break;
101
+ }
90
102
  case "assign": {
91
103
  //@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
92
104
  const AssignLibraryPlugin = require("./AssignLibraryPlugin");