webpack 5.18.0 → 5.20.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.

Potentially problematic release.


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

Files changed (51) hide show
  1. package/README.md +10 -47
  2. package/bin/webpack.js +0 -0
  3. package/lib/CleanPlugin.js +357 -0
  4. package/lib/CodeGenerationResults.js +28 -26
  5. package/lib/Compilation.js +192 -12
  6. package/lib/Dependency.js +1 -1
  7. package/lib/FlagDependencyUsagePlugin.js +8 -4
  8. package/lib/Generator.js +1 -0
  9. package/lib/ModuleGraph.js +8 -0
  10. package/lib/ModuleGraphConnection.js +3 -3
  11. package/lib/ModuleProfile.js +31 -4
  12. package/lib/NormalModule.js +17 -3
  13. package/lib/ProgressPlugin.js +12 -10
  14. package/lib/RuntimeGlobals.js +14 -0
  15. package/lib/RuntimePlugin.js +8 -0
  16. package/lib/RuntimeTemplate.js +1 -1
  17. package/lib/WebpackOptionsApply.js +16 -7
  18. package/lib/asset/AssetGenerator.js +10 -1
  19. package/lib/asset/AssetModulesPlugin.js +14 -5
  20. package/lib/async-modules/AwaitDependenciesInitFragment.js +12 -2
  21. package/lib/cache/IdleFileCachePlugin.js +9 -3
  22. package/lib/config/defaults.js +13 -2
  23. package/lib/config/normalization.js +1 -0
  24. package/lib/container/ContainerEntryModule.js +4 -1
  25. package/lib/container/ContainerPlugin.js +4 -2
  26. package/lib/dependencies/HarmonyCompatibilityDependency.js +5 -4
  27. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +1 -1
  28. package/lib/dependencies/HarmonyImportSideEffectDependency.js +1 -1
  29. package/lib/dependencies/HarmonyImportSpecifierDependency.js +13 -5
  30. package/lib/dependencies/URLDependency.js +9 -4
  31. package/lib/hmr/LazyCompilationPlugin.js +29 -3
  32. package/lib/hmr/lazyCompilationBackend.js +2 -3
  33. package/lib/index.js +4 -0
  34. package/lib/javascript/JavascriptModulesPlugin.js +2 -2
  35. package/lib/optimize/InnerGraph.js +28 -0
  36. package/lib/runtime/AsyncModuleRuntimeModule.js +137 -0
  37. package/lib/serialization/BinaryMiddleware.js +10 -2
  38. package/lib/sharing/ShareRuntimeModule.js +1 -1
  39. package/lib/util/ArrayQueue.js +103 -0
  40. package/lib/util/AsyncQueue.js +58 -27
  41. package/lib/util/ParallelismFactorCalculator.js +59 -0
  42. package/lib/util/fs.js +3 -0
  43. package/lib/util/runtime.js +135 -24
  44. package/lib/validateSchema.js +2 -2
  45. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +24 -22
  46. package/package.json +2 -3
  47. package/schemas/WebpackOptions.json +65 -0
  48. package/schemas/_container.json +4 -0
  49. package/schemas/plugins/container/ContainerPlugin.json +4 -0
  50. package/schemas/plugins/container/ModuleFederationPlugin.json +4 -0
  51. package/types.d.ts +111 -19
package/README.md CHANGED
@@ -111,14 +111,9 @@ within webpack itself use this plugin interface. This makes webpack very
111
111
  | :---------------------------------------: | :----------------: | :-----------------: | :-------------------------------------------------------------------------------------- |
112
112
  | [mini-css-extract-plugin][mini-css] | ![mini-css-npm] | ![mini-css-size] | Extracts CSS into separate files. It creates a CSS file per JS file which contains CSS. |
113
113
  | [compression-webpack-plugin][compression] | ![compression-npm] | ![compression-size] | Prepares compressed versions of assets to serve them with Content-Encoding |
114
- | [i18n-webpack-plugin][i18n] | ![i18n-npm] | ![i18n-size] | Adds i18n support to your bundles |
115
114
  | [html-webpack-plugin][html-plugin] | ![html-plugin-npm] | ![html-plugin-size] | Simplifies creation of HTML files (`index.html`) to serve your bundles |
