webpack 5.110.2 → 5.111.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 (226) hide show
  1. package/README.md +5 -2
  2. package/lib/APIPlugin.js +23 -7
  3. package/lib/AutomaticPrefetchPlugin.js +1 -1
  4. package/lib/Cache.js +8 -3
  5. package/lib/CacheFacade.js +1 -1
  6. package/lib/ChunkGraph.js +20 -18
  7. package/lib/CircularModulesPlugin.js +157 -55
  8. package/lib/CleanPlugin.js +2 -2
  9. package/lib/Compilation.js +321 -303
  10. package/lib/Compiler.js +209 -46
  11. package/lib/ConcatenationScope.js +25 -35
  12. package/lib/ContextModule.js +17 -81
  13. package/lib/ContextModuleFactory.js +1 -1
  14. package/lib/CopyPlugin.js +1054 -0
  15. package/lib/DefinePlugin.js +24 -8
  16. package/lib/DotenvPlugin.js +41 -13
  17. package/lib/ExternalModule.js +41 -14
  18. package/lib/FileSystemInfo.js +17 -14
  19. package/lib/FlagDependencyExportsPlugin.js +45 -21
  20. package/lib/FlagDependencyUsagePlugin.js +8 -2
  21. package/lib/HotModuleReplacementPlugin.js +53 -7
  22. package/lib/JavascriptMetaInfoPlugin.js +5 -3
  23. package/lib/MainTemplate.js +5 -1
  24. package/lib/Module.js +16 -7
  25. package/lib/MultiCompiler.js +1 -1
  26. package/lib/MultiWatching.js +1 -1
  27. package/lib/NormalModule.js +58 -32
  28. package/lib/NormalModuleFactory.js +1 -1
  29. package/lib/RuntimeGlobals.js +21 -7
  30. package/lib/RuntimeModule.js +28 -12
  31. package/lib/RuntimePlugin.js +33 -3
  32. package/lib/RuntimeTemplate.js +794 -477
  33. package/lib/SourceMapDevToolPlugin.js +1 -1
  34. package/lib/Watching.js +9 -0
  35. package/lib/WebpackOptionsApply.js +84 -91
  36. package/lib/asset/AssetGenerator.js +25 -8
  37. package/lib/asset/AssetModule.js +3 -0
  38. package/lib/asset/WebManifestParser.js +7 -5
  39. package/lib/async-modules/AsyncModuleHelpers.js +10 -4
  40. package/lib/cache/AddBuildDependenciesPlugin.js +33 -4
  41. package/lib/cache/IdleFileCachePlugin.js +2 -2
  42. package/lib/cache/PackFileCacheStrategy.js +14 -1
  43. package/lib/config/browserslistTargetHandler.js +19 -0
  44. package/lib/config/defaults.js +110 -64
  45. package/lib/config/normalization.js +100 -20
  46. package/lib/config/target.js +10 -0
  47. package/lib/container/ContainerReferencePlugin.js +6 -0
  48. package/lib/container/RemoteRuntimeModule.js +9 -0
  49. package/lib/container/declaredRemotes.js +39 -0
  50. package/lib/css/CssGenerator.js +8 -0
  51. package/lib/css/CssInjectStyleRuntimeModule.js +9 -0
  52. package/lib/css/CssLoadingRuntimeModule.js +94 -36
  53. package/lib/css/CssModule.js +1 -1
  54. package/lib/css/CssModulesPlugin.js +7 -6
  55. package/lib/css/CssParser.js +144 -11
  56. package/lib/css/CssServerStylesRuntimeModule.js +9 -0
  57. package/lib/css/cssMinify.js +11 -3
  58. package/lib/css/data.js +2814 -678
  59. package/lib/css/syntax.js +4082 -248
  60. package/lib/debug/ProfilingPlugin.js +4 -0
  61. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -3
  62. package/lib/dependencies/AMDRuntimeModules.js +18 -0
  63. package/lib/dependencies/CommonJsExportRequireDependency.js +3 -1
  64. package/lib/dependencies/CommonJsExportsParserPlugin.js +12 -13
  65. package/lib/dependencies/CommonJsImportsParserPlugin.js +1 -0
  66. package/lib/dependencies/CommonJsPlugin.js +19 -3
  67. package/lib/dependencies/CommonJsRequireDependency.js +32 -9
  68. package/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +20 -7
  69. package/lib/dependencies/CssIcssExportDependency.js +7 -1
  70. package/lib/dependencies/HarmonyCompatibilityDependency.js +58 -4
  71. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +8 -3
  72. package/lib/dependencies/HarmonyExportExpressionDependency.js +44 -29
  73. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +171 -32
  74. package/lib/dependencies/HarmonyExportInitFragment.js +99 -19
  75. package/lib/dependencies/HarmonyExportSpecifierDependency.js +18 -30
  76. package/lib/dependencies/HarmonyImportBareSideEffectDependency.js +59 -0
  77. package/lib/dependencies/HarmonyImportDependency.js +99 -41
  78. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +20 -3
  79. package/lib/dependencies/HarmonyImportSpecifierDependency.js +24 -1
  80. package/lib/dependencies/HarmonyModulesPlugin.js +20 -0
  81. package/lib/dependencies/HtmlEntryDependency.js +62 -2
  82. package/lib/dependencies/ImportContextDependency.js +43 -3
  83. package/lib/dependencies/ImportDependency.js +8 -29
  84. package/lib/dependencies/ImportMetaMainDependency.js +104 -0
  85. package/lib/dependencies/ImportMetaPlugin.js +59 -15
  86. package/lib/dependencies/ImportParserPlugin.js +24 -14
  87. package/lib/dependencies/RequireHeaderDependency.js +20 -21
  88. package/lib/dependencies/SystemRuntimeModule.js +9 -0
  89. package/lib/dependencies/WorkerDependency.js +1 -2
  90. package/lib/dependencies/WorkletDependency.js +1 -2
  91. package/lib/dependencies/importOptionsCheck.js +47 -0
  92. package/lib/dll/DelegatedModule.js +18 -1
  93. package/lib/dll/DllReferencePlugin.js +11 -8
  94. package/lib/dll/LibManifestPlugin.js +1 -1
  95. package/lib/errors/AnalyzableBailoutsWarning.js +41 -0
  96. package/lib/errors/DotenvFileError.js +29 -0
  97. package/lib/errors/DuplicateModulesWarning.js +12 -7
  98. package/lib/errors/EmptyCopyPatternWarning.js +26 -0
  99. package/lib/errors/ExternalStarReexportError.js +44 -0
  100. package/lib/errors/ImportedBindingAssignmentError.js +30 -0
  101. package/lib/errors/MissingSourceMapsWarning.js +36 -0
  102. package/lib/errors/ModuleParseError.js +2 -1
  103. package/lib/errors/UnusedAssetsWarning.js +36 -0
  104. package/lib/errors/UnusedFederationWarning.js +35 -0
  105. package/lib/errors/UnusedModulesWarning.js +38 -0
  106. package/lib/esm/ExportWebpackRequireRuntimeModule.js +9 -0
  107. package/lib/esm/ModuleChunkFormatPlugin.js +28 -3
  108. package/lib/esm/ModuleChunkLoadingPlugin.js +30 -11
  109. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +92 -60
  110. package/lib/hmr/HotModuleReplacement.runtime.js +8 -2
  111. package/lib/hmr/HotModuleReplacementRuntimeModule.js +9 -0
  112. package/lib/html/HtmlGenerator.js +11 -5
  113. package/lib/html/HtmlModulesPlugin.js +360 -84
  114. package/lib/html/HtmlParser.js +13 -6
  115. package/lib/html/builtinEmbeddedRenderer.js +107 -0
  116. package/lib/html/data.js +121 -7
  117. package/lib/html/htmlMinify.js +84 -113
  118. package/lib/html/syntax.js +1067 -569
  119. package/lib/ids/HashedModuleIdsPlugin.js +2 -1
  120. package/lib/index.js +3 -0
  121. package/lib/javascript/JavascriptModule.js +1 -0
  122. package/lib/javascript/JavascriptModulesPlugin.js +52 -22
  123. package/lib/javascript/JavascriptParser.js +1255 -728
  124. package/lib/javascript/StartupHelpers.js +27 -3
  125. package/lib/javascript/data.js +172 -0
  126. package/lib/javascript/grammar.js +5546 -0
  127. package/lib/javascript/parser.js +1494 -0
  128. package/lib/javascript/regexp.js +1762 -0
  129. package/lib/javascript/regexpData.js +51 -0
  130. package/lib/javascript/syntax.js +8696 -5225
  131. package/lib/library/ModuleLibraryPlugin.js +116 -5
  132. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +22 -0
  133. package/lib/node/RequireChunkLoadingRuntimeModule.js +22 -0
  134. package/lib/optimize/ConcatenatedModule.js +133 -25
  135. package/lib/optimize/ConstExportsPlugin.js +50 -39
  136. package/lib/optimize/InlineExports.js +20 -123
  137. package/lib/optimize/MangleExportsPlugin.js +10 -0
  138. package/lib/optimize/ModuleConcatenationPlugin.js +24 -1
  139. package/lib/optimize/RealContentHashPlugin.js +68 -9
  140. package/lib/optimize/SideEffectsFlagPlugin.js +17 -9
  141. package/lib/performance/AnalyzableBailoutsPlugin.js +115 -0
  142. package/lib/performance/CacheEffectivenessPlugin.js +4 -3
  143. package/lib/performance/DuplicateModulesPlugin.js +57 -13
  144. package/lib/performance/EvalUsagePlugin.js +5 -2
  145. package/lib/performance/MissingSourceMapsPlugin.js +115 -0
  146. package/lib/performance/PureAnnotationsPlugin.js +6 -3
  147. package/lib/performance/TopLevelThisPlugin.js +5 -4
  148. package/lib/performance/UnusedAssetsPlugin.js +109 -0
  149. package/lib/performance/UnusedFederationPlugin.js +147 -0
  150. package/lib/performance/UnusedModulesPlugin.js +141 -0
  151. package/lib/performance/UnusedReexportsPlugin.js +1 -55
  152. package/lib/performance/isOnlyReexported.js +65 -0
  153. package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +25 -5
  154. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +2 -0
  155. package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +9 -0
  156. package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +9 -0
  157. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +9 -0
  158. package/lib/prefetch/ResourceHintPlugin.js +7 -3
  159. package/lib/prefetch/ResourceHintRuntimeModule.js +9 -0
  160. package/lib/prefetch/StartupAssetHintRuntimeModule.js +9 -0
  161. package/lib/rules/RuleSetCompiler.js +211 -4
  162. package/lib/runtime/AsyncModuleRuntimeModule.js +105 -67
  163. package/lib/runtime/AutoPublicPathRuntimeModule.js +9 -0
  164. package/lib/runtime/BaseUriRuntimeModule.js +9 -0
  165. package/lib/runtime/ChunkNameRuntimeModule.js +9 -0
  166. package/lib/runtime/EnsureChunkRuntimeModule.js +35 -16
  167. package/lib/runtime/GetChunkFilenameRuntimeModule.js +9 -0
  168. package/lib/runtime/GetFullHashRuntimeModule.js +9 -0
  169. package/lib/runtime/GetMainFilenameRuntimeModule.js +9 -0
  170. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +9 -0
  171. package/lib/runtime/GlobalRuntimeModule.js +9 -0
  172. package/lib/runtime/HasOwnPropertyRuntimeModule.js +9 -0
  173. package/lib/runtime/HelperRuntimeModule.js +10 -0
  174. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +338 -217
  175. package/lib/runtime/NonceRuntimeModule.js +9 -0
  176. package/lib/runtime/OnChunksLoadedRuntimeModule.js +67 -20
  177. package/lib/runtime/PublicPathRuntimeModule.js +9 -0
  178. package/lib/runtime/RuntimeIdRuntimeModule.js +9 -0
  179. package/lib/runtime/SpecNamespaceObjectRuntimeModule.js +90 -0
  180. package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +9 -0
  181. package/lib/runtime/StartupEntrypointRuntimeModule.js +9 -0
  182. package/lib/runtime/SystemContextRuntimeModule.js +9 -0
  183. package/lib/runtime/ToBinaryRuntimeModule.js +9 -0
  184. package/lib/schemes/HttpUriPlugin.js +22 -5
  185. package/lib/serialization/FileMiddleware.js +15 -2
  186. package/lib/serialization/ObjectMiddleware.js +138 -106
  187. package/lib/sharing/ConsumeSharedPlugin.js +12 -0
  188. package/lib/sharing/ConsumeSharedRuntimeModule.js +11 -0
  189. package/lib/sharing/ShareRuntimeModule.js +9 -0
  190. package/lib/sharing/declaredShared.js +47 -0
  191. package/lib/stats/DefaultStatsFactoryPlugin.js +3 -1
  192. package/lib/stats/DefaultStatsPrinterPlugin.js +3 -0
  193. package/lib/util/ArrayQueue.js +3 -3
  194. package/lib/util/SourceProcessor.js +76 -69
  195. package/lib/util/URLAbsoluteSpecifier.js +3 -1
  196. package/lib/util/async.js +292 -0
  197. package/lib/util/buildDiagnostics.js +69 -0
  198. package/lib/util/conventions.js +5 -1
  199. package/lib/util/fs.js +27 -1
  200. package/lib/util/handlerKeys.js +40 -0
  201. package/lib/util/identifier.js +20 -0
  202. package/lib/util/internalSerializables.js +6 -0
  203. package/lib/util/registerExternalSerializer.js +6 -45
  204. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +9 -0
  205. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +9 -0
  206. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +9 -0
  207. package/lib/web/JsonpChunkLoadingRuntimeModule.js +36 -0
  208. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +19 -0
  209. package/package.json +22 -16
  210. package/schemas/WebpackOptions.check.js +1 -1
  211. package/schemas/WebpackOptions.json +388 -76
  212. package/schemas/plugins/LoaderOptionsPlugin.check.js +1 -1
  213. package/schemas/plugins/ManifestPlugin.check.js +1 -1
  214. package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
  215. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
  216. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
  217. package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
  218. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  219. package/schemas/plugins/debug/ProfilingPlugin.check.js +1 -1
  220. package/schemas/plugins/dll/DllReferencePlugin.check.js +1 -1
  221. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +1 -1
  222. package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
  223. package/types.d.ts +1440 -331
  224. package/lib/dependencies/ExportBindingInitFragment.js +0 -191
  225. package/lib/errors/EntrypointOverlapWarning.js +0 -45
  226. package/lib/performance/EntrypointOverlapPlugin.js +0 -122
