webpack 5.50.0 → 5.52.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 (43) hide show
  1. package/README.md +4 -16
  2. package/lib/ChunkGraph.js +75 -1
  3. package/lib/Compilation.js +10 -1
  4. package/lib/Compiler.js +7 -0
  5. package/lib/EvalSourceMapDevToolPlugin.js +2 -2
  6. package/lib/ExternalModule.js +25 -16
  7. package/lib/FileSystemInfo.js +660 -191
  8. package/lib/HotModuleReplacementPlugin.js +14 -0
  9. package/lib/InitFragment.js +23 -0
  10. package/lib/NormalModule.js +10 -2
  11. package/lib/NormalModuleFactory.js +7 -4
  12. package/lib/RuntimeGlobals.js +5 -0
  13. package/lib/RuntimeModule.js +2 -1
  14. package/lib/SourceMapDevToolPlugin.js +2 -2
  15. package/lib/Watching.js +8 -10
  16. package/lib/WebpackOptionsApply.js +1 -3
  17. package/lib/config/defaults.js +0 -1
  18. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +6 -2
  19. package/lib/dependencies/LoaderPlugin.js +94 -98
  20. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +10 -1
  21. package/lib/library/ModuleLibraryPlugin.js +4 -0
  22. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +7 -1
  23. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +2 -2
  24. package/lib/node/ReadFileCompileWasmPlugin.js +2 -1
  25. package/lib/node/RequireChunkLoadingRuntimeModule.js +7 -1
  26. package/lib/optimize/ConcatenatedModule.js +3 -3
  27. package/lib/optimize/MangleExportsPlugin.js +21 -4
  28. package/lib/optimize/SplitChunksPlugin.js +1 -1
  29. package/lib/runtime/GetChunkFilenameRuntimeModule.js +1 -0
  30. package/lib/util/fs.js +40 -0
  31. package/lib/util/identifier.js +26 -8
  32. package/lib/util/internalSerializables.js +1 -0
  33. package/lib/util/propertyAccess.js +54 -1
  34. package/lib/wasm-async/{AsyncWasmChunkLoadingRuntimeModule.js → AsyncWasmLoadingRuntimeModule.js} +3 -3
  35. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +18 -2
  36. package/lib/web/FetchCompileAsyncWasmPlugin.js +2 -2
  37. package/lib/web/FetchCompileWasmPlugin.js +2 -1
  38. package/lib/web/JsonpChunkLoadingRuntimeModule.js +21 -8
  39. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +7 -1
  40. package/package.json +3 -2
  41. package/schemas/WebpackOptions.check.js +1 -1
  42. package/schemas/WebpackOptions.json +0 -4
  43. package/types.d.ts +62 -12
@@ -39,13 +39,28 @@ const comparator = compareSelect(e => e.name, compareStringsNumeric);
39
39
  /**
40
40
  * @param {boolean} deterministic use deterministic names
41
41
  * @param {ExportsInfo} exportsInfo exports info
42
+ * @param {boolean} isNamespace is namespace object
42
43
  * @returns {void}
43
44
  */