116
- | [extract-text-webpack-plugin][extract] | ![extract-npm] | ![extract-size] | Extract text from a bundle, or bundles, into a separate file |
117
115
 
118
116
  [common-npm]: https://img.shields.io/npm/v/webpack.svg
119
- [extract]: https://github.com/webpack-contrib/extract-text-webpack-plugin
120
- [extract-npm]: https://img.shields.io/npm/v/extract-text-webpack-plugin.svg
121
- [extract-size]: https://packagephobia.com/badge?p=extract-text-webpack-plugin
122
117
  [mini-css]: https://github.com/webpack-contrib/mini-css-extract-plugin
123
118
  [mini-css-npm]: https://img.shields.io/npm/v/mini-css-extract-plugin.svg
124
119
  [mini-css-size]: https://packagephobia.com/badge?p=mini-css-extract-plugin
@@ -128,9 +123,6 @@ within webpack itself use this plugin interface. This makes webpack very
128
123
  [compression]: https://github.com/webpack-contrib/compression-webpack-plugin
129
124
  [compression-npm]: https://img.shields.io/npm/v/compression-webpack-plugin.svg
130
125
  [compression-size]: https://packagephobia.com/badge?p=compression-webpack-plugin
131
- [i18n]: https://github.com/webpack-contrib/i18n-webpack-plugin
132
- [i18n-npm]: https://img.shields.io/npm/v/i18n-webpack-plugin.svg
133
- [i18n-size]: https://packagephobia.com/badge?p=i18n-webpack-plugin
134
126
  [html-plugin]: https://github.com/jantimon/html-webpack-plugin
135
127
  [html-plugin-npm]: https://img.shields.io/npm/v/html-webpack-plugin.svg
136
128
  [html-plugin-size]: https://packagephobia.com/badge?p=html-webpack-plugin
@@ -168,32 +160,22 @@ or are automatically applied via regex from your webpack configuration.
168
160
 
169
161
  #### JSON
170
162
 
171
- | Name | Status | Install Size | Description |
172
- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------: | :-----------: | :-------------------------------------- |
173
- | <a href="https://github.com/webpack-contrib/json-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/json.svg"></a> | ![json-npm] | ![json-size] | Loads a JSON file (included by default) |
174
- | <a href="https://github.com/webpack-contrib/json5-loader"><img width="48" height="10.656" src="https://cdn.rawgit.com/json5/json5-logo/master/json5-logo.svg"></a> | ![json5-npm] | ![json5-size] | Loads and transpiles a JSON 5 file |
175
- | <a href="https://github.com/awnist/cson-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/coffeescript.svg"></a> | ![cson-npm] | ![cson-size] | Loads and transpiles a CSON file |
163
+ | Name | Status | Install Size | Description |
164
+ | :---------------------------------------------------------------------------------------------------------------------------------------: | :---------: | :----------: | :------------------------------: |
165
+ | <a href="https://github.com/awnist/cson-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/coffeescript.svg"></a> | ![cson-npm] | ![cson-size] | Loads and transpiles a CSON file |
176
166
 
177
- [json-npm]: https://img.shields.io/npm/v/json-loader.svg
178
- [json-size]: https://packagephobia.com/badge?p=json-loader
179
- [json5-npm]: https://img.shields.io/npm/v/json5-loader.svg
180
- [json5-size]: https://packagephobia.com/badge?p=json5-loader
181
167
  [cson-npm]: https://img.shields.io/npm/v/cson-loader.svg
182
168
  [cson-size]: https://packagephobia.com/badge?p=cson-loader
183
169
 
184
170
  #### Transpiling
185
171
 
