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.
- package/lib/Compilation.js +46 -1
- package/lib/css/CssGenerator.js +0 -10
- package/lib/css/CssModulesPlugin.js +11 -4
- package/lib/css/syntax-parser.js +171 -32
- package/lib/css/syntax-printer.js +1081 -1019
- package/lib/optimize/ConcatenatedModule.js +2 -2
- package/lib/util/SourceProcessor.js +48 -14
- package/package.json +3 -2
package/lib/Compilation.js
CHANGED
|
@@ -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
|
-
|
|
6520
|
+
codeGenInOrder([...modules], (err) => {
|
|
6476
6521
|
if (err) return callback(err);
|
|
6477
6522
|
reportErrors();
|
|
6478
6523
|
|
package/lib/css/CssGenerator.js
CHANGED
|
@@ -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 {
|
|
923
|
+
return {
|
|
924
|
+
list: sortedModules,
|
|
925
|
+
set: numberOfGroups > 1 ? new Set(sortedModules) : undefined
|
|
926
|
+
};
|
|
923
927
|
}
|
|
924
928
|
);
|
|
925
929
|
|
|
926
|
-
if (
|
|
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 (
|
|
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
|
}
|
package/lib/css/syntax-parser.js
CHANGED
|
@@ -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
|
-
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
14096
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
18786
|
-
/** @type {
|
|
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(
|
|
18867
|
+
properties.push(-1);
|
|
18797
18868
|
rankOf.push(-1);
|
|
18798
18869
|
continue;
|
|
18799
18870
|
}
|
|
18800
|
-
const
|
|
18801
|
-
if (
|
|
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(
|
|
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
|
-
|
|
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
|