webpack 5.108.3 → 5.109.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.
Files changed (191) hide show
  1. package/lib/APIPlugin.js +48 -29
  2. package/lib/CacheFacade.js +8 -0
  3. package/lib/ChunkGroup.js +1 -0
  4. package/lib/CompatibilityPlugin.js +31 -29
  5. package/lib/Compilation.js +50 -8
  6. package/lib/ConstPlugin.js +11 -11
  7. package/lib/ContextModule.js +239 -6
  8. package/lib/ContextModuleFactory.js +139 -14
  9. package/lib/DefinePlugin.js +396 -101
  10. package/lib/Entrypoint.js +1 -1
  11. package/lib/ExportsInfoApiPlugin.js +2 -2
  12. package/lib/ExternalModule.js +107 -5
  13. package/lib/ExternalModuleFactoryPlugin.js +20 -1
  14. package/lib/FileSystemInfo.js +130 -74
  15. package/lib/FlagDependencyExportsPlugin.js +55 -8
  16. package/lib/HotModuleReplacementPlugin.js +18 -15
  17. package/lib/LazyBarrel.js +30 -3
  18. package/lib/Module.js +3 -0
  19. package/lib/ModuleFilenameHelpers.js +2 -2
  20. package/lib/ModuleTypeConstants.js +8 -1
  21. package/lib/MultiCompiler.js +13 -2
  22. package/lib/MultiWatching.js +1 -0
  23. package/lib/NodeStuffPlugin.js +51 -33
  24. package/lib/NormalModule.js +169 -405
  25. package/lib/NormalModuleFactory.js +76 -2
  26. package/lib/ProgressPlugin.js +211 -119
  27. package/lib/ProvidePlugin.js +2 -2
  28. package/lib/RuntimeGlobals.js +47 -0
  29. package/lib/RuntimePlugin.js +33 -0
  30. package/lib/RuntimeTemplate.js +304 -16
  31. package/lib/UseStrictPlugin.js +1 -1
  32. package/lib/WebpackIsIncludedPlugin.js +1 -1
  33. package/lib/WebpackOptionsApply.js +24 -19
  34. package/lib/asset/AssetGenerator.js +110 -28
  35. package/lib/asset/AssetModulesPlugin.js +92 -2
  36. package/lib/asset/WebManifestGenerator.js +164 -0
  37. package/lib/asset/WebManifestParser.js +130 -0
  38. package/lib/async-modules/AwaitDependenciesInitFragment.js +14 -4
  39. package/lib/async-modules/isGeneratorLowered.js +26 -0
  40. package/lib/cache/PackFileCacheStrategy.js +9 -3
  41. package/lib/config/browserslistTargetHandler.js +40 -0
  42. package/lib/config/defaults.js +222 -32
  43. package/lib/config/normalization.js +26 -0
  44. package/lib/config/target.js +9 -1
  45. package/lib/css/CssGenerator.js +73 -73
  46. package/lib/css/CssLoadingRuntimeModule.js +5 -1
  47. package/lib/css/CssModulesPlugin.js +92 -53
  48. package/lib/css/CssParser.js +843 -302
  49. package/lib/css/syntax.js +1219 -483
  50. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -6
  51. package/lib/dependencies/AMDPlugin.js +2 -2
  52. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +13 -13
  53. package/lib/dependencies/CommonJsDependencyHelpers.js +39 -0
  54. package/lib/dependencies/CommonJsExportsDependency.js +47 -2
  55. package/lib/dependencies/CommonJsExportsParserPlugin.js +10 -10
  56. package/lib/dependencies/CommonJsImportsParserPlugin.js +18 -18
  57. package/lib/dependencies/CommonJsPlugin.js +2 -2
  58. package/lib/dependencies/CommonJsRequireDependency.js +26 -1
  59. package/lib/dependencies/CommonJsSelfReferenceDependency.js +32 -1
  60. package/lib/dependencies/ContextDependencyHelpers.js +3 -3
  61. package/lib/dependencies/CreateRequireParserPlugin.js +6 -6
  62. package/lib/dependencies/CssIcssExportDependency.js +190 -87
  63. package/lib/dependencies/CssUrlDependency.js +35 -4
  64. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +2 -2
  65. package/lib/dependencies/HarmonyCompatibilityDependency.js +32 -14
  66. package/lib/dependencies/HarmonyDetectionParserPlugin.js +43 -13
  67. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +7 -19
  68. package/lib/dependencies/HarmonyImportDependency.js +12 -1
  69. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +34 -107
  70. package/lib/dependencies/HarmonyImportGuard.js +192 -20
  71. package/lib/dependencies/HarmonyModulesPlugin.js +6 -0
  72. package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +1 -1
  73. package/lib/dependencies/HtmlEntryDependency.js +797 -172
  74. package/lib/dependencies/HtmlSourceDependency.js +26 -0
  75. package/lib/dependencies/ImportDependency.js +43 -1
  76. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +31 -18
  77. package/lib/dependencies/ImportMetaContextPlugin.js +38 -7
  78. package/lib/dependencies/ImportMetaGlobDependency.js +81 -0
  79. package/lib/dependencies/ImportMetaGlobDependencyParserPlugin.js +78 -0
  80. package/lib/dependencies/ImportMetaGlobHelpers.js +660 -0
  81. package/lib/dependencies/ImportMetaPlugin.js +532 -180
  82. package/lib/dependencies/ImportMetaResolveDependency.js +90 -0
  83. package/lib/dependencies/ImportParserPlugin.js +87 -26
  84. package/lib/dependencies/ImportPhase.js +10 -8
  85. package/lib/dependencies/LoaderPlugin.js +5 -1
  86. package/lib/dependencies/RequireContextDependencyParserPlugin.js +1 -1
  87. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +3 -6
  88. package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +4 -11
  89. package/lib/dependencies/SystemPlugin.js +2 -4
  90. package/lib/dependencies/TopLevelAwaitDependency.js +93 -0
  91. package/lib/dependencies/URLDependency.js +141 -21
  92. package/lib/dependencies/{WorkerPlugin.js → WorkerAndWorkletPlugin.js} +324 -112
  93. package/lib/dependencies/WorkerDependency.js +86 -18
  94. package/lib/dependencies/WorkletDependency.js +278 -0
  95. package/lib/dll/DelegatedModuleFactoryPlugin.js +19 -0
  96. package/lib/errors/EnvironmentNotSupportAsyncWarning.js +1 -1
  97. package/lib/errors/LoaderLoadingError.js +20 -0
  98. package/lib/errors/ModuleParseError.js +39 -22
  99. package/lib/errors/NodeStuffInWebError.js +1 -1
  100. package/lib/esm/ModuleChunkFormatPlugin.js +47 -14
  101. package/lib/esm/ModuleChunkLoadingPlugin.js +8 -1
  102. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +29 -1
  103. package/lib/hmr/lazyCompilationBackend.js +32 -8
  104. package/lib/html/HtmlGenerator.js +940 -91
  105. package/lib/html/HtmlModule.js +3 -2
  106. package/lib/html/HtmlModulesPlugin.js +625 -170
  107. package/lib/html/HtmlParser.js +812 -340
  108. package/lib/html/favicon.svg +1 -0
  109. package/lib/html/syntax.js +2116 -834
  110. package/lib/ids/IdHelpers.js +1 -1
  111. package/lib/index.js +6 -0
  112. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +4 -5
  113. package/lib/javascript/BasicEvaluatedExpression.js +366 -48
  114. package/lib/javascript/JavascriptGenerator.js +197 -49
  115. package/lib/javascript/JavascriptModulesPlugin.js +178 -24
  116. package/lib/javascript/JavascriptParser.js +711 -355
  117. package/lib/javascript/JavascriptParserHelpers.js +3 -6
  118. package/lib/javascript/syntax.js +4380 -0
  119. package/lib/library/ModuleLibraryPlugin.js +38 -1
  120. package/lib/loaders/LoaderRunner.js +714 -0
  121. package/lib/loaders/loadLoader.js +100 -0
  122. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +19 -0
  123. package/lib/node/ReadFileCompileWasmPlugin.js +14 -0
  124. package/lib/optimize/ConcatenatedModule.js +120 -16
  125. package/lib/optimize/FlagIncludedChunksPlugin.js +13 -3
  126. package/lib/optimize/InnerGraphPlugin.js +50 -30
  127. package/lib/optimize/ModuleConcatenationPlugin.js +69 -3
  128. package/lib/optimize/SideEffectsFlagPlugin.js +86 -43
  129. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +15 -0
  130. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +24 -13
  131. package/lib/prefetch/ResourceHintPlugin.js +663 -0
  132. package/lib/prefetch/ResourceHintRuntimeModule.js +149 -0
  133. package/lib/prefetch/StartupAssetHintRuntimeModule.js +210 -0
  134. package/lib/prefetch/parseResourceHintOptions.js +103 -0
  135. package/lib/rules/RuleSetCompiler.js +114 -0
  136. package/lib/runtime/AsyncModuleGeneratorRuntimeModule.js +56 -0
  137. package/lib/runtime/AsyncModuleRuntimeModule.js +24 -8
  138. package/lib/runtime/AutoPublicPathRuntimeModule.js +7 -1
  139. package/lib/runtime/CommonJsWrapRuntimeModule.js +37 -0
  140. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +59 -0
  141. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +204 -8
  142. package/lib/runtime/SetAnonymousDefaultNameRuntimeModule.js +4 -1
  143. package/lib/schemes/HttpUriPlugin.js +40 -1
  144. package/lib/schemes/VirtualUrlPlugin.js +1 -2
  145. package/lib/serialization/FileMiddleware.js +29 -3
  146. package/lib/stats/DefaultStatsFactoryPlugin.js +32 -3
  147. package/lib/stats/DefaultStatsPresetPlugin.js +2 -0
  148. package/lib/stats/DefaultStatsPrinterPlugin.js +12 -2
  149. package/lib/stats/StatsFactory.js +15 -8
  150. package/lib/url/URLParserPlugin.js +98 -19
  151. package/lib/util/AsyncQueue.js +122 -72
  152. package/lib/util/LocConverter.js +9 -8
  153. package/lib/util/SetHelpers.js +1 -1
  154. package/lib/util/SourceProcessor.js +41 -28
  155. package/lib/util/StackedMap.js +122 -48
  156. package/lib/util/binarySearchBounds.js +2 -2
  157. package/lib/util/concatenate.js +40 -14
  158. package/lib/util/createHooksRegistry.js +13 -5
  159. package/lib/util/dataURL.js +2 -2
  160. package/lib/util/deterministicGrouping.js +7 -5
  161. package/lib/util/formatSize.js +6 -2
  162. package/lib/util/globUtils.js +710 -0
  163. package/lib/util/identifier.js +23 -6
  164. package/lib/util/implicitTypeLoaderFallback.js +62 -0
  165. package/lib/util/internalSerializables.js +88 -71
  166. package/lib/util/magicComment.js +121 -25
  167. package/lib/util/numberHash.js +2 -2
  168. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +24 -18
  169. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +33 -22
  170. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +79 -16
  171. package/lib/web/FetchCompileAsyncWasmPlugin.js +19 -0
  172. package/lib/web/FetchCompileWasmPlugin.js +14 -0
  173. package/lib/web/JsonpChunkLoadingRuntimeModule.js +2 -0
  174. package/lib/webpack.js +65 -0
  175. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +3 -0
  176. package/module.d.ts +21 -0
  177. package/package.json +14 -13
  178. package/schemas/WebpackOptions.check.js +1 -1
  179. package/schemas/WebpackOptions.json +759 -36
  180. package/schemas/plugins/HtmlParserOptions.check.js +1 -1
  181. package/schemas/plugins/ProgressPlugin.check.js +1 -1
  182. package/schemas/plugins/ProgressPlugin.json +17 -1
  183. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  184. package/schemas/plugins/container/ContainerReferencePlugin.json +1 -0
  185. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  186. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  187. package/schemas/plugins/container/ModuleFederationPlugin.json +1 -0
  188. package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +1 -1
  189. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  190. package/schemas/plugins/css/CssParserOptions.check.js +1 -1
  191. package/types.d.ts +1300 -325