186
- | Name | Status | Install Size | Description |
187
- | :--------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------: | :------------------------: | :--------------------------------------------------------------------------------------------------- |
188
- | <a href="https://github.com/webpack-contrib/script-loader">`<script>`</a> | ![script-npm] | ![script-size] | Executes a JavaScript file once in global context (like in script tag), `require()`s are not parsed |
189
- | <a href="https://github.com/babel/babel-loader"><img width="48" height="48" title="babel-loader" src="https://worldvectorlogo.com/logos/babel-10.svg"></a> | ![babel-npm] | ![babel-size] | Loads ES2015+ code and transpiles to ES5 using <a href="https://github.com/babel/babel">Babel</a> |
190
- | <a href="https://github.com/jupl/traceur-loader"><img width="48" height="48" src="https://google.github.com/traceur-compiler/logo/tc.svg"></a> | ![traceur-npm] | ![traceur-size] | Loads ES2015+ code and transpiles to ES5 using [Traceur](https://github.com/google/traceur-compiler) |
191
- | <a href="https://github.com/TypeStrong/ts-loader"><img width="48" height="48" src="https://cdn.rawgit.com/Microsoft/TypeScript/master/doc/logo.svg"></a> | ![type-npm] | ![type-size] | Loads TypeScript like JavaScript |
192
- | [`awesome-typescript-loader`](https://github.com/s-panferov/awesome-typescript-loader) | ![awesome-typescript-npm] | ![awesome-typescript-size] | Awesome TypeScript loader for webpack |
193
- | <a href="https://github.com/webpack-contrib/coffee-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/coffeescript.svg"></a> | ![coffee-npm] | ![coffee-size] | Loads CoffeeScript like JavaScript |
194
-
195
- [script-npm]: https://img.shields.io/npm/v/script-loader.svg
196
- [script-size]: https://packagephobia.com/badge?p=script-loader
172
+ | Name | Status | Install Size | Description |
173
+ | :--------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------: | :-------------: | :--------------------------------------------------------------------------------------------------- |
174
+ | <a href="https://github.com/babel/babel-loader"><img width="48" height="48" title="babel-loader" src="https://worldvectorlogo.com/logos/babel-10.svg"></a> | ![babel-npm] | ![babel-size] | Loads ES2015+ code and transpiles to ES5 using <a href="https://github.com/babel/babel">Babel</a> |
175
+ | <a href="https://github.com/jupl/traceur-loader"><img width="48" height="48" src="https://google.github.com/traceur-compiler/logo/tc.svg"></a> | ![traceur-npm] | ![traceur-size] | Loads ES2015+ code and transpiles to ES5 using [Traceur](https://github.com/google/traceur-compiler) |
176
+ | <a href="https://github.com/TypeStrong/ts-loader"><img width="48" height="48" src="https://cdn.rawgit.com/Microsoft/TypeScript/master/doc/logo.svg"></a> | ![type-npm] | ![type-size] | Loads TypeScript like JavaScript |
177
+ | <a href="https://github.com/webpack-contrib/coffee-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/coffeescript.svg"></a> | ![coffee-npm] | ![coffee-size] | Loads CoffeeScript like JavaScript |
178
+
197
179
  [babel-npm]: https://img.shields.io/npm/v/babel-loader.svg
198
180
  [babel-size]: https://packagephobia.com/badge?p=babel-loader
199
181
  [traceur-npm]: https://img.shields.io/npm/v/traceur-loader.svg
@@ -202,8 +184,6 @@ or are automatically applied via regex from your webpack configuration.
202
184
  [coffee-size]: https://packagephobia.com/badge?p=coffee-loader
203
185
  [type-npm]: https://img.shields.io/npm/v/ts-loader.svg
204
186
  [type-size]: https://packagephobia.com/badge?p=ts-loader
205
- [awesome-typescript-npm]: https://img.shields.io/npm/v/awesome-typescript-loader.svg
206
- [awesome-typescript-size]: https://packagephobia.com/badge?p=awesome-typescript-loader
207
187
 
208
188
  #### Templating
209
189
 
@@ -252,23 +232,6 @@ or are automatically applied via regex from your webpack configuration.
252
232
  [postcss-npm]: https://img.shields.io/npm/v/postcss-loader.svg
253
233
  [postcss-size]: https://packagephobia.com/badge?p=postcss-loader
254
234
 
255
- #### Linting & Testing
256
-
257
- | Name | Status | Install Size | Description |
258
- | :--------------------------------------------------------------------------------------------------------------------------------------------: | :-----------: | :------------: | :-------------------------------------- |
259
- | <a href="https://github.com/webpack-contrib/mocha-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/mocha.svg"></a> | ![mocha-npm] | ![mocha-size] | Tests with mocha (Browser/NodeJS) |
260
- | <a href="https://github.com/webpack-contrib/eslint-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/eslint.svg"></a> | ![eslint-npm] | ![eslint-size] | PreLoader for linting code using ESLint |
261
- | <a href="https://github.com/webpack-contrib/jshint-loader"><img width="48" height="20.64" src="https://jshint.com/res/jshint-dark.png"></a> | ![jshint-npm] | ![jshint-size] | PreLoader for linting code using JSHint |
262
-
263
- [mocha-npm]: https://img.shields.io/npm/v/mocha-loader.svg
264
- [mocha-size]: https://packagephobia.com/badge?p=mocha-loader
265
- [eslint-npm]: https://img.shields.io/npm/v/eslint-loader.svg
266
- [eslint-size]: https://packagephobia.com/badge?p=eslint-loader
267
- [jshint-npm]: https://img.shields.io/npm/v/jshint-loader.svg
268
- [jshint-size]: https://packagephobia.com/badge?p=jshint-loader
269
- [jscs-npm]: https://img.shields.io/npm/v/jscs-loader.svg
270
- [jscs-size]: https://packagephobia.com/badge?p=jscs-loader
271
-
272
235
  #### Frameworks
273
236
 
274
237
  | Name | Status | Install Size | Description |
package/bin/webpack.js CHANGED
File without changes
@@ -0,0 +1,357 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Sergey Melyukov @smelukov
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const asyncLib = require("neo-async");
9
+ const { validate } = require("schema-utils");
10
+ const { SyncBailHook } = require("tapable");
11
+ const Compilation = require("../lib/Compilation");
12
+ const { join } = require("./util/fs");
13
+ const memoize = require("./util/memoize");
14
+ const processAsyncTree = require("./util/processAsyncTree");
15
+
16
+ /** @typedef {import("../declarations/WebpackOptions").CleanOptions} CleanOptions */
17
+ /** @typedef {import("./Compiler")} Compiler */
18
+ /** @typedef {import("./logging/Logger").Logger} Logger */
19
+ /** @typedef {import("./util/fs").OutputFileSystem} OutputFileSystem */
20
+
21
+ /** @typedef {(function(string):boolean)|RegExp} IgnoreItem */
22
+ /** @typedef {function(IgnoreItem): void} AddToIgnoreCallback */
23
+
24
+ /**
25
+ * @typedef {Object} CleanPluginCompilationHooks
26
+ * @property {SyncBailHook<[string], boolean>} keep when returning true the file/directory will be kept during cleaning, returning false will clean it and ignore the following plugins and config
27
+ */
28
+
29
+ const getSchema = memoize(() => {
30
+ const { definitions } = require("../schemas/WebpackOptions.json");
31
+ return {
32
+ definitions,
33
+ oneOf: [{ $ref: "#/definitions/CleanOptions" }]
34
+ };
35
+ });
36
+
37
+ /**
38
+ * @param {OutputFileSystem} fs filesystem
39
+ * @param {string} outputPath output path
40
+ * @param {Set<string>} currentAssets filename of the current assets (must not start with .. or ., must only use / as path separator)
41
+ * @param {function(Error=, Set<string>=): void} callback returns the filenames of the assets that shouldn't be there
42
+ * @returns {void}
43
+ */
44
+ const getDiffToFs = (fs, outputPath, currentAssets, callback) => {
45
+ const directories = new Set();
46
+ // get directories of assets
47
+ for (const asset of currentAssets) {
48
+ directories.add(asset.replace(/(^|\/)[^/]*$/, ""));
49
+ }
50
+ // and all parent directories
51
+ for (const directory of directories) {
52
+ directories.add(directory.replace(/(^|\/)[^/]*$/, ""));
53
+ }
54
+ const diff = new Set();
55
+ asyncLib.forEachLimit(
56
+ directories,
57
+ 10,
58
+ (directory, callback) => {
59
+ fs.readdir(join(fs, outputPath, directory), (err, entries) => {
60
+ if (err) {
61
+ if (err.code === "ENOENT") return callback();
62
+ if (err.code === "ENOTDIR") {
63
+ diff.add(directory);
64
+ return callback();
65
+ }
66
+ return callback(err);
67
+ }
68
+ for (const entry of entries) {
69
+ const file = /** @type {string} */ (entry);
70
+ const filename = directory ? `${directory}/${file}` : file;
71
+ if (!directories.has(filename) && !currentAssets.has(filename)) {
72
+ diff.add(filename);
73
+ }
74
+ }
75
+ callback();
76
+ });
77
+ },
78
+ err => {
79
+ if (err) return callback(err);
80
+
81
+ callback(null, diff);
82
+ }
83
+ );
84
+ };
85
+
86
+ /**
87
+ * @param {Set<string>} currentAssets assets list
88
+ * @param {Set<string>} oldAssets old assets list
89
+ * @returns {Set<string>} diff
90
+ */
91
+ const getDiffToOldAssets = (currentAssets, oldAssets) => {
92
+ const diff = new Set();
93
+ for (const asset of oldAssets) {
94
+ if (!currentAssets.has(asset)) diff.add(asset);
95
+ }
96
+ return diff;
97
+ };
98
+
99
+ /**
100
+ * @param {OutputFileSystem} fs filesystem
101
+ * @param {string} outputPath output path
102
+ * @param {boolean} dry only log instead of fs modification
103
+ * @param {Logger} logger logger
104
+ * @param {Set<string>} diff filenames of the assets that shouldn't be there
105
+ * @param {function(string): boolean} isKept check if the entry is ignored
106
+ * @param {function(Error=): void} callback callback
107
+ * @returns {void}
108
+ */
109
+ const applyDiff = (fs, outputPath, dry, logger, diff, isKept, callback) => {
110
+ const log = msg => {
111
+ if (dry) {
112
+ logger.info(msg);
113
+ } else {
114
+ logger.log(msg);
115
+ }
116
+ };
117
+ /** @typedef {{ type: "check" | "unlink" | "rmdir", filename: string, parent: { remaining: number, job: Job } | undefined }} Job */
118
+ /** @type {Job[]} */
119
+ const jobs = Array.from(diff, filename => ({
120
+ type: "check",
121
+ filename,
122
+ parent: undefined
123
+ }));
124
+ processAsyncTree(
125
+ jobs,
126
+ 10,
127
+ ({ type, filename, parent }, push, callback) => {
128
+ const handleError = err => {
129
+ if (err.code === "ENOENT") {
130
+ log(`${filename} was removed during cleaning by something else`);
131
+ handleParent();
132
+ return callback();
133
+ }
134
+ return callback(err);
135
+ };
136
+ const handleParent = () => {
137
+ if (parent && --parent.remaining === 0) push(parent.job);
138
+ };
139
+ const path = join(fs, outputPath, filename);
140
+ switch (type) {
141
+ case "check":
142
+ if (isKept(filename)) {
143
+ // do not decrement parent entry as we don't want to delete the parent
144
+ log(`${filename} will be kept`);
145
+ return process.nextTick(callback);
146
+ }
147
+ fs.stat(path, (err, stats) => {
148
+ if (err) return handleError(err);
149
+ if (!stats.isDirectory()) {
150
+ push({
151
+ type: "unlink",
152
+ filename,
153
+ parent
154
+ });
155
+ return callback();
156
+ }
157
+ fs.readdir(path, (err, entries) => {
158
+ if (err) return handleError(err);
159
+ /** @type {Job} */
160
+ const deleteJob = {
161
+ type: "rmdir",
162
+ filename,
163
+ parent
164
+ };
165
+ if (entries.length === 0) {
166
+ push(deleteJob);
167
+ } else {
168
+ const parentToken = {
169
+ remaining: entries.length,
170
+ job: deleteJob
171
+ };
172
+ for (const entry of entries) {
173
+ const file = /** @type {string} */ (entry);
174
+ if (file.startsWith(".")) {
175
+ log(
176
+ `${filename} will be kept (dot-files will never be removed)`
177
+ );
178
+ continue;
179
+ }
180
+ push({
181
+ type: "check",
182
+ filename: `${filename}/${file}`,
183
+ parent: parentToken
184
+ });
185
+ }
186
+ }
187
+ return callback();
188
+ });
189
+ });
190
+ break;
191
+ case "rmdir":
192
+ log(`${filename} will be removed`);
193
+ if (dry) {
194
+ handleParent();
195
+ return process.nextTick(callback);
196
+ }
197
+ if (!fs.rmdir) {
198
+ logger.warn(
199
+ `${filename} can't be removed because output file system doesn't support removing directories (rmdir)`
200
+ );
201
+ return process.nextTick(callback);
202
+ }
203
+ fs.rmdir(path, err => {
204
+ if (err) return handleError(err);
205
+ handleParent();
206
+ callback();
207
+ });
208
+ break;
209
+ case "unlink":
210
+ log(`${filename} will be removed`);
211
+ if (dry) {
212
+ handleParent();
213
+ return process.nextTick(callback);
214
+ }
215
+ if (!fs.unlink) {
216
+ logger.warn(
217
+ `${filename} can't be removed because output file system doesn't support removing files (rmdir)`
218
+ );
219
+ return process.nextTick(callback);
220
+ }
221
+ fs.unlink(path, err => {
222
+ if (err) return handleError(err);
223
+ handleParent();
224
+ callback();
225
+ });
226
+ break;
227
+ }
228
+ },
229
+ callback
230
+ );
231
+ };
232
+
233
+ /** @type {WeakMap<Compilation, CleanPluginCompilationHooks>} */
234
+ const compilationHooksMap = new WeakMap();
235
+
236
+ class CleanPlugin {
237
+ /**
238
+ * @param {Compilation} compilation the compilation
239
+ * @returns {CleanPluginCompilationHooks} the attached hooks
240
+ */
241
+ static getCompilationHooks(compilation) {
242
+ if (!(compilation instanceof Compilation)) {
243
+ throw new TypeError(
244
+ "The 'compilation' argument must be an instance of Compilation"
245
+ );
246
+ }
247
+ let hooks = compilationHooksMap.get(compilation);
248
+ if (hooks === undefined) {
249
+ hooks = {
250
+ /** @type {SyncBailHook<[string], boolean>} */
251
+ keep: new SyncBailHook(["ignore"])
252
+ };
253
+ compilationHooksMap.set(compilation, hooks);
254
+ }
255
+ return hooks;
256
+ }
257
+
258
+ /** @param {CleanOptions} [options] options */
259
+ constructor(options = {}) {
260
+ validate(getSchema(), options, {
261
+ name: "Clean Plugin",
262
+ baseDataPath: "options"
263
+ });
264
+
265
+ this.options = { dry: false, ...options };
266
+ }
267
+
268
+ /**
269
+ * Apply the plugin
270
+ * @param {Compiler} compiler the compiler instance
271
+ * @returns {void}
272
+ */
273
+ apply(compiler) {
274
+ const { dry, keep } = this.options;
275
+
276
+ const keepFn =
277
+ typeof keep === "function"
278
+ ? keep
279
+ : typeof keep === "string"
280
+ ? path => path.startsWith(keep)
281
+ : typeof keep === "object" && keep.test
282
+ ? path => keep.test(path)
283
+ : () => false;
284
+
285
+ // We assume that no external modification happens while the compiler is active
286
+ // So we can store the old assets and only diff to them to avoid fs access on
287
+ // incremental builds
288
+ let oldAssets;
289
+
290
+ compiler.hooks.emit.tapAsync(
291
+ {
292
+ name: "CleanPlugin",
293
+ stage: 100
294
+ },
295
+ (compilation, callback) => {
296
+ const hooks = CleanPlugin.getCompilationHooks(compilation);
297
+ const logger = compilation.getLogger("webpack.CleanPlugin");
298
+ const fs = compiler.outputFileSystem;
299
+
300
+ if (!fs.readdir) {
301
+ return callback(
302
+ new Error(
303
+ "CleanPlugin: Output filesystem doesn't support listing directories (readdir)"
304
+ )
305
+ );
306
+ }
307
+
308
+ const currentAssets = new Set();
309
+ for (const asset of Object.keys(compilation.assets)) {
310
+ if (/^[A-Za-z]:\\|^\/|^\\\\/.test(asset)) continue;
311
+ let normalizedAsset;
312
+ let newNormalizedAsset = asset.replace(/\\/g, "/");
313
+ do {
314
+ normalizedAsset = newNormalizedAsset;
315
+ newNormalizedAsset = normalizedAsset.replace(
316
+ /(^|\/)(?!\.\.)[^/]+\/\.\.\//g,
317
+ "$1"
318
+ );
319
+ } while (newNormalizedAsset !== normalizedAsset);
320
+ if (normalizedAsset.startsWith("../")) continue;
321
+ currentAssets.add(normalizedAsset);
322
+ }
323
+
324
+ const outputPath = compilation.getPath(compiler.outputPath, {});
325
+
326
+ const isKept = path => {
327
+ const result = hooks.keep.call(path);
328
+ if (result !== undefined) return result;
329
+ return keepFn(path);
330
+ };
331
+
332
+ const diffCallback = (err, diff) => {
333
+ if (err) {
334
+ oldAssets = undefined;
335
+ return callback(err);
336
+ }
337
+ applyDiff(fs, outputPath, dry, logger, diff, isKept, err => {
338
+ if (err) {
339
+ oldAssets = undefined;
340
+ } else {
341
+ oldAssets = currentAssets;
342
+ }
343
+ callback(err);
344
+ });
345
+ };
346
+
347
+ if (oldAssets) {
348
+ diffCallback(null, getDiffToOldAssets(currentAssets, oldAssets));
349
+ } else {
350
+ getDiffToFs(fs, outputPath, currentAssets, diffCallback);
351
+ }
352
+ }
353
+ );
354
+ }
355
+ }
356
+
357
+ module.exports = CleanPlugin;
@@ -18,8 +18,6 @@ class CodeGenerationResults {
18
18
  constructor() {
19
19
  /** @type {Map<Module, RuntimeSpecMap<CodeGenerationResult>>} */
20
20
  this.map = new Map();
21
- /** @type {Map<Module, RuntimeSpecMap<string>>} */
22
- this.hashes = new Map();
23
21
  }
24
22
 
25
23
  /**
@@ -38,31 +36,33 @@ class CodeGenerationResults {
38
36
  );
39
37
  }
40
38
  if (runtime === undefined) {
41
- const results = new Set(entry.values());
42
- if (results.size !== 1) {
43
- throw new Error(
44
- `No unique code generation entry for unspecified runtime for ${module.identifier()} (existing runtimes: ${Array.from(
45
- entry.keys(),
46
- r => runtimeToString(r)
47
- ).join(", ")}).
39
+ if (entry.size > 1) {
40
+ const results = new Set(entry.values());
41
+ if (results.size !== 1) {
42
+ throw new Error(
43
+ `No unique code generation entry for unspecified runtime for ${module.identifier()} (existing runtimes: ${Array.from(
44
+ entry.keys(),
45
+ r => runtimeToString(r)
46
+ ).join(", ")}).
48
47
  Caller might not support runtime-dependent code generation (opt-out via optimization.usedExports: "global").`
49
- );
50
- }
51
- return results.values().next().value;
52
- } else {
53
- const result = entry.get(runtime);
54
- if (result === undefined) {
55
- throw new Error(
56
- `No code generation entry for runtime ${runtimeToString(
57
- runtime
58
- )} for ${module.identifier()} (existing runtimes: ${Array.from(
59
- entry.keys(),
60
- r => runtimeToString(r)
61
- ).join(", ")})`
62
- );
48
+ );
49
+ }
50
+ return results.values().next().value;
63
51
  }
64
- return result;
52
+ return entry.values().next().value;
53
+ }
54
+ const result = entry.get(runtime);
55
+ if (result === undefined) {
56
+ throw new Error(
57
+ `No code generation entry for runtime ${runtimeToString(
58
+ runtime
59
+ )} for ${module.identifier()} (existing runtimes: ${Array.from(
60
+ entry.keys(),
61
+ r => runtimeToString(r)
62
+ ).join(", ")})`
63
+ );
65
64
  }
65
+ return result;
66
66
  }
67
67
 
68
68
  /**
@@ -75,11 +75,13 @@ Caller might not support runtime-dependent code generation (opt-out via optimiza
75
75
  if (entry === undefined) {
76
76
  return false;
77
77
  }
78
- if (runtime === undefined) {
78
+ if (runtime !== undefined) {
79
+ return entry.has(runtime);
80
+ } else if (entry.size > 1) {
79
81
  const results = new Set(entry.values());
80
82
  return results.size === 1;
81
83
  } else {
82
- return entry.has(runtime);
84
+ return entry.size === 1;
83
85
  }
84
86
  }
85
87