webpack 4.14.0 → 4.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/bin/webpack.js +7 -2
  2. package/lib/AsyncDependenciesBlock.js +44 -0
  3. package/lib/AutomaticPrefetchPlugin.js +1 -1
  4. package/lib/Chunk.js +53 -3
  5. package/lib/ChunkGroup.js +1 -1
  6. package/lib/ChunkTemplate.js +14 -2
  7. package/lib/CommentCompilationWarning.js +2 -2
  8. package/lib/Compilation.js +435 -34
  9. package/lib/Compiler.js +57 -4
  10. package/lib/ContextModule.js +3 -15
  11. package/lib/DelegatedModule.js +9 -1
  12. package/lib/DependenciesBlock.js +36 -3
  13. package/lib/DependenciesBlockVariable.js +22 -0
  14. package/lib/Dependency.js +25 -4
  15. package/lib/DllEntryPlugin.js +4 -1
  16. package/lib/DynamicEntryPlugin.js +21 -1
  17. package/lib/EntryOptionPlugin.js +12 -0
  18. package/lib/ExtendedAPIPlugin.js +8 -4
  19. package/lib/ExternalModuleFactoryPlugin.js +1 -1
  20. package/lib/GraphHelpers.js +2 -1
  21. package/lib/HotModuleReplacement.runtime.js +8 -5
  22. package/lib/HotModuleReplacementPlugin.js +114 -116
  23. package/lib/MainTemplate.js +19 -4
  24. package/lib/Module.js +9 -3
  25. package/lib/ModuleReason.js +8 -0
  26. package/lib/MultiEntryPlugin.js +25 -3
  27. package/lib/NormalModule.js +5 -23
  28. package/lib/RuleSet.js +3 -3
  29. package/lib/SingleEntryPlugin.js +14 -0
  30. package/lib/Stats.js +2 -1
  31. package/lib/Template.js +4 -1
  32. package/lib/UmdMainTemplatePlugin.js +12 -12
  33. package/lib/WebpackError.js +4 -0
  34. package/lib/WebpackOptionsDefaulter.js +3 -0
  35. package/lib/WebpackOptionsValidationError.js +0 -1
  36. package/lib/compareLocations.js +13 -17
  37. package/lib/debug/ProfilingPlugin.js +5 -7
  38. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +4 -6
  39. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +0 -2
  40. package/lib/dependencies/LoaderDependency.js +3 -0
  41. package/lib/dependencies/LoaderPlugin.js +3 -1
  42. package/lib/dependencies/ModuleDependency.js +3 -0
  43. package/lib/dependencies/MultiEntryDependency.js +5 -0
  44. package/lib/dependencies/SingleEntryDependency.js +3 -0
  45. package/lib/node/NodeMainTemplateAsync.runtime.js +1 -1
  46. package/lib/optimize/ConcatenatedModule.js +1 -0
  47. package/lib/optimize/SplitChunksPlugin.js +142 -2
  48. package/lib/util/Semaphore.js +12 -0
  49. package/lib/util/SetHelpers.js +4 -4
  50. package/lib/util/SortableSet.js +1 -1
  51. package/lib/util/createHash.js +15 -0
  52. package/lib/util/deterministicGrouping.js +251 -0
  53. package/lib/util/identifier.js +27 -0
  54. package/lib/wasm/WasmMainTemplatePlugin.js +10 -4
  55. package/lib/wasm/WebAssemblyGenerator.js +12 -12
  56. package/lib/wasm/WebAssemblyInInitialChunkError.js +88 -0
  57. package/lib/wasm/WebAssemblyModulesPlugin.js +28 -0
  58. package/lib/webpack.web.js +2 -2
  59. package/package.json +8 -7
  60. package/schemas/WebpackOptions.json +37 -1
@@ -332,7 +332,6 @@ class WebpackOptionsValidationError extends WebpackError {
332
332
  }
333
333
  return baseMessage;