@@ -6,36 +6,41 @@
6
6
 
7
7
  /**
8
8
  * Babel-style visitor map keyed by a numeric node-type discriminator; a bucket
9
- * is a function (enter-only) or `{ enter?, exit? }`. `ctx.skipChildren()`
10
- * (enter only) stops the walker descending into the node's children.
11
- * @typedef {{ skipChildren(): void }} VisitorContext
12
- */
13
- /**
14
- * @template TNode
15
- * @typedef {(node: TNode, parent: TNode | null, ctx: VisitorContext) => void} VisitorFn
9
+ * is a function (enter-only) or `{ enter?, exit? }`.
10
+ *
11
+ * A visitor receives a single `path` argument (the Babel `path` shape): the
12
+ * language's AST accessor with the current position on it — `path.node`,
13
+ * `path.parent` (null at a root) — plus `path.skipChildren()` (enter only)
14
+ * to stop the walk descending, and every field-read method (which defaults
15
+ * to the current node). The path is one reused object rebound before each callback:
16
+ * it is only valid during the callback, and future per-node functionality
17
+ * lands on it without changing any visitor signature.
18
+ * @template TPath
19
+ * @typedef {(path: TPath) => void} VisitorFn
16
20
  */
17
21
  /**
18
- * @template TNode
19
- * @typedef {VisitorFn<TNode> | { enter?: VisitorFn<TNode>, exit?: VisitorFn<TNode> }} VisitorBucket
22
+ * @template TPath
23
+ * @typedef {VisitorFn<TPath> | { enter?: VisitorFn<TPath>, exit?: VisitorFn<TPath> }} VisitorBucket
20
24
  */