@@ -261,14 +261,17 @@ class PrintContext {
261
261
  /** @type {NodePrinter<TPath, TNode, TPrintOptions>} */
262
262
  this._printer = printer;
263
263
  // Printed text by node handle, in two columns rather than one `Map`: the
264
- // handles are dense integers, and a stylesheet prints ~300k nodes through
265
- // a store that never holds more than a few dozen of them at once.
264
+ // handles are dense integers, and `_moveEpoch` keeps the live set small.
266
265
  /** @type {string[]} each finished node's printed text */
267
266
  this._storeText = [];
268
267
  /** @type {Int32Array} the epoch each slot was written in */
269
268
  this._storeGen = new Int32Array(0);
270
269
  /** @type {number} current epoch; a slot from an older one reads as absent */
271
270
  this._gen = 1;
271
+ /** @type {number} lowest slot written since the epoch last moved */
272
+ this._storeLow = 0x7fffffff;
273
+ /** @type {number} highest slot written since the epoch last moved */
274
+ this._storeHigh = -1;
272
275
  // Output accumulates into `_tail`, a plain string append, so printing that
273
276
  // never takes anything back costs exactly what appending to one string
274
277
  // costs. A piece is cut off into `_chunks` only for text that may still be
@@ -285,7 +288,7 @@ class PrintContext {
285
288
  this._flattened = 0;
286
289
  /** @type {[number, number, number, number][]} `[chunkIndex, offsetInChunk, srcLine, srcCol]`, output-ordered; a `srcLine` of -1 is one {@link retract} took back with its piece */
287
290
  this._mappings = [];
288
- /** @type {Map<number, number> | null} a retractable piece -> the mapping anchored to it, so taking the piece back takes its mapping too */
291
+ /** @type {number[] | null} by retractable piece index, the mapping anchored to it, so taking the piece back takes its mapping too */
289
292
  this._retractableMappings = null;
290
293
  // A map is built only for a caller that named the input, and that is known
291
294
  // before printing — so a print nobody asks a map of collects none.
@@ -424,8 +427,25 @@ class PrintContext {
424
427
  * node's text.
425
428
  */
426
429
  dropStore() {
427
- // Bumping the epoch invalidates every slot at once, so this stays O(1) —
428
- // it runs per node, and clearing a column by length would not.
430
+ this._moveEpoch();
431
+ }
432
+
433
+ /**
434
+ * Move the epoch on and release the text every slot written under the old one
435
+ * holds. Only the range actually written is walked, so the drop stays O(1)
436
+ * per node.
437
+ * @returns {void}
438
+ */
439
+ _moveEpoch() {
440
+ const high = this._storeHigh;
441
+ if (high !== -1) {
442
+ // `""` rather than a hole: the column is packed, and a hole in it would
443
+ // cost every read after this one.
444
+ const text = this._storeText;
445
+ for (let i = this._storeLow; i <= high; i++) text[i] = "";
446
+ this._storeLow = 0x7fffffff;
447
+ this._storeHigh = -1;
448
+ }
429
449
  this._gen++;
430
450
  }
431
451
 
@@ -469,6 +489,8 @@ class PrintContext {
469
489
  if (n >= this._storeText.length) this._growStore(n + 1);
470
490
  this._storeText[n] = text;
471
491
  this._storeGen[n] = this._gen;
492
+ if (n < this._storeLow) this._storeLow = n;
493
+ if (n > this._storeHigh) this._storeHigh = n;
472
494
  }
473
495
 
474
496
  /**
@@ -552,7 +574,7 @@ class PrintContext {
552
574
  retract(index) {
553
575
  this._chunks[index] = "";
554
576
  if (this._retractableMappings === null) return;
555
- const mapping = this._retractableMappings.get(index);
577
+ const mapping = this._retractableMappings[index];
556
578
  if (mapping !== undefined) this._mappings[mapping][2] = -1;
557
579
  }
558
580
 
@@ -598,12 +620,12 @@ class PrintContext {
598
620
  this.anchor(srcOffset, srcLine, srcCol);
599
621
  const mapping = this._mappings.length > before ? before : -1;
600
622
  const at = this.emitRetractable(text === undefined ? this.get(node) : text);
601
- this._gen++;
623
+ this._moveEpoch();
602
624
  if (mapping !== -1) {
603
- if (this._retractableMappings === null) {
604
- this._retractableMappings = new Map();
605
- }
606
- this._retractableMappings.set(at, mapping);
625
+ // Indexed by piece rather than a `Map`: pieces are dense integers, and
626
+ // nearly every rule minifying goes out as one.
627
+ if (this._retractableMappings === null) this._retractableMappings = [];
628
+ this._retractableMappings[at] = mapping;
607
629
  }
608
630
  return at;
609
631
  }
@@ -627,7 +649,7 @@ class PrintContext {
627
649
  this._emit(
628
650
  text === undefined ? this.get(/** @type {TNode} */ (node)) : text
629
651
  );
630
- this._gen++;
652
+ this._moveEpoch();
631
653
  }
