webpack 5.112.1 → 5.112.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -36,6 +36,7 @@ const { LogType, Logger } = require("./logging/Logger");
36
36
  const CodeGenerationResults = require("./module/CodeGenerationResults");
37
37
  const Module = require("./module/Module");
38
38
  const ModuleProfile = require("./module/ModuleProfile");
39
+ const { JAVASCRIPT_TYPE } = require("./module/ModuleSourceTypeConstants");
39
40
  const LazyBarrels = require("./optimize/LazyBarrels");
40
41
  const RuntimeGlobals = require("./runtime/RuntimeGlobals");
41
42
  const Stats = require("./stats/Stats");
@@ -6415,6 +6416,16 @@ This prevents using hashes of each other and should be avoided.`);
6415
6416
  chunkGraph.connectChunkAndModule(chunk, module);
6416
6417
  }
6417
6418
 
6419
+ // The loader reads `module` as JavaScript, a consumer only this chunk graph has.
6420
+ const sourceTypes = module.getSourceTypes();
6421
+ if (!sourceTypes.has(JAVASCRIPT_TYPE)) {
6422
+ chunkGraph.setChunkModuleSourceTypes(
6423
+ chunk,
6424
+ module,
6425
+ new Set([...sourceTypes, JAVASCRIPT_TYPE])
6426
+ );
6427
+ }
6428
+
6418
6429
  /** @type {WebpackError[]} */
6419
6430
  const errors = [];
6420
6431
 
@@ -6471,8 +6482,42 @@ This prevents using hashes of each other and should be avoided.`);
6471
6482
  }
6472
6483
  };
6473
6484
 
6485
+ /**
6486
+ * Generates code for modules, each after the ones its `codeGenerationDependencies` read.
6487
+ * @param {Module[]} pending modules whose code is not generated yet
6488
+ * @param {Callback} callback callback
6489
+ * @returns {void}
6490
+ */
6491
+ const codeGenInOrder = (pending, callback) => {
6492
+ const pendingSet = new Set(pending);
6493
+ /** @type {Module[]} */
6494
+ const ready = [];
6495
+ /** @type {Module[]} */
6496
+ const delayed = [];
6497
+ for (const module of pending) {
6498
+ const { codeGenerationDependencies } = module;
6499
+ const waits =
6500
+ codeGenerationDependencies !== undefined &&
6501
+ codeGenerationDependencies.some((dep) => {
6502
+ const referencedModule = this.moduleGraph.getModule(dep);
6503
+ return (
6504
+ referencedModule !== null && pendingSet.has(referencedModule)
6505
+ );
6506
+ });
6507
+ (waits ? delayed : ready).push(module);
6508
+ }
6509
+ // A cycle never frees a module, so generate them all and let templates report.
6510
+ if (ready.length === 0) {
6511
+ return asyncLib.eachLimit(pending, 10, codeGen, callback);
6512
+ }
6513
+ asyncLib.eachLimit(ready, 10, codeGen, (err) => {
6514
+ if (err || delayed.length === 0) return callback(err);
6515
+ codeGenInOrder(delayed, callback);
6516
+ });
6517
+ };
6518
+
6474
6519
  // Generate code for all aggregated modules