21
25
  /**
22
- * @template TNode
23
- * @typedef {{ [nodeType: number]: VisitorBucket<TNode> }} VisitorMap
26
+ * @template TPath
27
+ * @typedef {{ [nodeType: number]: VisitorBucket<TPath> }} VisitorMap
24
28
  */
25
29
  /**
26
- * @template TNode
27
- * @typedef {{ enter: VisitorFn<TNode>[], exit: VisitorFn<TNode>[] }} CompiledVisitorBucket
30
+ * @template TPath
31
+ * @typedef {{ enter: VisitorFn<TPath>[], exit: VisitorFn<TPath>[] }} CompiledVisitorBucket
28
32
  */
29
33
  /**
30
- * @template TNode
31
- * @typedef {CompiledVisitorBucket<TNode>[]} CompiledVisitorMap a sparse array indexed by node type
34
+ * @template TPath
35
+ * @typedef {CompiledVisitorBucket<TPath>[]} CompiledVisitorMap a sparse array indexed by node type
32
36
  */
33
37
  /**
34
38
  * A language grammar: parse `input` and fire the compiled visitors in source
35
- * order (the grammar owns tokenizing, parsing, and walking).
36
- * @template TNode
39
+ * order (the grammar owns tokenizing, parsing, walking — and the `path`
40
+ * object each visitor receives).
41
+ * @template TPath
37
42
  * @template TProcessOptions
38
- * @typedef {(input: string, visitors: CompiledVisitorMap<TNode>, options: TProcessOptions) => void} Grammar
43
+ * @typedef {(input: string, visitors: CompiledVisitorMap<TPath>, options: TProcessOptions) => void} Grammar
39
44
  */