44
- const mangleExportsInfo = (deterministic, exportsInfo) => {
45
+ const mangleExportsInfo = (deterministic, exportsInfo, isNamespace) => {
45
46
  if (!canMangle(exportsInfo)) return;
46
47
  const usedNames = new Set();
47
48
  /** @type {ExportInfo[]} */
48
49
  const mangleableExports = [];
50
+
51
+ // Avoid to renamed exports that are not provided when
52
+ // 1. it's not a namespace export: non-provided exports can be found in prototype chain
53
+ // 2. there are other provided exports and deterministic mode is chosen:
54
+ // non-provided exports would break the determinism
55
+ let avoidMangleNonProvided = !isNamespace;
56
+ if (!avoidMangleNonProvided && deterministic) {
57
+ for (const exportInfo of exportsInfo.ownedExports) {
58
+ if (exportInfo.provided !== false) {
59
+ avoidMangleNonProvided = true;
60
+ break;
61
+ }
62
+ }
63
+ }
49
64
  for (const exportInfo of exportsInfo.ownedExports) {
50
65
  const name = exportInfo.name;
51
66
  if (!exportInfo.hasUsedName()) {
@@ -59,7 +74,7 @@ const mangleExportsInfo = (deterministic, exportsInfo) => {
59
74
  name.length === 2 &&
60
75
  /^[a-zA-Z_$][a-zA-Z0-9_$]|^[1-9][0-9]/.test(name)) ||
61
76
  // Don't rename exports that are not provided
62
- exportInfo.provided !== true
77
+ (avoidMangleNonProvided && exportInfo.provided !== true)
63
78
  ) {
64
79
  exportInfo.setUsedName(name);
65
80
  usedNames.add(name);
@@ -73,7 +88,7 @@ const mangleExportsInfo = (deterministic, exportsInfo) => {
73
88
  used === UsageState.OnlyPropertiesUsed ||
74
89
  used === UsageState.Unused
75
90
  ) {
76
- mangleExportsInfo(deterministic, exportInfo.exportsInfo);
91
+ mangleExportsInfo(deterministic, exportInfo.exportsInfo, false);
77
92
  }
78
93
  }
79
94
  }
@@ -143,8 +158,10 @@ class MangleExportsPlugin {
143
158
  "MangleExportsPlugin",
144
159
  modules => {
145
160
  for (const module of modules) {
161
+ const isNamespace =
162
+ module.buildMeta && module.buildMeta.exportsType === "namespace";
146
163
  const exportsInfo = moduleGraph.getExportsInfo(module);
147
- mangleExportsInfo(deterministic, exportsInfo);
164
+ mangleExportsInfo(deterministic, exportsInfo, isNamespace);
148
165
  }
149
166
  }
150
167
  );
@@ -1073,7 +1073,7 @@ module.exports = class SplitChunksPlugin {
1073
1073
  "SplitChunksPlugin\n" +
1074
1074
  `Cache group "${cacheGroup.key}" conflicts with existing chunk.\n` +
1075
1075
  `Both have the same name "${name}" and existing chunk is not a parent of the selected modules.\n` +
1076
- "Use a different name for the cache group or make sure that the existing chunk is a parent (e. g. via dependsOn).\n" +
1076
+ "Use a different name for the cache group or make sure that the existing chunk is a parent (e. g. via dependOn).\n" +
1077
1077
  'HINT: You can omit "name" to automatically create a name.\n' +
1078
1078
  "BREAKING CHANGE: webpack < 5 used to allow to use an entrypoint as splitChunk. " +
1079
1079
  "This is no longer allowed when the entrypoint is not a parent of the selected modules.\n" +
@@ -30,6 +30,7 @@ class GetChunkFilenameRuntimeModule extends RuntimeModule {
30
30
  this.global = global;
31
31
  this.getFilenameForChunk = getFilenameForChunk;
32
32
  this.allChunks = allChunks;
33
+ this.dependentHash = true;
33
34
  }
34
35
 
35
36
  /**
package/lib/util/fs.js CHANGED
@@ -59,6 +59,7 @@ const path = require("path");
59
59
  /** @typedef {function((NodeJS.ErrnoException | null)=, number=): void} NumberCallback */
60
60
  /** @typedef {function((NodeJS.ErrnoException | null)=, IStats=): void} StatsCallback */
61
61
  /** @typedef {function((NodeJS.ErrnoException | Error | null)=, any=): void} ReadJsonCallback */
62
+ /** @typedef {function((NodeJS.ErrnoException | Error | null)=, IStats|string=): void} LstatReadlinkAbsoluteCallback */
62
63
 
63
64
  /**
64
65
  * @typedef {Object} Watcher
@@ -103,6 +104,7 @@ const path = require("path");
103
104
  * @property {function(string, BufferOrStringCallback): void} readlink
104
105
  * @property {function(string, DirentArrayCallback): void} readdir
105
106
  * @property {function(string, StatsCallback): void} stat
107
+ * @property {function(string, StatsCallback): void=} lstat
106
108
  * @property {(function(string, BufferOrStringCallback): void)=} realpath
107
109
  * @property {(function(string=): void)=} purge
108
110
  * @property {(function(string, string): string)=} join
@@ -282,3 +284,41 @@ const readJson = (fs, p, callback) => {
282
284
  });
283
285
  };
284
286
  exports.readJson = readJson;
287
+
288
+ /**
289
+ * @param {InputFileSystem} fs a file system
290
+ * @param {string} p an absolute path
291
+ * @param {ReadJsonCallback} callback callback
292
+ * @returns {void}
293
+ */
294
+ const lstatReadlinkAbsolute = (fs, p, callback) => {
295
+ let i = 3;
296
+ const doReadLink = () => {
297
+ fs.readlink(p, (err, target) => {
298
+ if (err && --i > 0) {
299
+ // It might was just changed from symlink to file
300
+ // we retry 2 times to catch this case before throwing the error
301
+ return doStat();
302
+ }
303
+ if (err || !target) return doStat();
304
+ const value = target.toString();
305
+ callback(null, join(fs, dirname(fs, p), value));
306
+ });
307
+ };
308
+ const doStat = () => {
309
+ if ("lstat" in fs) {
310
+ return fs.lstat(p, (err, stats) => {
311
+ if (err) return callback(err);
312
+ if (stats.isSymbolicLink()) {
313
+ return doReadLink();
314
+ }
315
+ callback(null, stats);
316
+ });
317
+ } else {
318
+ return fs.stat(p, callback);
319
+ }
320
+ };
321
+ if ("lstat" in fs) return doStat();
322
+ doReadLink();
323
+ };
324
+ exports.lstatReadlinkAbsolute = lstatReadlinkAbsolute;
@@ -15,6 +15,13 @@ const WINDOWS_PATH_SEPARATOR_REGEXP = /\\/g;
15
15
  * @property {Map<string, Map<string, string>>=} relativePaths
16
16
  */
17
17
 
18
+ const relativePathToRequest = relativePath => {
19
+ if (relativePath === "") return "./.";
20
+ if (relativePath === "..") return "../.";
21
+ if (relativePath.startsWith("../")) return relativePath;
22
+ return `./${relativePath}`;
23
+ };
24
+
18
25
  /**
19
26
  * @param {string} context context for relative path
20
27
  * @param {string} maybeAbsolutePath path to make relative
@@ -36,10 +43,7 @@ const absoluteToRequest = (context, maybeAbsolutePath) => {
36
43
  querySplitPos === -1
37
44
  ? maybeAbsolutePath
38
45
  : maybeAbsolutePath.slice(0, querySplitPos);
39
- resource = path.posix.relative(context, resource);
40
- if (!resource.startsWith("../")) {
41
- resource = "./" + resource;
42
- }
46
+ resource = relativePathToRequest(path.posix.relative(context, resource));
43
47
  return querySplitPos === -1
44
48
  ? resource
45
49
  : resource + maybeAbsolutePath.slice(querySplitPos);
@@ -53,10 +57,9 @@ const absoluteToRequest = (context, maybeAbsolutePath) => {
53
57
  : maybeAbsolutePath.slice(0, querySplitPos);
54
58
  resource = path.win32.relative(context, resource);
55
59
  if (!WINDOWS_ABS_PATH_REGEXP.test(resource)) {
56
- resource = resource.replace(WINDOWS_PATH_SEPARATOR_REGEXP, "/");
57
- if (!resource.startsWith("../")) {
58
- resource = "./" + resource;
59
- }
60
+ resource = relativePathToRequest(
61
+ resource.replace(WINDOWS_PATH_SEPARATOR_REGEXP, "/")
62
+ );
60
63
  }
61
64
  return querySplitPos === -1
62
65
  ? resource
@@ -214,6 +217,21 @@ const _makePathsRelative = (context, identifier) => {
214
217
 
215
218
  exports.makePathsRelative = makeCacheable(_makePathsRelative);
216
219
 
220
+ /**
221
+ *
222
+ * @param {string} context context for relative path
223
+ * @param {string} identifier identifier for path
224
+ * @returns {string} a converted relative path
225
+ */
226
+ const _makePathsAbsolute = (context, identifier) => {
227
+ return identifier
228
+ .split(SEGMENTS_SPLIT_REGEXP)
229
+ .map(str => requestToAbsolute(context, str))
230
+ .join("");
231
+ };
232
+
233
+ exports.makePathsAbsolute = makeCacheable(_makePathsAbsolute);
234
+
217
235
  /**
218
236
  * @param {string} context absolute context path
219
237
  * @param {string} request any request string may containing absolute paths, query string, etc.
@@ -164,6 +164,7 @@ module.exports = {
164
164
  DllModule: () => require("../DllModule"),
165
165
  ExternalModule: () => require("../ExternalModule"),
166
166
  FileSystemInfo: () => require("../FileSystemInfo"),
167
+ InitFragment: () => require("../InitFragment"),
167
168
  InvalidDependenciesModuleWarning: () =>
168
169
  require("../InvalidDependenciesModuleWarning"),
169
170
  Module: () => require("../Module"),
@@ -6,6 +6,59 @@
6
6
  "use strict";
7
7
 
8
8
  const SAFE_IDENTIFIER = /^[_a-zA-Z$][_a-zA-Z$0-9]*$/;
9
+ const RESERVED_IDENTIFER = new Set([
10
+ "break",
11
+ "case",
12
+ "catch",
13
+ "class",
14
+ "const",
15
+ "continue",
16
+ "debugger",
17
+ "default",
18
+ "delete",
19
+ "do",
20
+ "else",
21
+ "export",
22
+ "extends",
23
+ "finally",
24
+ "for",
25
+ "function",
26
+ "if",
27
+ "import",
28
+ "in",
29
+ "instanceof",
30
+ "new",
31
+ "return",
32
+ "super",
33
+ "switch",
34
+ "this",
35
+ "throw",
36
+ "try",
37
+ "typeof",
38
+ "var",
39
+ "void",
40
+ "while",
41
+ "with",
42
+ "enum",
43
+ // strict mode
44
+ "implements",
45
+ "interface",
46
+ "let",
47
+ "package",
48
+ "private",
49
+ "protected",
50
+ "public",
51
+ "static",
52
+ "yield",
53
+ "yield",
54
+ // module code
55
+ "await",
56
+ // skip future reserved keywords defined under ES1 till ES3
57
+ // additional
58
+ "null",
59
+ "true",
60
+ "false"
61
+ ]);
9
62
 
10
63
  const propertyAccess = (properties, start = 0) => {
11
64
  let str = "";
@@ -13,7 +66,7 @@ const propertyAccess = (properties, start = 0) => {
13
66
  const p = properties[i];
14
67
  if (`${+p}` === p) {
15
68
  str += `[${p}]`;
16
- } else if (SAFE_IDENTIFIER.test(p)) {
69
+ } else if (SAFE_IDENTIFIER.test(p) && !RESERVED_IDENTIFER.has(p)) {
17
70
  str += `.${p}`;
18
71
  } else {
19
72
  str += `[${JSON.stringify(p)}]`;
@@ -9,9 +9,9 @@ const RuntimeGlobals = require("../RuntimeGlobals");
9
9
  const RuntimeModule = require("../RuntimeModule");
10
10
  const Template = require("../Template");
11
11
 
12
- class AsyncWasmChunkLoadingRuntimeModule extends RuntimeModule {
12
+ class AsyncWasmLoadingRuntimeModule extends RuntimeModule {
13
13
  constructor({ generateLoadBinaryCode, supportsStreaming }) {
14
- super("wasm chunk loading", RuntimeModule.STAGE_ATTACH);
14
+ super("wasm loading", RuntimeModule.STAGE_NORMAL);
15
15
  this.generateLoadBinaryCode = generateLoadBinaryCode;
16
16
  this.supportsStreaming = supportsStreaming;
17
17
  }
@@ -75,4 +75,4 @@ class AsyncWasmChunkLoadingRuntimeModule extends RuntimeModule {
75
75
  }
76
76
  }
77
77
 
78
- module.exports = AsyncWasmChunkLoadingRuntimeModule;
78
+ module.exports = AsyncWasmLoadingRuntimeModule;
@@ -189,11 +189,17 @@ const generateImportObject = (
189
189
  };
190
190
 
191
191
  class WasmChunkLoadingRuntimeModule extends RuntimeModule {
192
- constructor({ generateLoadBinaryCode, supportsStreaming, mangleImports }) {
192
+ constructor({
193
+ generateLoadBinaryCode,
194
+ supportsStreaming,
195
+ mangleImports,
196
+ runtimeRequirements
197
+ }) {
193
198
  super("wasm chunk loading", RuntimeModule.STAGE_ATTACH);
194
199
  this.generateLoadBinaryCode = generateLoadBinaryCode;
195
200
  this.supportsStreaming = supportsStreaming;
196
201
  this.mangleImports = mangleImports;
202
+ this._runtimeRequirements = runtimeRequirements;
197
203
  }
198
204
 
199
205
  /**
@@ -203,6 +209,9 @@ class WasmChunkLoadingRuntimeModule extends RuntimeModule {
203
209
  const { chunkGraph, compilation, chunk, mangleImports } = this;
204
210
  const { moduleGraph, outputOptions } = compilation;
205
211
  const fn = RuntimeGlobals.ensureChunkHandlers;
212
+ const withHmr = this._runtimeRequirements.has(
213
+ RuntimeGlobals.hmrDownloadUpdateHandlers
214
+ );
206
215
  const wasmModules = getAllWasmModules(moduleGraph, chunkGraph, chunk);
207
216
  const declarations = [];
208
217
  const importObjects = wasmModules.map(module => {
@@ -247,9 +256,16 @@ class WasmChunkLoadingRuntimeModule extends RuntimeModule {
247
256
  runtime: chunk.runtime
248
257
  }
249
258
  );
259
+
260
+ const stateExpression = withHmr
261
+ ? `${RuntimeGlobals.hmrRuntimeStatePrefix}_wasm`
262
+ : undefined;
263
+
250
264
  return Template.asString([
251
265
  "// object to store loaded and loading wasm modules",
252
- "var installedWasmModules = {};",
266
+ `var installedWasmModules = ${
267
+ stateExpression ? `${stateExpression} = ${stateExpression} || ` : ""
268
+ }{};`,
253
269
  "",
254
270
  // This function is used to delay reading the installed wasm module promises
255
271
  // by a microtask. Sorting them doesn't help because there are edge cases where
@@ -6,7 +6,7 @@
6
6
  "use strict";
7
7
 
8
8
  const RuntimeGlobals = require("../RuntimeGlobals");
9
- const AsyncWasmChunkLoadingRuntimeModule = require("../wasm-async/AsyncWasmChunkLoadingRuntimeModule");
9
+ const AsyncWasmLoadingRuntimeModule = require("../wasm-async/AsyncWasmLoadingRuntimeModule");
10
10
 
11
11
  /** @typedef {import("../Compiler")} Compiler */
12
12
 
@@ -48,7 +48,7 @@ class FetchCompileAsyncWasmPlugin {
48
48
  set.add(RuntimeGlobals.publicPath);
49
49
  compilation.addRuntimeModule(
50
50
  chunk,
51
- new AsyncWasmChunkLoadingRuntimeModule({
51
+ new AsyncWasmLoadingRuntimeModule({
52
52
  generateLoadBinaryCode,
53
53
  supportsStreaming: true
54
54
  })
@@ -58,7 +58,8 @@ class FetchCompileWasmPlugin {
58
58
  new WasmChunkLoadingRuntimeModule({
59
59
  generateLoadBinaryCode,
60
60
  supportsStreaming: true,
61
- mangleImports: this.options.mangleImports
61
+ mangleImports: this.options.mangleImports,
62
+ runtimeRequirements: set
62
63
  })
63
64
  );
64
65
  });
@@ -98,6 +98,10 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
98
98
  const hasJsMatcher = compileBooleanMatcher(conditionMap);
99
99
  const initialChunkIds = getInitialChunkIds(chunk, chunkGraph);
100
100
 
101
+ const stateExpression = withHmr
102
+ ? `${RuntimeGlobals.hmrRuntimeStatePrefix}_jsonp`
103
+ : undefined;
104
+
101
105
  return Template.asString([
102
106
  withBaseURI
103
107
  ? Template.asString([
@@ -108,7 +112,9 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
108
112
  "// object to store loaded and loading chunks",
109
113
  "// undefined = chunk not loaded, null = chunk preloaded/prefetched",
110
114
  "// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded",
111
- "var installedChunks = {",
115
+ `var installedChunks = ${
116
+ stateExpression ? `${stateExpression} = ${stateExpression} || ` : ""
117
+ }{`,
112
118
  Template.indent(
113
119
  Array.from(initialChunkIds, id => `${JSON.stringify(id)}: 0`).join(
114
120
  ",\n"
@@ -389,16 +395,23 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
389
395
  '// add "moreModules" to the modules object,',
390
396
  '// then flag all "chunkIds" as loaded and fire callback',
391
397
  "var moduleId, chunkId, i = 0;",
392
- "for(moduleId in moreModules) {",
398
+ `if(chunkIds.some(${runtimeTemplate.returningFunction(
399
+ "installedChunks[id] !== 0",
400
+ "id"
401
+ )})) {`,
393
402
  Template.indent([
394
- `if(${RuntimeGlobals.hasOwnProperty}(moreModules, moduleId)) {`,
395
- Template.indent(
396
- `${RuntimeGlobals.moduleFactories}[moduleId] = moreModules[moduleId];`
397
- ),
398
- "}"
403
+ "for(moduleId in moreModules) {",
404
+ Template.indent([
405
+ `if(${RuntimeGlobals.hasOwnProperty}(moreModules, moduleId)) {`,
406
+ Template.indent(
407
+ `${RuntimeGlobals.moduleFactories}[moduleId] = moreModules[moduleId];`
408
+ ),
409
+ "}"
410
+ ]),
411
+ "}",
412
+ "if(runtime) var result = runtime(__webpack_require__);"
399
413
  ]),
400
414
  "}",
401
- "if(runtime) var result = runtime(__webpack_require__);",
402
415
  "if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);",
403
416
  "for(;i < chunkIds.length; i++) {",
404
417
  Template.indent([
@@ -67,6 +67,10 @@ class ImportScriptsChunkLoadingRuntimeModule extends RuntimeModule {
67
67
  false
68
68
  );
69
69
 
70
+ const stateExpression = withHmr
71
+ ? `${RuntimeGlobals.hmrRuntimeStatePrefix}_importScripts`
72
+ : undefined;
73
+
70
74
  return Template.asString([
71
75
  withBaseURI
72
76
  ? Template.asString([
@@ -78,7 +82,9 @@ class ImportScriptsChunkLoadingRuntimeModule extends RuntimeModule {
78
82
  "",
79
83
  "// object to store loaded chunks",
80
84
  '// "1" means "already loaded"',
81
- "var installedChunks = {",
85
+ `var installedChunks = ${
86
+ stateExpression ? `${stateExpression} = ${stateExpression} || ` : ""
87
+ }{`,
82
88
  Template.indent(
83
89
  Array.from(initialChunkIds, id => `${JSON.stringify(id)}: 1`).join(
84
90
  ",\n"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webpack",
3
- "version": "5.50.0",
3
+ "version": "5.52.0",
4
4
  "author": "Tobias Koppers @sokra",
5
5
  "description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.",
6
6
  "license": "MIT",
@@ -58,7 +58,7 @@
58
58
  "eslint-plugin-jest": "^24.3.6",
59
59
  "eslint-plugin-jsdoc": "^33.0.0",
60
60
  "eslint-plugin-node": "^11.0.0",
61
- "eslint-plugin-prettier": "^3.1.4",
61
+ "eslint-plugin-prettier": "^4.0.0",
62
62
  "file-loader": "^6.0.0",
63
63
  "fork-ts-checker-webpack-plugin": "^6.0.5",
64
64
  "husky": "^6.0.0",
@@ -66,6 +66,7 @@
66
66
  "istanbul": "^0.4.5",
67
67
  "jest": "^27.0.6",
68
68
  "jest-circus": "^27.0.6",
69
+ "jest-cli": "^27.0.6",
69
70
  "jest-diff": "^27.0.2",
70
71
  "jest-junit": "^12.0.0",
71
72
  "json-loader": "^0.5.7",