6475
- asyncLib.eachLimit(modules, 10, codeGen, (err) => {
6520
+ codeGenInOrder([...modules], (err) => {
6476
6521
  if (err) return callback(err);
6477
6522
  reportErrors();
6478
6523
 
@@ -686,16 +686,6 @@ class CssGenerator extends Generator {
686
686
  continue;
687
687
  }
688
688
 
689
- // `importModule()` executes the module as JavaScript, and its dependency
690
- // carries no origin module (`connectOrigin: false` in `LoaderPlugin`).
691
- if (
692
- connection.dependency !== null &&
693
- isDependencyKind(connection.dependency, "loader-import")
694
- ) {
695
- hasJs = true;
696
- continue;
697
- }
698
-
699
689
  if (!connection.originModule) {
700
690
  continue;
701
691
  }
@@ -904,6 +904,7 @@ class CssModulesPlugin {
904
904
 
905
905
  // Get ordered list of modules per chunk group
906
906
  // Lists are in reverse order to allow to use Array.pop()
907
+ const numberOfGroups = chunk.getNumberOfGroups();
907
908
  const modulesByChunkGroup = Array.from(
908
909
  chunk.groupsIterable,
909
910
  (chunkGroup) => {
@@ -919,11 +920,14 @@ class CssModulesPlugin {
919
920
  )
920
921
  .map((item) => item.module);
921
922
 
922
- return { list: sortedModules, set: new Set(sortedModules) };
923
+ return {
924
+ list: sortedModules,
925
+ set: numberOfGroups > 1 ? new Set(sortedModules) : undefined
926
+ };
923
927
  }
924
928
  );
925
929
 
926
- if (modulesByChunkGroup.length === 1) {
930
+ if (numberOfGroups === 1) {
927
931
  return modulesByChunkGroup[0].list.reverse();
928
932
  }
929
933
 
@@ -967,7 +971,7 @@ class CssModulesPlugin {
967
971
  if (list.length === 0) continue;
968
972
  const lastModule = list[list.length - 1];
969
973
  if (lastModule === selectedModule) continue;
970
- if (!set.has(selectedModule)) continue;
974
+ if (!(/** @type {Set<Module>} */ (set).has(selectedModule))) continue;
971
975
  failedModules.add(selectedModule);
972
976
  if (failedModules.has(lastModule)) {
973
977
  // There is a conflict, try other alternatives
@@ -1026,7 +1030,10 @@ class CssModulesPlugin {
1026
1030
  const lastModule = list[list.length - 1];
1027
1031
  if (lastModule === selectedModule) {
1028
1032
  list.pop();
1029
- } else if (hasFailed && set.has(selectedModule)) {
1033
+ } else if (
1034
+ hasFailed &&
1035
+ /** @type {Set<Module>} */ (set).has(selectedModule)
1036
+ ) {
1030
1037
  const idx = list.indexOf(selectedModule);
1031
1038
  if (idx >= 0) list.splice(idx, 1);
1032
1039
  }
@@ -5380,8 +5380,8 @@ class TakenPiece {
5380
5380
  constructor(piece, text, empties) {
5381
5381
  /** @type {number} */
5382
5382
  this.piece = piece;
5383
- /** @type {RuleSpan[]} */
5384
- this.spans = [];
5383
+ /** @type {RuleSpan[]} shared and empty until `_noteSpans` gives it its own */
5384
+ this.spans = _NO_RULE_SPANS;
5385
5385
  /** @type {number} */
5386
5386
  this.empties = empties;
5387
5387
  /** @type {string} */
@@ -6373,7 +6373,13 @@ const _noteSpans = (writer, taken, spans, chain) => {
6373
6373
  for (const span of spans) {
6374
6374
  if (chain.length !== 0) span.scope = _enclosingRuleScope(span.scope, chain);
6375
6375
  span.taken = taken;
6376
- taken.spans.push(span);
6376
+ }
6377
+ // A copy its own size: a first push would give the list room for 17, and
6378
+ // the piece holds it until the sheet ends.
6379
+ if (taken.spans.length === 0) {
6380
+ taken.spans = [...spans];
6381
+ } else {
6382
+ for (const span of spans) taken.spans.push(span);
6377
6383
  }
6378
6384
  for (const span of spans) {
6379
6385
  if (span.key === UNKEYED) continue;
@@ -12855,10 +12861,11 @@ const _lowerDirSelector = (parts) => {
12855
12861
  * Empty parts are stepped over — a comment between the colons printed away, and
12856
12862
  * the tokenizer had already dropped it anyway.
12857
12863
  * @param {string[]} parts the prelude's printed parts
12858
- * @returns {void}
12864
+ * @returns {boolean} whether a pseudo it read may be an `:is()` for `_unwrapLoneIs`
12859
12865
  */
12860
12866
  const _foldPseudoNames = (parts) => {
12861
12867
  const dropping = _S._transforms.shortenSelectors;
12868
+ let mayUnwrap = false;
12862
12869
  // The two non-empty parts before the current one.
12863
12870
  let first = -1;
12864
12871
  let second = -1;
@@ -12869,6 +12876,13 @@ const _foldPseudoNames = (parts) => {
12869
12876
  // not, `linearGradient` being an SVG element, and nor does an id, class or
12870
12877
  // attribute value. A functional pseudo folds its own name alone.
12871
12878
  if (second !== -1 && parts[second] === ":") {
12879
+ if (
12880
+ part.length > 4 &&
12881
+ part.charCodeAt(2) === CC_LEFT_PARENTHESIS &&
12882
+ (part.charCodeAt(0) | 0x20) === CC_LOWER_I
12883
+ ) {
12884
+ mayUnwrap = true;
12885
+ }
12872
12886
  if (_S._transforms.foldCase && !part.includes("(")) {
12873
12887
  const lowered = asciiLowercaseName(part);
12874
12888
  if (lowered !== part) {
@@ -12890,6 +12904,7 @@ const _foldPseudoNames = (parts) => {
12890
12904
  first = second;
12891
12905
  second = i;
12892
12906
  }
12907
+ return mayUnwrap;
12893
12908
  };
12894
12909
 
12895
12910
  // A legacy pseudo-element written with one colon, which `:is()` cannot hold.
@@ -12933,19 +12948,9 @@ const _isCompoundText = (selector) => {
12933
12948
  * Unwrap each `:is()` holding one compound, which matches the same elements with
12934
12949
  * the same specificity. Only where the targets read every pseudo it names, since
12935
12950
  * `:is()` forgives an argument it cannot parse and a bare compound does not.
12936
- * @param {string[]} parts a selector's printed parts, rewritten in place
12951
+ * @param {string[]} parts a selector's printed parts, rewritten in place, called only where `_foldPseudoNames` read a pseudo that may be an `:is()`
12937
12952
  */
12938
12953
  const _unwrapLoneIs = (parts) => {
12939
- // Almost no selector holds an `:is()`, and the walk below reads every part.
12940
- let candidate = false;
12941
- for (let i = 0; i < parts.length && !candidate; i++) {
12942
- const part = parts[i];
12943
- candidate =
12944
- part.length > 4 &&
12945
- part.charCodeAt(2) === CC_LEFT_PARENTHESIS &&
12946
- (part.charCodeAt(0) | 0x20) === CC_LOWER_I;
12947
- }
12948
- if (!candidate) return;
12949
12954
  let before = -1;
12950
12955
  // Past a pseudo-element a compound takes only a few pseudo-classes, which an
12951
12956
  // `:is()` there may hold and a bare compound may not.
@@ -13390,7 +13395,8 @@ const _selectsFeatureless = (parts, at) => {
13390
13395
  * @returns {void}
13391
13396
  */
13392
13397
  const _dropImpliedUniversalSelector = (parts) => {
13393
- if (!_S._transforms.shortenSelectors) return;
13398
+ // A native search first: almost no selector holds a `*` at all.
13399
+ if (!_S._transforms.shortenSelectors || !parts.includes("*")) return;
13394
13400
  let previous = -1;
13395
13401
  for (let i = 0; i < parts.length; i++) {
13396
13402
  const part = parts[i];
@@ -14084,6 +14090,10 @@ const _foldFollowingLonghands = (path, items, texts, superseded) => {
14084
14090
  // asks again of the ones before it, and a fold keeps the property it rewrites.
14085
14091
  /** @type {(string | undefined)[]} */
14086
14092
  const properties = [];
14093
+ // The number `_declarationTable` gives each, or -1 for one it does not name.
14094
+ /** @type {number[]} */
14095
+ const ids = [];
14096
+ const table = _declarationTable();
14087
14097
  /**
14088
14098
  * The property a declaration sets, read through `_canonicalProperty`.
14089
14099
  * @param {number} at the declaration's index
@@ -14092,13 +14102,31 @@ const _foldFollowingLonghands = (path, items, texts, superseded) => {
14092
14102
  const propertyAt = (at) => {
14093
14103
  let property = properties[at];
14094
14104
  if (property === undefined) {
14095
- property = _canonicalProperty(
14096
- _printedProperty(texts[at], texts[at].indexOf(":"))
14097
- );
14105
+ const printed = _printedProperty(texts[at], texts[at].indexOf(":"));
14106
+ const id = table.ids.get(printed);
14107
+ if (id === undefined) {
14108
+ property = printed;
14109
+ ids[at] = -1;
14110
+ } else {
14111
+ ids[at] = table.canonical[id];
14112
+ property = table.names[ids[at]];
14113
+ }
14098
14114
  properties[at] = property;
14099
14115
  }
14100
14116
  return property;
14101
14117
  };
14118
+ /**
14119
+ * Whether two declarations must keep their order, as `_orderMatters` reads it.
14120
+ * @param {number} a a declaration's index, its property already read
14121
+ * @param {number} b another's
14122
+ * @returns {boolean} true when the two must keep their order
14123
+ */
14124
+ const orderMattersAt = (a, b) => {
14125
+ const property = propertyAt(b);
14126
+ return ids[a] !== -1 && ids[b] !== -1
14127
+ ? _orderMattersById(table, ids[a], ids[b])
14128
+ : _orderMatters(/** @type {string} */ (properties[a]), property);
14129
+ };
14102
14130
  for (let i = 0; i < items.length; i++) {
14103
14131
  // A dropped declaration prints nothing, so nothing stands where it stood.
14104
14132
  if (texts[i].length === 0 || superseded.has(i)) continue;
@@ -14116,7 +14144,8 @@ const _foldFollowingLonghands = (path, items, texts, superseded) => {
14116
14144
  superseded,
14117
14145
  i,
14118
14146
  dropsWithPrefix,
14119
- propertyAt
14147
+ propertyAt,
14148
+ orderMattersAt
14120
14149
  )
14121
14150
  ) {
14122
14151
  superseded.add(i);
@@ -14142,6 +14171,7 @@ let _anyLonghand = null;
14142
14171
  * @param {number} from the longhand's index
14143
14172
  * @param {(at: number) => boolean} drops whether a declaration is dropped later
14144
14173
  * @param {(at: number) => string} propertyAt the property a declaration sets, read through `_canonicalProperty`
14174
+ * @param {(a: number, b: number) => boolean} orderMattersAt `_orderMatters` of two declarations' properties, the first already read
14145
14175
  * @returns {boolean} true when it was folded into one before it
14146
14176
  */
14147
14177
  const _foldIntoEarlier = (
@@ -14151,7 +14181,8 @@ const _foldIntoEarlier = (
14151
14181
  superseded,
14152
14182
  from,
14153
14183
  drops,
14154
- propertyAt
14184
+ propertyAt,
14185
+ orderMattersAt
14155
14186
  ) => {
14156
14187
  if (_anyLonghand === null) {
14157
14188
  _anyLonghand = new Set();
@@ -14171,7 +14202,7 @@ const _foldIntoEarlier = (
14171
14202
  if (texts[at].length === 0 || superseded.has(at)) continue;
14172
14203
  if (path.type(items[at]) !== NodeType.Declaration) return false;
14173
14204
  if (drops(at)) continue;
14174
- if (_orderMatters(property, propertyAt(at))) {
14205
+ if (orderMattersAt(from, at)) {
14175
14206
  return _foldInto(path, items, texts, at, from);
14176
14207
  }
14177
14208
  }
@@ -15408,7 +15439,22 @@ const _mergeBoxLonghands = (
15408
15439
  // tail uncovered, dropping its declaration.
15409
15440
  /** @type {Set<Node> | null} */
15410
15441
  let claimed = null;
15411
- for (let e = 0; e < table.length; e++) {
15442
+ // Only an entry whose first longhand the block writes can merge, and blocks
15443
+ // write few properties against a table of dozens of entries.
15444
+ const firsts = _mergeTableFirsts(table);
15445
+ /** @type {number[]} */
15446
+ const candidates = [];
15447
+ for (const property of at.keys()) {
15448
+ const entries = firsts.get(property);
15449
+ if (entries !== undefined) {
15450
+ for (const entry of entries) candidates.push(entry);
15451
+ }
15452
+ }
15453
+ if (candidates.length === 0) return null;
15454
+ // In table order, as the claims between entries are made.
15455
+ if (candidates.length > 1) candidates.sort((a, b) => a - b);
15456
+ for (let c = 0; c < candidates.length; c++) {
15457
+ const e = candidates[c];
15412
15458
  const shorthand = table[e][0];
15413
15459
  const longhands = table[e][1];
15414
15460
  // A plain loop: this runs for every table entry of every rule, where one
@@ -15896,6 +15942,30 @@ const MERGE_FAMILY = 1;
15896
15942
  const MERGE_SLASH = 2;
15897
15943
  const MERGE_ORDERED = 3;
15898
15944
 
15945
+ /** @type {WeakMap<[string, string[]][], Map<string, number[]>>} */
15946
+ const _mergeTableFirstsCache = new WeakMap();
15947
+
15948
+ /**
15949
+ * A merge table's entries by their first longhand, which a block has to write
15950
+ * for the entry to merge.
15951
+ * @param {[string, string[]][]} table a merge table
15952
+ * @returns {Map<string, number[]>} the indexes of the entries each first longhand leads
15953
+ */
15954
+ const _mergeTableFirsts = (table) => {
15955
+ let firsts = _mergeTableFirstsCache.get(table);
15956
+ if (firsts === undefined) {
15957
+ firsts = new Map();
15958
+ for (let e = 0; e < table.length; e++) {
15959
+ const first = table[e][1][0];
15960
+ const entries = firsts.get(first);
15961
+ if (entries === undefined) firsts.set(first, [e]);
15962
+ else entries.push(e);
15963
+ }
15964
+ _mergeTableFirstsCache.set(table, firsts);
15965
+ }
15966
+ return firsts;
15967
+ };
15968
+
15899
15969
  // Each table as its entries, read by index: a `for…of` over the map would
15900
15970
  // allocate an entry pair per row of every table for every block merged.
15901
15971
  /** @type {[[string, string[]][], number][]} */
@@ -18086,8 +18156,9 @@ const _rulePrelude = (path, writer, minify, outParts) => {
18086
18156
  if (_S._transforms.customSelectors && _customSelectors.size !== 0) {
18087
18157
  _writeCustomSelector(parts);
18088
18158
  }
18089
- _foldPseudoNames(parts);
18090
- if (_S._transforms.shortenSelectors) _unwrapLoneIs(parts);
18159
+ if (_foldPseudoNames(parts) && _S._transforms.shortenSelectors) {
18160
+ _unwrapLoneIs(parts);
18161
+ }
18091
18162
  // After the fold, which is what makes the names above match, and before the
18092
18163
  // class replacement, so a pseudo written as a class is one either way.
18093
18164
  if (!_S._isSelectorAllowed) {
@@ -18782,8 +18853,8 @@ const _writesOnlyDeclarations = (path, items, texts) => {
18782
18853
  * @returns {number[] | null} where each comes from, or null to keep them as written
18783
18854
  */
18784
18855
  const _declarationOrder = (texts) => {
18785
- const ranks = getDeclarationRanks();
18786
- /** @type {string[]} */
18856
+ const table = _declarationTable();
18857
+ /** @type {number[]} */
18787
18858
  const properties = [];
18788
18859
  /** @type {number[]} */
18789
18860
  const rankOf = [];
@@ -18793,14 +18864,15 @@ const _declarationOrder = (texts) => {
18793
18864
  if (colon <= 0) return null;
18794
18865
  const property = toLowerCaseIfNeeded(text.slice(0, colon));
18795
18866
  if (property.startsWith("--")) {
18796
- properties.push(property);
18867
+ properties.push(-1);
18797
18868
  rankOf.push(-1);
18798
18869
  continue;
18799
18870
  }
18800
- const rank = ranks.get(property);
18801
- if (rank === undefined) return null;
18871
+ const id = table.ids.get(property);
18872
+ if (id === undefined) return null;
18873
+ const rank = table.ranks[id];
18802
18874
  if (rank !== -1) ranked = true;
18803
- properties.push(_canonicalProperty(property));
18875
+ properties.push(table.canonical[id]);
18804
18876
  rankOf.push(rank);
18805
18877
  }
18806
18878
  if (!ranked) return null;
@@ -18832,7 +18904,7 @@ const _declarationOrder = (texts) => {
18832
18904
  for (let j = i + 1; j < order.length; j++) {
18833
18905
  if (
18834
18906
  order[j] < order[i] &&
18835
- _orderMatters(properties[order[i]], properties[order[j]])
18907
+ _orderMattersById(table, properties[order[i]], properties[order[j]])
18836
18908
  ) {
18837
18909
  return null;
18838
18910
  }
@@ -18841,6 +18913,73 @@ const _declarationOrder = (texts) => {
18841
18913
  return moved ? order : null;
18842
18914
  };
18843
18915
 
18916
+ /**
18917
+ * Every property `getDeclarationRanks` names by a small number: its rank, the
18918
+ * number of the property `_canonicalProperty` reads it as, and `_orderMatters`
18919
+ * of two such numbers, filled in as pairs are asked of.
18920
+ * @typedef {object} DeclarationTable
18921
+ * @property {Map<string, number>} ids each property's number
18922
+ * @property {Int32Array} ranks the rank of each number
18923
+ * @property {Int32Array} canonical the number of the property each is read as
18924
+ * @property {string[]} names the property each number stands for
18925
+ * @property {number} all the number of `all`
18926
+ * @property {Uint8Array} matters `_orderMatters` by `a * names.length + b`: 0 unknown, 1 no, 2 yes
18927
+ */
18928
+
18929
+ /** @type {DeclarationTable | undefined} */
18930
+ let _declarationTableValue;
18931
+
18932
+ /**
18933
+ * @returns {DeclarationTable} the table, built on first use
18934
+ */
18935
+ const _declarationTable = () => {
18936
+ if (_declarationTableValue !== undefined) return _declarationTableValue;
18937
+ const rankMap = getDeclarationRanks();
18938
+ /** @type {Map<string, number>} */
18939
+ const ids = new Map();
18940
+ /** @type {string[]} */
18941
+ const names = [];
18942
+ for (const name of rankMap.keys()) {
18943
+ ids.set(name, names.length);
18944
+ names.push(name);
18945
+ }
18946
+ const ranks = new Int32Array(names.length);
18947
+ const canonical = new Int32Array(names.length);
18948
+ for (let i = 0; i < names.length; i++) {
18949
+ ranks[i] = /** @type {number} */ (rankMap.get(names[i]));
18950
+ const id = ids.get(_canonicalProperty(names[i]));
18951
+ canonical[i] = id === undefined ? i : id;
18952
+ }
18953
+ _declarationTableValue = {
18954
+ ids,
18955
+ ranks,
18956
+ canonical,
18957
+ names,
18958
+ all: /** @type {number} */ (ids.get("all")),
18959
+ matters: new Uint8Array(names.length * names.length)
18960
+ };
18961
+ return _declarationTableValue;
18962
+ };
18963
+
18964
+ /**
18965
+ * `_orderMatters` of two numbered properties, -1 for a custom one.
18966
+ * @param {DeclarationTable} table the numbering
18967
+ * @param {number} a a property's canonical number
18968
+ * @param {number} b another
18969
+ * @returns {boolean} true when the two must keep their order
18970
+ */
18971
+ const _orderMattersById = (table, a, b) => {
18972
+ if (a === b || a === table.all || b === table.all) return true;
18973
+ // Two custom properties are both -1 yet never trade places: they share a rank.
18974
+ if (a === -1 || b === -1) return false;
18975
+ const at = a * table.names.length + b;
18976
+ const known = table.matters[at];
18977
+ if (known !== 0) return known === 2;
18978
+ const matters = _computeOrderMatters(table.names[a], table.names[b]);
18979
+ table.matters[at] = matters ? 2 : 1;
18980
+ return matters;
18981
+ };
18982
+
18844
18983
  /**
18845
18984
  * Put one declaration list together: the list-wide transforms (merge a family's
18846
18985
  * longhands into their shorthand, drop what a later declaration supersedes, add