40
45
 
41
46
  /**
@@ -44,28 +49,31 @@
44
49
  * binds its own grammar and node-type enum. Babel-style usage:
45
50
  *
46
51
  * ```
47
- * processor.use({ [NodeType.X]: (node) => {}, [NodeType.Y]: { enter, exit } });
52
+ * processor.use({ [NodeType.X]: (path) => {}, [NodeType.Y]: { enter, exit } });
48
53
  * processor.process(source);
49
54
  * ```
50
- * @template TNode
55
+ * @template TPath
51
56
  * @template [TProcessOptions=object]
52
57
  */
53
58
  class SourceProcessor {
54
59
  /**
55
- * @param {Grammar<TNode, TProcessOptions>} grammar the grammar to drive over the source
60
+ * @param {Grammar<TPath, TProcessOptions>} grammar the grammar to drive over the source
61
+ * @param {TProcessOptions=} options default process options (e.g. `skip`) merged under each `process` call's own options
56
62
  */
57
- constructor(grammar) {
58
- /** @type {Grammar<TNode, TProcessOptions>} */
63
+ constructor(grammar, options) {
64
+ /** @type {Grammar<TPath, TProcessOptions>} */
59
65
  this._grammar = grammar;
60
- /** @type {CompiledVisitorMap<TNode>} */
66
+ /** @type {CompiledVisitorMap<TPath>} */
61
67
  this._visitors = [];
68
+ /** @type {TProcessOptions | undefined} */
69
+ this._options = options;
62
70
  }
63
71
 
64
72
  /**
65
73
  * Register a Babel-style visitor map; calls accumulate per node type.
66
74
  * A bucket is a function (= `{ enter }`) or `{ enter?, exit? }`.
67
- * @param {VisitorMap<TNode>} map visitor map keyed by node type
68
- * @returns {SourceProcessor<TNode, TProcessOptions>} `this`, for chaining
75
+ * @param {VisitorMap<TPath>} map visitor map keyed by node type
76
+ * @returns {SourceProcessor<TPath, TProcessOptions>} `this`, for chaining
69
77
  */
70
78
  use(map) {
71
79
  // `map`'s keys are node-type enum members; `Object.keys` stringifies them,
@@ -90,15 +98,20 @@ class SourceProcessor {
90
98
 
91
99
  /**
92
100
  * Run the grammar over `input`, firing visitors in source order. No
93
- * AST retained.
101
+ * AST retained. Per-call `options` override the instance defaults.
94
102
  * @param {string} input source text
95
103
  * @param {TProcessOptions=} options grammar-specific options
96
104
  */
97
105
  process(input, options) {
106
+ const defaults = this._options;
98
107
  this._grammar(
99
108
  input,
100
109
  this._visitors,
101
- options || /** @type {TProcessOptions} */ ({})
110
+ defaults
111
+ ? options
112
+ ? { ...defaults, ...options }
113
+ : defaults
114
+ : options || /** @type {TProcessOptions} */ ({})
102
115
  );
103
116
  }
104
117
  }
@@ -41,21 +41,24 @@ const extractPair = (pair) => {
41
41
 
42
42
  /**
43
43
  * Layered map that supports child scopes while memoizing lookups from parent
44
- * scopes into the current layer.
44
+ * scopes. Layers form a linked parent chain, so `createChild` is O(1) instead
45
+ * of copying a layer array per scope. A layer's `Map` is only allocated on its
46
+ * first own write, and lookup results are memoized into the nearest
47
+ * `Map`-bearing layer of the walk — read-only layers (most block scopes) stay
48
+ * allocation-free and share their parent's memoized entries.
45
49
  * @template K
46
50
  * @template V
47
51
  */
48
52
  class StackedMap {
49
53
  /**
50
- * Creates a new map layer on top of an optional parent stack.
51
- * @param {Map<K, InternalCell<V>>[]=} parentStack an optional parent
54
+ * Creates a new map layer on top of an optional parent.
55
+ * @param {StackedMap<K, V>=} parent an optional parent map
52
56
  */
53
- constructor(parentStack) {
54
- /** @type {Map<K, InternalCell<V>>} */
55
- this.map = new Map();
56
- /** @type {Map<K, InternalCell<V>>[]} */
57
- this.stack = parentStack === undefined ? [] : [...parentStack];
58
- this.stack.push(this.map);
57
+ constructor(parent) {
58
+ /** @type {Map<K, InternalCell<V>> | undefined} */
59
+ this.map = undefined;
60
+ /** @type {StackedMap<K, V> | undefined} */
61
+ this.parent = parent;
59
62
  }
60
63
 
61
64
  /**
@@ -66,7 +69,10 @@ class StackedMap {
66
69
  * @returns {void}
67
70
  */
68
71
  set(item, value) {
69
- this.map.set(item, value === undefined ? UNDEFINED_MARKER : value);
72
+ (this.map || (this.map = new Map())).set(
73
+ item,
74
+ value === undefined ? UNDEFINED_MARKER : value
75
+ );
70
76
  }
71
77
 
72
78
  /**
@@ -76,80 +82,145 @@ class StackedMap {
76
82
  * @returns {void}
77
83
  */
78
84
  delete(item) {
79
- if (this.stack.length > 1) {
80
- this.map.set(item, TOMBSTONE);
81
- } else {
85
+ if (this.parent !== undefined) {
86
+ (this.map || (this.map = new Map())).set(item, TOMBSTONE);
87
+ } else if (this.map !== undefined) {
82
88
  this.map.delete(item);
83
89
  }
84
90
  }
85
91
 
86
92
  /**
87
93
  * Checks whether a key exists in the current scope chain, caching any parent
88
- * lookup result in the current layer.
94
+ * lookup result in the nearest `Map`-bearing layer.
89
95
  * @param {K} item the item to test
90
96
  * @returns {boolean} true if the item exists in this set
91
97
  */
92
98
  has(item) {
93
- const topValue = this.map.get(item);
94
- if (topValue !== undefined) {
95
- return topValue !== TOMBSTONE;
99
+ const own = this.map;
100
+ if (own !== undefined) {
101
+ const topValue = own.get(item);
102
+ if (topValue !== undefined) {
103
+ return topValue !== TOMBSTONE;
104
+ }
96
105
  }
97
- if (this.stack.length > 1) {
98
- for (let i = this.stack.length - 2; i >= 0; i--) {
99
- const value = this.stack[i].get(item);
106
+ /** @type {StackedMap<K, V> | undefined} */
107
+ let memoTarget = own !== undefined ? this : undefined;
108
+ /** @type {StackedMap<K, V> | undefined} */
109
+ let current = this.parent;
110
+ while (current !== undefined) {
111
+ const map = current.map;
112
+ if (map !== undefined) {
113
+ const value = map.get(item);
100
114
  if (value !== undefined) {
101
- this.map.set(item, value);
115
+ if (memoTarget !== undefined) {
116
+ /** @type {Map<K, InternalCell<V>>} */ (memoTarget.map).set(
117
+ item,
118
+ value
119
+ );
120
+ }
102
121
  return value !== TOMBSTONE;
103
122
  }
123
+ if (memoTarget === undefined) memoTarget = current;
104
124
  }
105
- this.map.set(item, TOMBSTONE);
125
+ current = current.parent;
126
+ }
127
+ if (memoTarget !== undefined) {
128
+ /** @type {Map<K, InternalCell<V>>} */ (memoTarget.map).set(
129
+ item,
130
+ TOMBSTONE
131
+ );
106
132
  }
107
133
  return false;
108
134
  }
109
135
 
110
136
  /**
111
137
  * Returns the visible value for a key, caching parent hits and misses in the
112
- * current layer.
138
+ * nearest `Map`-bearing layer so repeated lookups (from this layer or any
139
+ * sibling below that layer) answer with a single probe.
113
140
  * @param {K} item the key of the element to return
114
141
  * @returns {Cell<V>} the value of the element
115
142
  */
116
143
  get(item) {
117
- const topValue = this.map.get(item);
118
- if (topValue !== undefined) {
119
- return topValue === TOMBSTONE || topValue === UNDEFINED_MARKER
120
- ? undefined
121
- : topValue;
144
+ const own = this.map;
145
+ if (own !== undefined) {
146
+ const topValue = own.get(item);
147
+ if (topValue !== undefined) {
148
+ return topValue === TOMBSTONE || topValue === UNDEFINED_MARKER
149
+ ? undefined
150
+ : topValue;
151
+ }
122
152
  }
123
- if (this.stack.length > 1) {
124
- for (let i = this.stack.length - 2; i >= 0; i--) {
125
- const value = this.stack[i].get(item);
153
+ /** @type {StackedMap<K, V> | undefined} */
154
+ let memoTarget = own !== undefined ? this : undefined;
155
+ /** @type {StackedMap<K, V> | undefined} */
156
+ let current = this.parent;
157
+ while (current !== undefined) {
158
+ const map = current.map;
159
+ if (map !== undefined) {
160
+ const value = map.get(item);
126
161
  if (value !== undefined) {
127
- this.map.set(item, value);
162
+ if (memoTarget !== undefined) {
163
+ /** @type {Map<K, InternalCell<V>>} */ (memoTarget.map).set(
164
+ item,
165
+ value
166
+ );
167
+ }
128
168
  return value === TOMBSTONE || value === UNDEFINED_MARKER
129
169
  ? undefined
130
170
  : value;
131
171
  }
172
+ if (memoTarget === undefined) memoTarget = current;
132
173
  }
133
- this.map.set(item, TOMBSTONE);
174
+ current = current.parent;
175
+ }
176
+ if (memoTarget !== undefined) {
177
+ /** @type {Map<K, InternalCell<V>>} */ (memoTarget.map).set(
178
+ item,
179
+ TOMBSTONE
180
+ );
134
181
  }
135
182
  }
136
183
 
137
184
  /**
138
- * Collapses the stacked layers into a single concrete map.
185
+ * Collapses the parent chain into a single concrete map.
139
186
  */
140
187
  _compress() {
141
- if (this.stack.length === 1) return;
142
- this.map = new Map();
143
- for (const data of this.stack) {
144
- for (const pair of data) {
145
- if (pair[1] === TOMBSTONE) {
146
- this.map.delete(pair[0]);
147
- } else {
148
- this.map.set(pair[0], pair[1]);
188
+ if (this.parent === undefined) {
189
+ const map = this.map;
190
+ if (map === undefined) {
191
+ this.map = new Map();
192
+ return;
193
+ }
194
+ // a parent-less layer holds tombstones only as memoized misses
195
+ // (deletes remove outright) — drop them from the visible view
196
+ for (const pair of map) {
197
+ if (pair[1] === TOMBSTONE) map.delete(pair[0]);
198
+ }
199
+ return;
200
+ }
201
+ /** @type {StackedMap<K, V>[]} */
202
+ const layers = [];
203
+ /** @type {StackedMap<K, V> | undefined} */
204
+ let current = this;
205
+ do {
206
+ layers.push(current);
207
+ current = current.parent;
208
+ } while (current !== undefined);
209
+ const map = new Map();
210
+ for (let i = layers.length - 1; i >= 0; i--) {
211
+ const layerMap = layers[i].map;
212
+ if (layerMap !== undefined) {
213
+ for (const pair of layerMap) {
214
+ if (pair[1] === TOMBSTONE) {
215
+ map.delete(pair[0]);
216
+ } else {
217
+ map.set(pair[0], pair[1]);
218
+ }
149
219
  }
150
220
  }
151
221
  }
152
- this.stack = [this.map];
222
+ this.map = map;
223
+ this.parent = undefined;
153
224
  }
154
225
 
155
226
  /**
@@ -158,7 +229,7 @@ class StackedMap {
158
229
  */
159
230
  asArray() {
160
231
  this._compress();
161
- return [...this.map.keys()];
232
+ return [.../** @type {Map<K, InternalCell<V>>} */ (this.map).keys()];
162
233
  }
163
234
 
164
235
  /**
@@ -167,7 +238,7 @@ class StackedMap {
167
238
  */
168
239
  asSet() {
169
240
  this._compress();
170
- return new Set(this.map.keys());
241
+ return new Set(/** @type {Map<K, InternalCell<V>>} */ (this.map).keys());
171
242
  }
172
243
 
173
244
  /**
@@ -176,7 +247,10 @@ class StackedMap {
176
247
  */
177
248
  asPairArray() {
178
249
  this._compress();
179
- return Array.from(this.map.entries(), extractPair);
250
+ return Array.from(
251
+ /** @type {Map<K, InternalCell<V>>} */ (this.map).entries(),
252
+ extractPair
253
+ );
180
254
  }
181
255
 
182
256
  /**
@@ -193,7 +267,7 @@ class StackedMap {
193
267
  */
194
268
  get size() {
195
269
  this._compress();
196
- return this.map.size;
270
+ return /** @type {Map<K, InternalCell<V>>} */ (this.map).size;
197
271
  }
198
272
 
199
273
  /**
@@ -202,7 +276,7 @@ class StackedMap {
202
276
  * @returns {StackedMap<K, V>} child map
203
277
  */
204
278
  createChild() {
205
- return new StackedMap(this.stack);
279
+ return new StackedMap(this);
206
280
  }
207
281
  }
208
282
 
@@ -128,9 +128,9 @@ const fns = {
128
128
  * const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
129
129
  *
130
130
  * // Find the index of the first element greater than 5
131
- * const index1 = gt(arr, 5); // index1 === 3
131
+ * const index1 = gt(arr, 5); // index1 === 5
132
132
  *
133
- * // Find the index of the first element less than or equal to 5
133
+ * // Find the index of the last element less than or equal to 5
134
134
  * const index2 = le(arr, 5); // index2 === 4
135
135
  * ```
136
136
  */
@@ -25,11 +25,14 @@ const NAMESPACE_OBJECT_EXPORT = "__WEBPACK_NAMESPACE_OBJECT__";
25
25
  const getAllReferences = (variable) => {
26
26
  let set = variable.references;
27
27
  // Look for inner scope variables too (like in class Foo { t() { Foo } })
28
- const identifiers = new Set(variable.identifiers);
28
+ // identifiers is tiny (usually 1 declaration) — indexOf beats a Set here
29
+ const identifiers = variable.identifiers;
29
30
  for (const scope of variable.scope.childScopes) {
30
31
  for (const innerVar of scope.variables) {
31
- if (innerVar.identifiers.some((id) => identifiers.has(id))) {
32
- set = [...set, ...innerVar.references];
32
+ if (innerVar.identifiers.some((id) => identifiers.includes(id))) {
33
+ // copy-on-write to keep the common no-match case allocation-free
34
+ if (set === variable.references) set = [...set];
35
+ for (const ref of innerVar.references) set.push(ref);
33
36
  break;
34
37
  }
35
38
  }
@@ -113,6 +116,32 @@ const getPathInAst = (ast, node) => {
113
116
  }
114
117
  };
115
118
 
119
+ /** @type {Map<string, string[]>} */
120
+ const splittedInfoCache = new Map();
121
+
122
+ /**
123
+ * Returns path segments of the cleaned extra info.
124
+ * @param {string} extraInfo extra info
125
+ * @returns {string[]} cleaned path segments
126
+ */
127
+ const getSplittedInfo = (extraInfo) => {
128
+ let splittedInfo = splittedInfoCache.get(extraInfo);
129
+ if (splittedInfo === undefined) {
130
+ // bound the cache — extraInfo repeats for every renamed binding of a
131
+ // module, but distinct values grow with project size
132
+ if (splittedInfoCache.size >= 4096) splittedInfoCache.clear();
133
+ // Remove uncool stuff
134
+ splittedInfo = extraInfo
135
+ .replace(
136
+ /\.+\/|(?:\/index)?\.[a-zA-Z0-9]{1,4}(?:$|\s|\?)|\s*\+\s*\d+\s*modules/g,
137
+ ""
138
+ )
139
+ .split("/");
140
+ splittedInfoCache.set(extraInfo, splittedInfo);
141
+ }
142
+ return splittedInfo;
143
+ };
144
+
116
145
  /**
117
146
  * Returns found new name.
118
147
  * @param {string} oldName old name
@@ -131,15 +160,9 @@ function findNewName(oldName, usedNamed1, usedNamed2, extraInfo) {
131
160
  name = "namespaceObject";
132
161
  }
133
162
 
134
- // Remove uncool stuff
135
- extraInfo = extraInfo.replace(
136
- /\.+\/|(?:\/index)?\.[a-zA-Z0-9]{1,4}(?:$|\s|\?)|\s*\+\s*\d+\s*modules/g,
137
- ""
138
- );
139
-
140
- const splittedInfo = extraInfo.split("/");
141
- while (splittedInfo.length) {
142
- name = splittedInfo.pop() + (name ? `_${name}` : "");
163
+ const splittedInfo = getSplittedInfo(extraInfo);
164
+ for (let i = splittedInfo.length - 1; i >= 0; i--) {
165
+ name = splittedInfo[i] + (name ? `_${name}` : "");
143
166
  const nameIdent = Template.toIdentifier(name);
144
167
  if (
145
168
  !usedNamed1.has(nameIdent) &&
@@ -149,15 +172,18 @@ function findNewName(oldName, usedNamed1, usedNamed2, extraInfo) {
149
172
  }
150
173
  }
151
174
 
175
+ // `_${i}` is identifier-safe, so escaping the base once is equivalent to
176
+ // escaping every candidate — avoids two regexes per collision
177
+ const nameIdent = Template.toIdentifier(name);
152
178
  let i = 0;
153
- let nameWithNumber = Template.toIdentifier(`${name}_${i}`);
179
+ let nameWithNumber = `${nameIdent}_${i}`;
154
180
  while (
155
181
  usedNamed1.has(nameWithNumber) ||
156
182
  // eslint-disable-next-line no-unmodified-loop-condition
157
183
  (usedNamed2 && usedNamed2.has(nameWithNumber))
158
184
  ) {
159
185
  i++;
160
- nameWithNumber = Template.toIdentifier(`${name}_${i}`);
186
+ nameWithNumber = `${nameIdent}_${i}`;
161
187
  }
162
188
  return nameWithNumber;
163
189
  }
@@ -17,11 +17,19 @@ const createHooksRegistry = (createHooks) => {
17
17
  /** @type {WeakMap<import("../Compilation"), T>} */
18
18
  const map = new WeakMap();
19
19
  return (compilation) => {
20
- const Compilation = getCompilation();
21
- if (!(compilation instanceof Compilation)) {
22
- throw new TypeError(
23
- "The 'compilation' argument must be an instance of Compilation"
24
- );
20
+ if (!(compilation instanceof getCompilation())) {
21
+ // a compilation from another webpack copy fails instanceof — match the class name
22
+ const candidate =
23
+ /** @type {{ constructor?: { name: string } } | null} */ (compilation);
24
+ if (
25
+ !candidate ||
26
+ !candidate.constructor ||
27
+ candidate.constructor.name !== "Compilation"
28
+ ) {
29
+ throw new TypeError(
30
+ "The 'compilation' argument must be an instance of Compilation"
31
+ );
32
+ }
25
33
  }
26
34
  let hooks = map.get(compilation);
27
35
  if (hooks === undefined) {
@@ -28,9 +28,9 @@ const decodeDataURI = (uri) => {
28
28
  // CSS allows to use `data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" style="stroke: rgb(223,224,225); stroke-width: 2px; fill: none; stroke-dasharray: 6px 3px" /></svg>`
29
29
  // so we return original body if we can't `decodeURIComponent`
30
30
  try {
31
- return Buffer.from(decodeURIComponent(body), "ascii");
31
+ return Buffer.from(decodeURIComponent(body), "utf8");
32
32
  } catch (_) {
33
- return Buffer.from(body, "ascii");
33
+ return Buffer.from(body, "utf8");
34
34
  }
35
35
  };
36
36
 
@@ -168,15 +168,14 @@ const getTooSmallTypes = (size, minSize) => {
168
168
 
169
169
  /**
170
170
  * Gets number of matching size types.
171
- * @template {object} T
172
- * @param {T} size size
171
+ * @param {Sizes} size size
173
172
  * @param {Types} types types
174
173
  * @returns {number} number of matching size types
175
174
  */
176
175
  const getNumberOfMatchingSizeTypes = (size, types) => {
177
176
  let i = 0;
178
177
  for (const key in size) {
179
- if (size[/** @type {keyof T} */ (key)] !== 0 && types.has(key)) i++;
178
+ if (size[key] !== 0 && types.has(key)) i++;
180
179
  }
181
180
  return i;
182
181
  };
@@ -378,9 +377,12 @@ module.exports = ({ maxSize, minSize, items, getSize, getKey }) => {
378
377
  );
379
378
  if (possibleResultGroups.length > 0) {
380
379
  const bestGroup = possibleResultGroups.reduce((min, group) => {
381
- const minMatches = getNumberOfMatchingSizeTypes(min, problemTypes);
380
+ const minMatches = getNumberOfMatchingSizeTypes(
381
+ min.size,
382
+ problemTypes
383
+ );
382
384
  const groupMatches = getNumberOfMatchingSizeTypes(
383
- group,
385
+ group.size,
384
386
  problemTypes
385
387
  );
386
388
  if (minMatches !== groupMatches) {
@@ -19,8 +19,12 @@ const formatSize = (size) => {
19
19
  return "0 bytes";
20
20
  }
21
21
 
22
- const abbreviations = ["bytes", "KiB", "MiB", "GiB"];
23
- const index = Math.floor(Math.log(size) / Math.log(1024));
22
+ const abbreviations = ["bytes", "KiB", "MiB", "GiB", "TiB", "PiB"];
23
+ // clamp so sizes beyond the largest unit don't index past the table
24
+ const index = Math.min(
25
+ Math.floor(Math.log(size) / Math.log(1024)),
26
+ abbreviations.length - 1
27
+ );
24
28
 
25
29
  return `${Number((size / 1024 ** index).toPrecision(3))} ${abbreviations[index]}`;
26
30
  };