334
334
  } else {
335
- // eslint-disable-line no-fallthrough
336
335
  return `${dataPath} ${err.message} (${JSON.stringify(
337
336
  err,
338
337
  null,
@@ -4,23 +4,13 @@
4
4
  */
5
5
  "use strict";
6
6
 
7
- /**
8
- * @typedef {Object} LineAndColumn
9
- * @property {number=} line
10
- * @property {number=} column
11
- */
12
-
13
- /**
14
- * @typedef {Object} NodeLocation
15
- * @property {LineAndColumn=} start
16
- * @property {LineAndColumn=} end
17
- * @property {number=} index
18
- */
7
+ /** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */
19
8
 
9
+ // TODO webpack 5 remove string type from a and b
20
10
  /**
21
11
  * Compare two locations
22
- * @param {string|NodeLocation} a A location node
23
- * @param {string|NodeLocation} b A location node
12
+ * @param {string|DependencyLocation} a A location node
13
+ * @param {string|DependencyLocation} b A location node
24
14
  * @returns {-1|0|1} sorting comparator value
25
15
  */
26
16
  module.exports = (a, b) => {
@@ -38,7 +28,7 @@ module.exports = (a, b) => {
38
28
  if (typeof b === "string") {
39
29
  return -1;
40
30
  } else if (typeof b === "object") {
41
- if (a.start && b.start) {
31
+ if ("start" in a && "start" in b) {
42
32
  const ap = a.start;
43
33
  const bp = b.start;
44
34
  if (ap.line < bp.line) return -1;
@@ -46,8 +36,14 @@ module.exports = (a, b) => {
46
36
  if (ap.column < bp.column) return -1;
47
37
  if (ap.column > bp.column) return 1;
48
38
  }
49
- if (a.index < b.index) return -1;
50
- if (a.index > b.index) return 1;
39
+ if ("name" in a && "name" in b) {
40
+ if (a.name < b.name) return -1;
41
+ if (a.name > b.name) return 1;
42
+ }
43
+ if ("index" in a && "index" in b) {
44
+ if (a.index < b.index) return -1;
45
+ if (a.index > b.index) return 1;
46
+ }
51
47
  return 0;
52
48
  } else {
53
49
  return 0;
@@ -5,7 +5,8 @@ const schema = require("../../schemas/plugins/debug/ProfilingPlugin.json");
5
5
  let inspector = undefined;
6
6
 
7
7
  try {
8
- inspector = require("inspector"); // eslint-disable-line node/no-missing-require
8
+ // eslint-disable-next-line node/no-missing-require
9
+ inspector = require("inspector");
9
10
  } catch (e) {
10
11
  console.log("Unable to CPU profile in < node 8.0");
11
12
  }
@@ -84,7 +85,7 @@ class Profiler {
84
85
  * @param {string} outputPath The location where to write the log.
85
86
  * @returns {Trace} The trace object
86
87
  */
87
- function createTrace(outputPath) {
88
+ const createTrace = outputPath => {
88
89
  const trace = new Tracer({
89
90
  noStream: true
90
91
  });
@@ -136,10 +137,10 @@ function createTrace(outputPath) {
136
137
  callback();
137
138
  });
138
139
  // Tear down the readable trace stream.
139
- trace.destroy();
140
+ trace.push(null);
140
141
  }
141
142
  };
142
- }
143
+ };
143
144
 
144
145
  const pluginName = "ProfilingPlugin";
145
146
 
@@ -354,7 +355,6 @@ const makeNewProfiledTapFn = (hookName, tracer, { name, type, fn }) => {
354
355
  switch (type) {
355
356
  case "promise":
356
357
  return (...args) => {
357
- // eslint-disable-line
358
358
  const id = ++tracer.counter;
359
359
  tracer.trace.begin({
360
360
  name,
@@ -373,7 +373,6 @@ const makeNewProfiledTapFn = (hookName, tracer, { name, type, fn }) => {
373
373
  };
374
374
  case "async":
375
375
  return (...args) => {
376
- // eslint-disable-line
377
376
  const id = ++tracer.counter;
378
377
  tracer.trace.begin({
379
378
  name,
@@ -392,7 +391,6 @@ const makeNewProfiledTapFn = (hookName, tracer, { name, type, fn }) => {
392
391
  };
393
392
  case "sync":
394
393
  return (...args) => {
395
- // eslint-disable-line
396
394
  const id = ++tracer.counter;
397
395
  // Do not instrument ourself due to the CPU
398
396
  // profile needing to be the last event in the trace.
@@ -23,17 +23,17 @@ const isBoundFunctionExpression = expr => {
23
23
  return true;
24
24
  };
25
25
 
26
- function isUnboundFunctionExpression(expr) {
26
+ const isUnboundFunctionExpression = expr => {
27
27
  if (expr.type === "FunctionExpression") return true;
28
28
  if (expr.type === "ArrowFunctionExpression") return true;
29
29
  return false;
30
- }
30
+ };
31
31
 
32
- function isCallable(expr) {
32
+ const isCallable = expr => {
33
33
  if (isUnboundFunctionExpression(expr)) return true;
34
34
  if (isBoundFunctionExpression(expr)) return true;
35
35
  return false;
36
- }
36
+ };
37
37
 
38
38
  class AMDDefineDependencyParserPlugin {
39
39
  constructor(options) {
@@ -80,7 +80,6 @@ class AMDDefineDependencyParserPlugin {
80
80
  request
81
81
  ))
82
82
  ) {
83
- // eslint-disable-line no-cond-assign
84
83
  dep = new LocalModuleDependency(localModule, undefined, false);
85
84
  dep.loc = expr.loc;
86
85
  parser.state.current.addDependency(dep);
@@ -121,7 +120,6 @@ class AMDDefineDependencyParserPlugin {
121
120
  namedModule
122
121
  ))
123
122
  ) {
124
- // eslint-disable-line no-cond-assign
125
123
  dep = new LocalModuleDependency(localModule, param.range, false);
126
124
  } else {
127
125
  dep = this.newRequireItemDependency(param.string, param.range);
@@ -79,7 +79,6 @@ class AMDRequireDependenciesBlockParserPlugin {
79
79
  request
80
80
  ))
81
81
  ) {
82
- // eslint-disable-line no-cond-assign
83
82
  dep = new LocalModuleDependency(localModule, undefined, false);
84
83
  dep.loc = expr.loc;
85
84
  parser.state.current.addDependency(dep);
@@ -127,7 +126,6 @@ class AMDRequireDependenciesBlockParserPlugin {
127
126
  param.string
128
127
  ))
129
128
  ) {
130
- // eslint-disable-line no-cond-assign
131
129
  dep = new LocalModuleDependency(localModule, param.range, false);
132
130
  } else {
133
131
  dep = this.newRequireItemDependency(param.string, param.range);
@@ -6,6 +6,9 @@
6
6
  const ModuleDependency = require("./ModuleDependency");
7
7
 
8
8
  class LoaderDependency extends ModuleDependency {
9
+ /**
10
+ * @param {string} request request string
11
+ */
9
12
  constructor(request) {
10
13
  super(request);
11
14
  }
@@ -5,6 +5,7 @@
5
5
  "use strict";
6
6
 
7
7
  const LoaderDependency = require("./LoaderDependency");
8
+ const NormalModule = require("../NormalModule");
8
9
 
9
10
  class LoaderPlugin {
10
11
  apply(compiler) {
@@ -57,7 +58,8 @@ class LoaderPlugin {
57
58
  if (!dep.module) {
58
59
  return callback(new Error("Cannot load the module"));
59
60
  }
60
- if (dep.module.error) {
61
+ // TODO consider removing this in webpack 5
62
+ if (dep.module instanceof NormalModule && dep.module.error) {
61
63
  return callback(dep.module.error);
62
64
  }
63
65
  if (!dep.module._source) {
@@ -6,6 +6,9 @@
6
6
  const Dependency = require("../Dependency");
7
7
 
8
8
  class ModuleDependency extends Dependency {
9
+ /**
10
+ * @param {string} request request path which needs resolving
11
+ */
9
12
  constructor(request) {
10
13
  super();
11
14
  this.request = request;
@@ -3,9 +3,14 @@
3
3
  Author Tobias Koppers @sokra
4
4
  */
5
5
  "use strict";
6
+ /** @typedef {import("./SingleEntryDependency")} SingleEntryDependency */
6
7
  const Dependency = require("../Dependency");
7
8
 
8
9
  class MultiEntryDependency extends Dependency {
10
+ /**
11
+ * @param {SingleEntryDependency[]} dependencies an array of SingleEntryDependencies
12
+ * @param {string} name entry name
13
+ */
9
14
  constructor(dependencies, name) {
10
15
  super();
11
16
  this.dependencies = dependencies;
@@ -6,6 +6,9 @@
6
6
  const ModuleDependency = require("./ModuleDependency");
7
7
 
8
8
  class SingleEntryDependency extends ModuleDependency {
9
+ /**
10
+ * @param {string} request request path for entry
11
+ */
9
12
  constructor(request) {
10
13
  super(request);
11
14
  }
@@ -37,7 +37,7 @@ module.exports = function() {
37
37
  });
38
38
  }
39
39
 
40
- //eslint-disable-next-line no-unused-vars
40
+ // eslint-disable-next-line no-unused-vars
41
41
  function hotDisposeChunk(chunkId) {
42
42
  delete installedChunks[chunkId];
43
43
  }
@@ -639,6 +639,7 @@ class ConcatenatedModule extends Module {
639
639
 
640
640
  // Must use full identifier in our cache here to ensure that the source
641
641
  // is updated should our dependencies list change.
642
+ // TODO webpack 5 refactor
642
643
  innerDependencyTemplates.set(
643
644
  "hash",
644
645
  innerDependencyTemplates.get("hash") + this.identifier()
@@ -8,9 +8,16 @@ const crypto = require("crypto");
8
8
  const SortableSet = require("../util/SortableSet");
9
9
  const GraphHelpers = require("../GraphHelpers");
10
10
  const { isSubset } = require("../util/SetHelpers");
11
+ const deterministicGrouping = require("../util/deterministicGrouping");
12
+ const contextify = require("../util/identifier").contextify;
11
13
 
14
+ /** @typedef {import("../Compiler")} Compiler */
12
15
  /** @typedef {import("../Chunk")} Chunk */
13
16
  /** @typedef {import("../Module")} Module */
17
+ /** @typedef {import("../util/deterministicGrouping").Options<Module>} DeterministicGroupingOptionsForModule */
18
+ /** @typedef {import("../util/deterministicGrouping").GroupedItems<Module>} DeterministicGroupingGroupedItemsForModule */
19
+
20
+ const deterministicGroupingForModules = /** @type {function(DeterministicGroupingOptionsForModule): DeterministicGroupingGroupedItemsForModule[]} */ (deterministicGrouping);
14
21
 
15
22
  const hashFilename = name => {
16
23
  return crypto
@@ -104,6 +111,7 @@ module.exports = class SplitChunksPlugin {
104
111
  options.chunks || "all"
105
112
  ),
106
113
  minSize: options.minSize || 0,
114
+ maxSize: options.maxSize || 0,
107
115
  minChunks: options.minChunks || 1,
108
116
  maxAsyncRequests: options.maxAsyncRequests || 1,
109
117
  maxInitialRequests: options.maxInitialRequests || 1,
@@ -112,17 +120,24 @@ module.exports = class SplitChunksPlugin {
112
120
  name: options.name,
113
121
  automaticNameDelimiter: options.automaticNameDelimiter
114
122
  }) || (() => {}),
123
+ hidePathInfo: options.hidePathInfo || false,
115
124
  filename: options.filename || undefined,
116
125
  getCacheGroups: SplitChunksPlugin.normalizeCacheGroups({
117
126
  cacheGroups: options.cacheGroups,
118
127
  automaticNameDelimiter: options.automaticNameDelimiter
119
- })
128
+ }),
129
+ automaticNameDelimiter: options.automaticNameDelimiter,
130
+ fallbackCacheGroup: SplitChunksPlugin.normalizeFallbackCacheGroup(
131
+ options.fallbackCacheGroup || {},
132
+ options
133
+ )
120
134
  };
121
135
  }
122
136
 
123
137
  static normalizeName({ name, automaticNameDelimiter }) {
124
138
  if (name === true) {
125
- const cache = new Map();
139
+ /** @type {WeakMap<Chunk[], Record<string, string>>} */
140
+ const cache = new WeakMap();
126
141
  const fn = (module, chunks, cacheGroup) => {
127
142
  let cacheEntry = cache.get(chunks);
128
143
  if (cacheEntry === undefined) {
@@ -177,6 +192,26 @@ module.exports = class SplitChunksPlugin {
177
192
  if (typeof chunks === "function") return chunks;
178
193
  }
179
194
 
195
+ static normalizeFallbackCacheGroup(
196
+ {
197
+ minSize = undefined,
198
+ maxSize = undefined,
199
+ automaticNameDelimiter = undefined
200
+ },
201
+ {
202
+ minSize: defaultMinSize = undefined,
203
+ maxSize: defaultMaxSize = undefined,
204
+ automaticNameDelimiter: defaultAutomaticNameDelimiter = undefined
205
+ }
206
+ ) {
207
+ return {
208
+ minSize: typeof minSize === "number" ? minSize : defaultMinSize || 0,
209
+ maxSize: typeof maxSize === "number" ? maxSize : defaultMaxSize || 0,
210
+ automaticNameDelimiter:
211
+ automaticNameDelimiter || defaultAutomaticNameDelimiter || "~"
212
+ };
213
+ }
214
+
180
215
  static normalizeCacheGroups({ cacheGroups, automaticNameDelimiter }) {
181
216
  if (typeof cacheGroups === "function") {
182
217
  // TODO webpack 5 remove this
@@ -225,6 +260,7 @@ module.exports = class SplitChunksPlugin {
225
260
  ),
226
261
  enforce: option.enforce,
227
262
  minSize: option.minSize,
263
+ maxSize: option.maxSize,
228
264
  minChunks: option.minChunks,
229
265
  maxAsyncRequests: option.maxAsyncRequests,
230
266
  maxInitialRequests: option.maxInitialRequests,
@@ -278,6 +314,10 @@ module.exports = class SplitChunksPlugin {
278
314
  return false;
279
315
  }
280
316
 
317
+ /**
318
+ * @param {Compiler} compiler webpack compiler
319
+ * @returns {void}
320
+ */
281
321
  apply(compiler) {
282
322
  compiler.hooks.thisCompilation.tap("SplitChunksPlugin", compilation => {
283
323
  let alreadyOptimized = false;
@@ -486,6 +526,12 @@ module.exports = class SplitChunksPlugin {
486
526
  : cacheGroupSource.enforce
487
527
  ? 0
488
528
  : this.options.minSize,
529
+ maxSize:
530
+ cacheGroupSource.maxSize !== undefined
531
+ ? cacheGroupSource.maxSize
532
+ : cacheGroupSource.enforce
533
+ ? 0
534
+ : this.options.maxSize,
489
535
  minChunks:
490
536
  cacheGroupSource.minChunks !== undefined
491
537
  ? cacheGroupSource.minChunks
@@ -512,6 +558,10 @@ module.exports = class SplitChunksPlugin {
512
558
  cacheGroupSource.filename !== undefined
513
559
  ? cacheGroupSource.filename
514
560
  : this.options.filename,
561
+ automaticNameDelimiter:
562
+ cacheGroupSource.automaticNameDelimiter !== undefined
563
+ ? cacheGroupSource.automaticNameDelimiter
564
+ : this.options.automaticNameDelimiter,
515
565
  reuseExistingChunk: cacheGroupSource.reuseExistingChunk
516
566
  };
517
567
  // For all combination of chunk selection
@@ -537,6 +587,9 @@ module.exports = class SplitChunksPlugin {
537
587
  }
538
588
  }
539
589
 
590
+ /** @type {Map<Chunk, {minSize: number, maxSize: number, automaticNameDelimiter: string}>} */
591
+ const maxSizeQueueMap = new Map();
592
+
540
593
  while (chunksInfoMap.size > 0) {
541
594
  // Find best matching entry
542
595
  let bestEntryKey;
@@ -563,6 +616,7 @@ module.exports = class SplitChunksPlugin {
563
616
 
564
617
  let chunkName = item.name;
565
618
  // Variable for the new chunk (lazy created)
619
+ /** @type {Chunk} */
566
620
  let newChunk;
567
621
  // When no chunk name, check if we can reuse a chunk instead of creating a new one
568
622
  let isReused = false;
@@ -689,6 +743,22 @@ module.exports = class SplitChunksPlugin {
689
743
  }
690
744
  }
691
745
  }
746
+
747
+ if (item.cacheGroup.maxSize > 0) {
748
+ const oldMaxSizeSettings = maxSizeQueueMap.get(newChunk);
749
+ maxSizeQueueMap.set(newChunk, {
750
+ minSize: Math.max(
751
+ oldMaxSizeSettings ? oldMaxSizeSettings.minSize : 0,
752
+ item.cacheGroup.minSize
753
+ ),
754
+ maxSize: Math.min(
755
+ oldMaxSizeSettings ? oldMaxSizeSettings.maxSize : Infinity,
756
+ item.cacheGroup.maxSize
757
+ ),
758
+ automaticNameDelimiter: item.cacheGroup.automaticNameDelimiter
759
+ });
760
+ }
761
+
692
762
  // remove all modules from other entries and update size
693
763
  for (const [key, info] of chunksInfoMap) {
694
764
  if (isOverlap(info.chunks, item.chunks)) {
@@ -709,6 +779,76 @@ module.exports = class SplitChunksPlugin {
709
779
  }
710
780
  }
711
781
  }
782
+
783
+ // Make sure that maxSize is fulfilled
784
+ for (const chunk of compilation.chunks.slice()) {
785
+ const { minSize, maxSize, automaticNameDelimiter } =
786
+ maxSizeQueueMap.get(chunk) || this.options.fallbackCacheGroup;
787
+ if (!maxSize) continue;
788
+ const results = deterministicGroupingForModules({
789
+ maxSize,
790
+ minSize,
791
+ items: chunk.modulesIterable,
792
+ getKey(module) {
793
+ const ident = contextify(
794
+ compilation.options.context,
795
+ module.identifier()
796
+ );
797
+ const name = module.nameForCondition
798
+ ? contextify(
799
+ compilation.options.context,
800
+ module.nameForCondition()
801
+ )
802
+ : ident.replace(/^.*!|\?[^?!]*$/g, "");
803
+ const fullKey =
804
+ name + automaticNameDelimiter + hashFilename(ident);
805
+ return fullKey.replace(/[\\/?]/g, "_");
806
+ },
807
+ getSize(module) {
808
+ return module.size();
809
+ }
810
+ });
811
+ results.sort((a, b) => {
812
+ if (a.key < b.key) return -1;
813
+ if (a.key > b.key) return 1;
814
+ return 0;
815
+ });
816
+ for (let i = 0; i < results.length; i++) {
817
+ const group = results[i];
818
+ const key = this.options.hidePathInfo
819
+ ? hashFilename(group.key)
820
+ : group.key;
821
+ let name = chunk.name
822
+ ? chunk.name + automaticNameDelimiter + key
823
+ : null;
824
+ if (name && name.length > 100) {
825
+ name =
826
+ name.slice(0, 100) +
827
+ automaticNameDelimiter +
828
+ hashFilename(name);
829
+ }
830
+ let newPart;
831
+ if (i !== results.length - 1) {
832
+ newPart = compilation.addChunk(name);
833
+ chunk.split(newPart);
834
+ // Add all modules to the new chunk
835
+ for (const module of group.items) {
836
+ if (typeof module.chunkCondition === "function") {
837
+ if (!module.chunkCondition(newPart)) continue;
838
+ }
839
+ // Add module to new chunk
840
+ GraphHelpers.connectChunkAndModule(newPart, module);
841
+ // Remove module from used chunks
842
+ chunk.removeModule(module);
843
+ module.rewriteChunkInReasons(chunk, [newPart]);
844
+ }
845
+ } else {
846
+ // change the chunk to be a part
847
+ newPart = chunk;
848
+ chunk.name = name;
849
+ }
850
+ }
851
+ }
712
852
  }
713
853
  );
714
854
  });
@@ -5,12 +5,24 @@
5
5
  "use strict";
6
6
 
7
7
  class Semaphore {
8
+ /**
9
+ * Creates an instance of Semaphore.
10
+ *
11
+ * @param {number} available the amount available number of "tasks"
12
+ * in the Semaphore
13
+ */
8
14
  constructor(available) {
9
15
  this.available = available;
16
+ /** @type {(function(): void)[]} */
10
17
  this.waiters = [];
18
+ /** @private */
11
19
  this._continue = this._continue.bind(this);
12
20
  }
13
21
 
22
+ /**
23
+ * @param {function(): void} callback function block to capture and run
24
+ * @returns {void}
25
+ */
14
26
  acquire(callback) {
15
27
  if (this.available > 0) {
16
28
  this.available--;
@@ -5,7 +5,7 @@
5
5
  * @param {Set[]} sets an array of sets being checked for shared elements
6
6
  * @returns {Set<TODO>} returns a new Set containing the intersecting items
7
7
  */
8
- function intersect(sets) {
8
+ const intersect = sets => {
9
9
  if (sets.length === 0) return new Set();
10
10
  if (sets.length === 1) return new Set(sets[0]);
11
11
  let minSize = Infinity;
@@ -28,7 +28,7 @@ function intersect(sets) {
28
28
  }
29
29
  }
30
30
  return current;
31
- }
31
+ };
32
32
 
33
33
  /**
34
34
  * Checks if a set is the subset of another set
@@ -36,13 +36,13 @@ function intersect(sets) {
36
36
  * @param {Set<TODO>} smallSet the set whos elements might be contained inside of bigSet
37
37
  * @returns {boolean} returns true if smallSet contains all elements inside of the bigSet
38
38
  */
39
- function isSubset(bigSet, smallSet) {
39
+ const isSubset = (bigSet, smallSet) => {
40
40
  if (bigSet.size < smallSet.size) return false;
41
41
  for (const item of smallSet) {
42
42
  if (!bigSet.has(item)) return false;
43
43
  }
44
44
  return true;
45
- }
45
+ };
46
46
 
47
47
  exports.intersect = intersect;
48
48
  exports.isSubset = isSubset;
@@ -7,7 +7,7 @@
7
7
  class SortableSet extends Set {
8
8
  /**
9
9
  * Create a new sortable set
10
- * @param {Array<T>=} initialIterable The initial iterable value
10
+ * @param {Iterable<T>=} initialIterable The initial iterable value
11
11
  * @typedef {function(T, T): number} SortFunction
12
12
  * @param {SortFunction=} defaultSort Default sorting function
13
13
  */
@@ -4,8 +4,18 @@
4
4
  */
5
5
  "use strict";
6
6
 
7
+ /** @typedef {{new(): Hash}} HashConstructor */
8
+ /**
9
+ * @typedef {Object} Hash
10
+ * @property {function(string|Buffer, string=): Hash} update
11
+ * @property {function(string): string} digest
12
+ */
13
+
7
14
  const BULK_SIZE = 1000;
8
15
 
16
+ /**
17
+ * @implements {Hash}
18
+ */
9
19
  class BulkUpdateDecorator {
10
20
  constructor(hash) {
11
21
  this.hash = hash;
@@ -63,6 +73,11 @@ class DebugHash {
63
73
  }
64
74
  }
65
75
 
76
+ /**
77
+ * Creates a hash by name or function
78
+ * @param {string | HashConstructor} algorithm the algorithm name or a constructor creating a hash
79
+ * @returns {Hash} the hash
80
+ */
66
81
  module.exports = algorithm => {
67
82
  if (typeof algorithm === "function") {
68
83
  return new BulkUpdateDecorator(new algorithm());