632
654
 
633
655
  /**
@@ -739,68 +761,44 @@ class PrintContext {
739
761
 
740
762
  /**
741
763
  * @param {SourceMapOptions} options the input's name / content
764
+ * @param {string=} code the output {@link result} built, walked for its line breaks
742
765
  * @returns {SourceMap} the input->output source map
743
766
  */
744
- sourceMap(options) {
767
+ sourceMap(options, code) {
745
768
  let out = "";
746
769
  let genLine = 0;
747
770
  let genCol = 0;
748
771
  let srcLine = 0;
749
772
  let srcCol = 0;
750
773
  let atLineStart = true;
751
- // Where each anchor landed, walked once alongside the mappings — both are
752
- // in output order, so this is one pass over the output, not a position
753
- // recomputed per mapping. An anchor can sit inside a piece rather than at
754
- // its start, since output accumulates into the piece it is appending to.
774
+ // Walked over the flat output rather than piece by piece: a piece is a rope
775
+ // until something reads it, and reading each one flattens each one.
776
+ const text = code === undefined ? this.result() : code;
755
777
  const chunks = this._chunks;
756
- const tail = this._tail;
757
- /**
758
- * @param {number} i piece index, `chunks.length` being the tail
759
- * @returns {string} that piece
760
- */
761
- const pieceAt = (i) => (i === chunks.length ? tail : chunks[i]);
762
778
  let atChunk = 0;
779
+ let chunkStart = 0;
763
780
  let atOffset = 0;
764
781
  let atLine = 0;
765
782
  let atCol = 0;
766
- // Offset of the next newline at or after the cursor, `-1` for none left in
767
- // this piece. Carried rather than searched for per mapping: `indexOf` has no
768
- // end bound, so asking it again for each of a piece's mappings scans again to
769
- // the end of the piece every time — and minified output, the case with no
770
- // newlines at all, is the one where that is the whole piece.
771
- let nextNewline = pieceAt(0).indexOf("\n");
772
- /**
773
- * @param {string} text the piece to walk
774
- * @param {number} to offset to walk to
775
- */
776
- const advanceOver = (text, to) => {
777
- while (nextNewline !== -1 && nextNewline < to) {
778
- atLine++;
779
- atCol = 0;
780
- atOffset = nextNewline + 1;
781
- nextNewline = text.indexOf("\n", atOffset);
782
- }
783
- atCol += to - atOffset;
784
- atOffset = to;
785
- };
786
- /**
787
- * @param {number} chunk piece index to advance to
788
- * @param {number} offset offset within it
789
- */
790
- const advanceTo = (chunk, offset) => {
791
- while (atChunk < chunk) {
792
- const text = pieceAt(atChunk);
793
- advanceOver(text, text.length);
794
- atChunk++;
795
- atOffset = 0;
796
- nextNewline = pieceAt(atChunk).indexOf("\n");
797
- }
798
- if (offset > atOffset) advanceOver(pieceAt(atChunk), offset);
799
- };
783
+ // Offset of the next newline at or after the cursor, `-1` for none left.
784
+ // Carried rather than searched for per mapping: `indexOf` has no end bound.
785
+ let nextNewline = text.indexOf("\n");
800
786
  for (const [chunkIndex, chunkOffset, sl, sc] of this._mappings) {
801
787
  // Its piece was taken back, so there is no output left to anchor.
802
788
  if (sl === -1) continue;
803
- advanceTo(chunkIndex, chunkOffset);
789
+ // A piece's length is stored, so summing them costs nothing per byte.
790
+ while (atChunk < chunkIndex) chunkStart += chunks[atChunk++].length;
791
+ const to = chunkStart + chunkOffset;
792
+ if (to > atOffset) {
793
+ while (nextNewline !== -1 && nextNewline < to) {
794
+ atLine++;
795
+ atCol = 0;
796
+ atOffset = nextNewline + 1;
797
+ nextNewline = text.indexOf("\n", atOffset);
798
+ }
799
+ atCol += to - atOffset;
800
+ atOffset = to;
801
+ }
804
802
  const gl = atLine;
805
803
  const gc = atCol;
806
804
  while (genLine < gl) {
@@ -915,7 +913,11 @@ class PrintContext {
915
913
  if (this._insertIdx < this._inserts.length) this._flushBefore(Infinity);
916
914
  // Nothing was ever cut into its own piece, so there is nothing to join.
917
915
  const chunks = this._chunks;
918
- return chunks.length === 0 ? this._tail : chunks.join("") + this._tail;
916
+ if (chunks.length === 0) return this._tail;
917
+ // The tail joins as a piece of its own, so the output comes back flat
918
+ // rather than as a rope over the join that every reader flattens again.
919
+ this._cutTail();
920
+ return chunks.join("");
919
921
  }
920
922
  }
921
923
 
@@ -1030,16 +1032,21 @@ class SourceProcessor {
1030
1032
  );
1031
1033
  this._grammar(input, this._visitors, ctx, opts);
1032
1034
  const name = /** @type {{ source?: string, content?: string }} */ (opts);
1033
- const build = () => ({
1034
- code: ctx.result(),
1035
- // Built only for a caller that named the input: building one walks the
1036
- // whole output for its line breaks, and the minifier prints an inline
1037
- // `style=""` — which asks for no map — thousands of times a document.
1038
- map:
1039
- name.source === undefined
1040
- ? undefined
1041
- : ctx.sourceMap({ source: name.source, content: name.content })
1042
- });
1035
+ const build = () => {
1036
+ const code = ctx.result();
1037
+ return {
1038
+ code,
1039
+ // Built only for a caller that named the input: a map walks the whole
1040
+ // output, and an inline `style=""` asks for none thousands of times a page.
1041
+ map:
1042
+ name.source === undefined
1043
+ ? undefined
1044
+ : ctx.sourceMap(
1045
+ { source: name.source, content: name.content },
1046
+ code
1047
+ )
1048
+ };
1049
+ };
1043
1050
  if (this._deferred !== null) {
1044
1051
  const finish = this._deferred;
1045
1052
 
@@ -17,6 +17,7 @@ const _0CharCode = "0".charCodeAt(0);
17
17
  const _9CharCode = "9".charCodeAt(0);
18
18
  const plusCharCode = "+".charCodeAt(0);
19
19
  const hyphenCharCode = "-".charCodeAt(0);
20
+ const dotCharCode = ".".charCodeAt(0);
20
21
  const colonCharCode = ":".charCodeAt(0);
21
22
  const hashCharCode = "#".charCodeAt(0);
22
23
  const queryCharCode = "?".charCodeAt(0);
@@ -46,7 +47,8 @@ function getScheme(specifier) {
46
47
  (ch >= aUpperCaseCharCode && ch <= zUpperCaseCharCode) ||
47
48
  (ch >= _0CharCode && ch <= _9CharCode) ||
48
49
  ch === plusCharCode ||
49
- ch === hyphenCharCode
50
+ ch === hyphenCharCode ||
51
+ ch === dotCharCode
50
52
  ) {
51
53
  if (++i === specifier.length) return;
52
54
  ch = specifier.charCodeAt(i);
@@ -0,0 +1,292 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Alexander Akait @alexander-akait
4
+ */
5
+
6
+ "use strict";
7
+
8
+ /**
9
+ * Wraps the shared completion callback for one item, so an iterator that
10
+ * reports twice fails loudly instead of settling the run early.
11
+ * @template E
12
+ * @param {(err?: E | null) => void} done shared completion callback
13
+ * @returns {(err?: E | null) => void} completion callback for a single item
14
+ */
15
+ const once = (done) => {
16
+ /** @type {((err?: E | null) => void) | undefined} */
17
+ let pending = done;
18
+ return (err) => {
19
+ const fn = pending;
20
+ if (fn === undefined) throw new Error("Callback was already called");
21
+ pending = undefined;
22
+ fn(err);
23
+ };
24
+ };
25
+
26
+ /**
27
+ * Runs `iterator` over every item with unlimited concurrency.
28
+ * Every item is started from one flat loop, so a synchronous iterator never
29
+ * grows the stack.
30
+ * @template T
31
+ * @template E
32
+ * @param {Iterable<T>} collection items to iterate
33
+ * @param {(item: T, callback: (err?: E | null) => void) => void} iterator called once per item
34
+ * @param {(err?: E | null) => void} callback called when every item is done, or with the first error
35
+ * @returns {void}
36
+ */
37
+ const each = (collection, iterator, callback) => {
38
+ let remaining = 1;
39
+ let finished = false;
40
+
41
+ /**
42
+ * @param {(E | null)=} err error
43
+ * @returns {void}
44
+ */
45
+ const done = (err) => {
46
+ if (finished) return;
47
+ if (err) {
48
+ finished = true;
49
+ callback(err);
50
+ return;
51
+ }
52
+ if (--remaining === 0) {
53
+ finished = true;
54
+ callback(null);
55
+ }
56
+ };
57
+
58
+ if (Array.isArray(collection)) {
59
+ const array = /** @type {T[]} */ (collection);
60
+ const length = array.length;
61
+ if (length === 0) return callback(null);
62
+ remaining = length;
63
+ // Dispatching continues past an error on purpose: callers rely on every
64
+ // item being started, e.g. to close every watcher when one close fails.
65
+ for (let i = 0; i < length; i++) iterator(array[i], once(done));
66
+ return;
67
+ }
68
+
69
+ // `remaining` starts at 1 so that completion cannot fire while items of a
70
+ // collection of unknown length are still being dispatched.
71
+ for (const item of collection) {
72
+ remaining++;
73
+ iterator(item, once(done));
74
+ }
75
+ done(null);
76
+ };
77
+
78
+ /**
79
+ * Runs `iterator` over every item, keeping at most `limit` of them in flight.
80
+ * A synchronous iterator is drained by the dispatch loop instead of by
81
+ * recursion, so the stack stays flat however long the collection is.
82
+ * @template T
83
+ * @template E
84
+ * @param {Iterable<T>} collection items to iterate
85
+ * @param {number} limit maximum number of items in flight
86
+ * @param {(item: T, callback: (err?: E | null) => void) => void} iterator called once per item
87
+ * @param {(err?: E | null) => void} callback called when every item is done, or with the first error
88
+ * @returns {void}
89
+ */
90
+ const eachLimit = (collection, limit, iterator, callback) => {
91
+ const array = Array.isArray(collection)
92
+ ? /** @type {T[]} */ (collection)
93
+ : undefined;
94
+ const length = array === undefined ? 0 : array.length;
95
+ const values =
96
+ array === undefined ? collection[Symbol.iterator]() : undefined;
97
+ let index = 0;
98
+ let running = 0;
99
+ let exhausted = false;
100
+ let finished = false;
101
+ let dispatching = false;
102
+
103
+ const dispatch = () => {
104
+ // A re-entrant call returns at once; the loop already running sees the
105
+ // slot the completed item freed and takes the next one itself.
106
+ if (dispatching) return;
107
+ dispatching = true;
108
+ while (running < limit && !exhausted) {
109
+ // `finished` is set from `done`, which an iterator may call before it
110
+ // returns, so it has to be re-read on every turn of this loop.
111
+ if (finished) break;
112
+ /** @type {T} */
113
+ let item;
114
+ if (array === undefined) {
115
+ const next = /** @type {Iterator<T>} */ (values).next();
116
+ if (next.done) {
117
+ exhausted = true;
118
+ break;
119
+ }
120
+ item = next.value;
121
+ } else {
122
+ if (index === length) {
123
+ exhausted = true;
124
+ break;
125
+ }
126
+ item = array[index++];
127
+ }
128
+ running++;
129
+ iterator(item, once(done));
130
+ }
131
+ dispatching = false;
132
+ if (exhausted && running === 0 && !finished) {
133
+ finished = true;
134
+ callback(null);
135
+ }
136
+ };
137
+
138
+ /**
139
+ * @param {(E | null)=} err error
140
+ * @returns {void}
141
+ */
142
+ const done = (err) => {
143
+ if (finished) return;
144
+ running--;
145
+ if (err) {
146
+ finished = true;
147
+ callback(err);
148
+ return;
149
+ }
150
+ dispatch();
151
+ };
152
+
153
+ if (limit < 1) return callback(null);
154
+
155
+ dispatch();
156
+ };
157
+
158
+ /**
159
+ * Runs `iterator` over every item with unlimited concurrency and collects the
160
+ * results in the order of the collection, not the order of completion.
161
+ * @template T
162
+ * @template R
163
+ * @template E
164
+ * @param {Iterable<T>} collection items to iterate
165
+ * @param {(item: T, callback: (err?: E | null, result?: R) => void) => void} iterator called once per item
166
+ * @param {(err?: E | null, results?: R[]) => void} callback called with every result, or with the first error
167
+ * @returns {void}
168
+ */
169
+ const map = (collection, iterator, callback) => {
170
+ const array = Array.isArray(collection)
171
+ ? /** @type {T[]} */ (collection)
172
+ : undefined;
173
+ // Pre-sized, because growing it or `Array.from` costs measurably more on
174
+ // the small collections this is called with.
175
+ /** @type {R[]} */
176
+ // eslint-disable-next-line unicorn/no-new-array
177
+ const results = array === undefined ? [] : new Array(array.length);
178
+ let remaining = 1;
179
+ let finished = false;
180
+
181
+ /**
182
+ * @param {(E | null)=} err error
183
+ * @returns {void}
184
+ */
185
+ const settle = (err) => {
186
+ if (finished) return;
187
+ if (err) {
188
+ finished = true;
189
+ callback(err, results);
190
+ return;
191
+ }
192
+ if (--remaining === 0) {
193
+ finished = true;
194
+ callback(null, results);
195
+ }
196
+ };
197
+
198
+ /**
199
+ * @param {number} index position the result of that item belongs at
200
+ * @returns {(err?: E | null, result?: R) => void} completion callback for that item
201
+ */
202
+ const createCallback = (index) => {
203
+ let position = index;
204
+ return (err, result) => {
205
+ const at = position;
206
+ if (at === -1) throw new Error("Callback was already called");
207
+ position = -1;
208
+ // A result arriving after the run settled must not reach `results`,
209
+ // which the callback already handed to the caller.
210
+ if (finished) return;
211
+ if (!err) results[at] = /** @type {R} */ (result);
212
+ settle(err);
213
+ };
214
+ };
215
+
216
+ if (array !== undefined) {
217
+ const length = array.length;
218
+ if (length === 0) return callback(null, results);
219
+ remaining = length;
220
+ for (let i = 0; i < length; i++) iterator(array[i], createCallback(i));
221
+ return;
222
+ }
223
+
224
+ let index = 0;
225
+ for (const item of collection) {
226
+ remaining++;
227
+ iterator(item, createCallback(index++));
228
+ }
229
+ results.length = index;
230
+ settle(null);
231
+ };
232
+
233
+ /**
234
+ * Runs `iterator` over every item, at most `limit` of them in flight, and
235
+ * collects the results in the order of the collection, not of completion.
236
+ * @template T
237
+ * @template R
238
+ * @template E
239
+ * @param {Iterable<T>} collection items to iterate
240
+ * @param {number} limit maximum number of items in flight
241
+ * @param {(item: T, callback: (err?: E | null, result?: R) => void) => void} iterator called once per item
242
+ * @param {(err?: E | null, results?: R[]) => void} callback called with every result, or with the first error
243
+ * @returns {void}
244
+ */
245
+ const mapLimit = (collection, limit, iterator, callback) => {
246
+ /** @type {R[]} */
247
+ const results = [];
248
+ let index = 0;
249
+ eachLimit(
250
+ collection,
251
+ limit,
252
+ (item, done) => {
253
+ // the dispatch loop hands out one item at a time, so this counts the
254
+ // position of the item rather than of whichever finishes first
255
+ const position = index++;
256
+ iterator(item, (err, result) => {
257
+ if (err) return done(err);
258
+ results[position] = /** @type {R} */ (result);
259
+ done(null);
260
+ });
261
+ },
262
+ (err) => {
263
+ if (err) return callback(err);
264
+ callback(null, results);
265
+ }
266
+ );
267
+ };
268
+
269
+ /**
270
+ * @template R
271
+ * @template E
272
+ * @param {(callback: (err?: E | null, result?: R) => void) => void} task task to run
273
+ * @param {(err?: E | null, result?: R) => void} callback called when the task is done
274
+ * @returns {void}
275
+ */
276
+ const runTask = (task, callback) => task(callback);
277
+
278
+ /**
279
+ * Runs every task in parallel and collects the results in task order.
280
+ * @template R
281
+ * @template E
282
+ * @param {((callback: (err?: E | null, result?: R) => void) => void)[]} tasks tasks to run
283
+ * @param {(err?: E | null, results?: R[]) => void} callback called with every result, or with the first error
284
+ * @returns {void}
285
+ */
286
+ const parallel = (tasks, callback) => map(tasks, runTask, callback);
287
+
288
+ module.exports.each = each;
289
+ module.exports.eachLimit = eachLimit;
290
+ module.exports.map = map;
291
+ module.exports.mapLimit = mapLimit;
292
+ module.exports.parallel = parallel;
@@ -0,0 +1,69 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Haijie Xie @hai-x
4
+ */
5
+
6
+ "use strict";
7
+
8
+ /** @import Module, { BuildDiagnostics, BuildInfo } from "../Module" */
9
+ /** @import ModuleGraph from "../ModuleGraph" */
10
+
11
+ /**
12
+ * The diagnostics record of a build info, created on first use so a module nothing reports about carries none.
13
+ * @param {BuildInfo} buildInfo the build info of the module
14
+ * @returns {BuildDiagnostics} the record
15
+ */
16
+ const getBuildDiagnostics = (buildInfo) => {
17
+ let diagnostics = buildInfo.diagnostics;
18
+ if (diagnostics === undefined) {
19
+ diagnostics = buildInfo.diagnostics = {
20
+ optimizationBailouts: undefined,
21
+ sideEffectStatement: undefined,
22
+ ineffectivePureAnnotations: undefined,
23
+ topLevelThis: undefined,
24
+ usesEval: undefined,
25
+ notCacheableReasons: undefined
26
+ };
27
+ }
28
+ return diagnostics;
29
+ };
30
+
31
+ /**
32
+ * Records a bailout a parser plugin found, where a module restored from the cache still has it for the module graph to report.
33
+ * @param {BuildInfo} buildInfo the build info of the module being parsed
34
+ * @param {string} reason the bailout as reported
35
+ * @returns {void}
36
+ */
37
+ const recordOptimizationBailout = (buildInfo, reason) => {
38
+ const diagnostics = getBuildDiagnostics(buildInfo);
39
+ const bailouts =
40
+ diagnostics.optimizationBailouts || (diagnostics.optimizationBailouts = []);
41
+ bailouts.push(reason);
42
+ };
43
+
44
+ /**
45
+ * Replays the bailouts parser plugins recorded for a module into the module graph,
46
+ * which a module reused from the cache never parses into.
47
+ * @param {ModuleGraph} moduleGraph the module graph
48
+ * @param {Module} module the built or still valid module
49
+ * @returns {void}
50
+ */
51
+ const replayOptimizationBailouts = (moduleGraph, module) => {
52
+ const buildInfo = module.buildInfo;
53
+ if (buildInfo === undefined) return;
54
+ const diagnostics = buildInfo.diagnostics;
55
+ if (
56
+ diagnostics === undefined ||
57
+ diagnostics.optimizationBailouts === undefined
58
+ ) {
59
+ return;
60
+ }
61
+ const bailouts = moduleGraph.getOptimizationBailout(module);
62
+ for (const reason of diagnostics.optimizationBailouts) bailouts.push(reason);
63
+ };
64
+
65
+ module.exports = {
66
+ getBuildDiagnostics,
67
+ recordOptimizationBailout,
68
+ replayOptimizationBailouts
69
+ };
@@ -115,7 +115,11 @@ module.exports.cssExportConvention = (input, convention) => {
115
115
  const set = new Set();
116
116
  if (typeof convention === "function") {
117
117
  const result = convention(input);
118
- const validate = (/** @type {string} */ name) => {
118
+ /**
119
+ * @param {string} name name returned by the convention function
120
+ * @returns {void}
121
+ */
122
+ const validate = (name) => {
119
123
  if (typeof name !== "string" || name.length === 0) {
120
124
  throw new Error(
121
125
  `exportsConvention function must return a non-empty string or an array of non-empty strings, got ${safeStringify(result)}`
package/lib/util/fs.js CHANGED
@@ -167,7 +167,7 @@ const { ABSOLUTE_PATH_REGEXP } = require("./identifier");
167
167
  * @typedef {{
168
168
  * (path: PathOrFileDescriptor, options?: { encoding?: null | undefined, flag?: string | undefined } | null): Buffer,
169
169
  * (path: PathOrFileDescriptor, options: { encoding: BufferEncoding, flag?: string | undefined } | BufferEncoding): string,
170
- * (path: PathOrFileDescriptor, options?: (ObjectEncodingOptions & { flag?: string | undefined }) | BufferEncoding | null): string | Buffer,
170
+ * (path: PathOrFileDescriptor, options: ObjectEncodingOptions & { flag?: string | undefined }): string | Buffer,
171
171
  * }} ReadFileSync
172
172
  */
173
173
 
@@ -402,6 +402,21 @@ const { ABSOLUTE_PATH_REGEXP } = require("./identifier");
402
402
  * @typedef {(path: PathLike, options?: BufferEncoding | ReadStreamOptions) => NodeJS.ReadableStream} CreateReadStream
403
403
  */
404
404
 
405
+ /**
406
+ * Defines the symlink type used by this module.
407
+ * @typedef {(target: PathLike, path: PathLike, type: "dir" | "file" | "junction" | null | undefined, callback: NoParamCallback) => void} Symlink
408
+ */
409
+
410
+ /**
411
+ * Defines the chmod type used by this module.
412
+ * @typedef {(path: PathLike, mode: number | string, callback: NoParamCallback) => void} Chmod
413
+ */
414
+
415
+ /**
416
+ * Defines the utimes type used by this module.
417
+ * @typedef {(path: PathLike, atime: number | string | Date, mtime: number | string | Date, callback: NoParamCallback) => void} Utimes
418
+ */
419
+
405
420
  /**
406
421
  * Defines the output file system type used by this module.
407
422
  * @typedef {object} OutputFileSystem
@@ -410,6 +425,10 @@ const { ABSOLUTE_PATH_REGEXP } = require("./identifier");
410
425
  * @property {Rmdir=} rmdir
411
426
  * @property {WriteFile} writeFile
412
427
  * @property {Unlink=} unlink
428
+ * @property {Symlink=} symlink
429
+ * @property {Readlink=} readlink
430
+ * @property {Chmod=} chmod
431
+ * @property {Utimes=} utimes
413
432
  * @property {Stat} stat
414
433
  * @property {LStat=} lstat
415
434
  * @property {ReadFile} readFile
@@ -755,6 +774,13 @@ const lstatReadlinkAbsolute = (fs, p, callback) => {
755
774
  */
756
775
  const isAbsolute = (pathname) => ABSOLUTE_PATH_REGEXP.test(pathname);
757
776
 
777
+ /**
778
+ * What of a file's mode is its permissions — the type bits above them are not
779
+ * settable, and the set-user-id and sticky bits are not carried over a copy.
780
+ */
781
+ const PERMISSIONS_MASK = 0o777;
782
+
783
+ module.exports.PERMISSIONS_MASK = PERMISSIONS_MASK;
758
784
  module.exports.dirname = dirname;
759
785
  module.exports.isAbsolute = isAbsolute;
760
786
  module.exports.join = join;