@angular/ssr 22.1.0-next.4 → 22.1.0-rc.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.
@@ -630,27 +630,74 @@ function requireStringifier () {
630
630
  return str[0].toUpperCase() + str.slice(1)
631
631
  }
632
632
 
633
+ function atruleStart(str, node) {
634
+ let name = '@' + node.name;
635
+ let params = node.params ? str.rawValue(node, 'params') : '';
636
+
637
+ if (typeof node.raws.afterName !== 'undefined') {
638
+ name += node.raws.afterName;
639
+ } else if (params) {
640
+ name += ' ';
641
+ }
642
+
643
+ return name + params
644
+ }
645
+
646
+ function pushBody(str, stack, node) {
647
+ let nodes = node.nodes;
648
+ let last = nodes.length - 1;
649
+ while (last > 0) {
650
+ if (nodes[last].type !== 'comment') break
651
+ last -= 1;
652
+ }
653
+
654
+ let semicolon = str.raw(node, 'semicolon');
655
+ let isDocument = node.type === 'document';
656
+ for (let i = nodes.length - 1; i >= 0; i--) {
657
+ stack.push({
658
+ document: isDocument,
659
+ node: nodes[i],
660
+ semicolon: last !== i || semicolon
661
+ });
662
+ }
663
+ }
664
+
665
+ function pushBlock(str, stack, node, start) {
666
+ let between = str.raw(node, 'between', 'beforeOpen');
667
+ str.builder(escapeHTMLInCSS(start + between) + '{', node, 'start');
668
+
669
+ let hasNodes = node.nodes && node.nodes.length;
670
+ let close = () => {
671
+ let after = hasNodes
672
+ ? str.raw(node, 'after')
673
+ : str.raw(node, 'after', 'emptyBody');
674
+ if (after) str.builder(escapeHTMLInCSS(after));
675
+ str.builder('}', node, 'end');
676
+ if (node.type === 'rule' && node.raws.ownSemicolon) {
677
+ str.builder(escapeHTMLInCSS(node.raws.ownSemicolon), node, 'end');
678
+ }
679
+ };
680
+
681
+ if (hasNodes) {
682
+ stack.push(close);
683
+ pushBody(str, stack, node);
684
+ } else {
685
+ close();
686
+ }
687
+ }
688
+
633
689
  class Stringifier {
634
690
  constructor(builder) {
635
691
  this.builder = builder;
636
692
  }
637
693
 
638
694
  atrule(node, semicolon) {
639
- let raws = node.raws;
640
- let name = '@' + node.name;
641
- let params = node.params ? this.rawValue(node, 'params') : '';
642
-
643
- if (typeof raws.afterName !== 'undefined') {
644
- name += raws.afterName;
645
- } else if (params) {
646
- name += ' ';
647
- }
648
-
695
+ let start = atruleStart(this, node);
649
696
  if (node.nodes) {
650
- this.block(node, name + params);
697
+ this.block(node, start);
651
698
  } else {
652
- let end = (raws.between || '') + (semicolon ? ';' : '');
653
- this.builder(escapeHTMLInCSS(name + params + end), node);
699
+ let end = (node.raws.between || '') + (semicolon ? ';' : '');
700
+ this.builder(escapeHTMLInCSS(start + end), node);
654
701
  }
655
702
  }
656
703
 
@@ -700,20 +747,38 @@ function requireStringifier () {
700
747
  }
701
748
 
702
749
  body(node) {
703
- let nodes = node.nodes;
704
- let last = nodes.length - 1;
705
- while (last > 0) {
706
- if (nodes[last].type !== 'comment') break
707
- last -= 1;
708
- }
750
+ // Rules and at-rules are expanded into an explicit stack instead of
751
+ // recursive `stringify()` calls to survive deeply nested trees.
752
+ // If a subclass changes the traversal methods, its children go
753
+ // through `stringify()` to keep the override in charge.
754
+ let proto = Stringifier.prototype;
755
+ let expandable = ['atrule', 'block', 'body', 'rule', 'stringify'].every(
756
+ method => this[method] === proto[method]
757
+ );
758
+
759
+ let stack = [];
760
+ pushBody(this, stack, node);
761
+
762
+ while (stack.length > 0) {
763
+ let entry = stack.pop();
764
+ if (typeof entry === 'function') {
765
+ entry();
766
+ continue
767
+ }
709
768
 
710
- let semicolon = this.raw(node, 'semicolon');
711
- let isDocument = node.type === 'document';
712
- for (let i = 0; i < nodes.length; i++) {
713
- let child = nodes[i];
769
+ let child = entry.node;
714
770
  let before = this.raw(child, 'before');
715
- if (before) this.builder(isDocument ? before : escapeHTMLInCSS(before));
716
- this.stringify(child, last !== i || semicolon);
771
+ if (before) {
772
+ this.builder(entry.document ? before : escapeHTMLInCSS(before));
773
+ }
774
+
775
+ if (expandable && child.type === 'rule') {
776
+ pushBlock(this, stack, child, this.rawValue(child, 'selector'));
777
+ } else if (expandable && child.type === 'atrule' && child.nodes) {
778
+ pushBlock(this, stack, child, atruleStart(this, child));
779
+ } else {
780
+ this.stringify(child, entry.semicolon);
781
+ }
717
782
  }
718
783
  }
719
784
 
@@ -1021,25 +1086,41 @@ function requireNode$1 () {
1021
1086
 
1022
1087
  function cloneNode(obj, parent) {
1023
1088
  let cloned = new obj.constructor();
1024
-
1025
- for (let i in obj) {
1026
- if (!Object.prototype.hasOwnProperty.call(obj, i)) {
1027
- /* c8 ignore next 2 */
1028
- continue
1029
- }
1030
- if (i === 'proxyCache') continue
1031
- let value = obj[i];
1032
- let type = typeof value;
1033
-
1034
- if (i === 'parent' && type === 'object') {
1035
- if (parent) cloned[i] = parent;
1036
- } else if (i === 'source') {
1037
- cloned[i] = value;
1038
- } else if (Array.isArray(value)) {
1039
- cloned[i] = value.map(j => cloneNode(j, cloned));
1040
- } else {
1041
- if (type === 'object' && value !== null) value = cloneNode(value);
1042
- cloned[i] = value;
1089
+ // An explicit stack instead of recursive calls to survive deeply
1090
+ // nested trees. Each entry is [source, its clone, clone's parent].
1091
+ let stack = [[obj, cloned, parent]];
1092
+
1093
+ while (stack.length > 0) {
1094
+ let [source, target, targetParent] = stack.pop();
1095
+ for (let i in source) {
1096
+ if (!Object.prototype.hasOwnProperty.call(source, i)) {
1097
+ /* c8 ignore next 2 */
1098
+ continue
1099
+ }
1100
+ if (i === 'proxyCache') continue
1101
+ let value = source[i];
1102
+ let type = typeof value;
1103
+
1104
+ if (i === 'parent' && type === 'object') {
1105
+ if (targetParent) target[i] = targetParent;
1106
+ } else if (i === 'source') {
1107
+ target[i] = value;
1108
+ } else if (Array.isArray(value)) {
1109
+ let children = [];
1110
+ target[i] = children;
1111
+ for (let j of value) {
1112
+ let childClone = new j.constructor();
1113
+ children.push(childClone);
1114
+ stack.push([j, childClone, target]);
1115
+ }
1116
+ } else {
1117
+ if (type === 'object' && value !== null) {
1118
+ let valueClone = new value.constructor();
1119
+ stack.push([value, valueClone, undefined]);
1120
+ value = valueClone;
1121
+ }
1122
+ target[i] = value;
1123
+ }
1043
1124
  }
1044
1125
  }
1045
1126
 
@@ -1083,7 +1164,8 @@ function requireNode$1 () {
1083
1164
  this[isClean] = false;
1084
1165
  this[my] = true;
1085
1166
 
1086
- for (let name in defaults) {
1167
+ for (let name of Object.keys(defaults)) {
1168
+ if (name === '__proto__') continue
1087
1169
  if (name === 'nodes') {
1088
1170
  this.nodes = [];
1089
1171
  for (let node of defaults[name]) {
@@ -1395,47 +1477,68 @@ function requireNode$1 () {
1395
1477
  }
1396
1478
 
1397
1479
  toJSON(_, inputs) {
1398
- let fixed = {};
1399
1480
  let emitInputs = inputs == null;
1400
1481
  inputs = inputs || new Map();
1401
- let inputsNextIndex = 0;
1402
1482
 
1403
- for (let name in this) {
1404
- if (!Object.prototype.hasOwnProperty.call(this, name)) {
1405
- /* c8 ignore next 2 */
1406
- continue
1407
- }
1408
- if (name === 'parent' || name === 'proxyCache') continue
1409
- let value = this[name];
1483
+ // A worklist instead of recursive `toJSON()` calls to survive deeply
1484
+ // nested trees. Each entry converts one node and writes the result
1485
+ // into the already converted parent by [holder, key].
1486
+ let holderOfRoot = [];
1487
+ let queue = [[this, holderOfRoot, 0]];
1488
+
1489
+ for (let step = 0; step < queue.length; step++) {
1490
+ let [node, holder, key] = queue[step];
1491
+ let fixed = {};
1492
+ holder[key] = fixed;
1410
1493
 
1411
- if (Array.isArray(value)) {
1412
- fixed[name] = value.map(i => {
1413
- if (typeof i === 'object' && i.toJSON) {
1414
- return i.toJSON(null, inputs)
1494
+ for (let name in node) {
1495
+ if (!Object.prototype.hasOwnProperty.call(node, name)) {
1496
+ /* c8 ignore next 2 */
1497
+ continue
1498
+ }
1499
+ if (name === 'parent' || name === 'proxyCache') continue
1500
+ let value = node[name];
1501
+
1502
+ if (Array.isArray(value)) {
1503
+ let fixedArray = [];
1504
+ fixed[name] = fixedArray;
1505
+ for (let i = 0; i < value.length; i++) {
1506
+ let item = value[i];
1507
+ if (typeof item === 'object' && item.toJSON) {
1508
+ if (item.toJSON === Node.prototype.toJSON) {
1509
+ queue.push([item, fixedArray, i]);
1510
+ } else {
1511
+ fixedArray[i] = item.toJSON(null, inputs);
1512
+ }
1513
+ } else {
1514
+ fixedArray[i] = item;
1515
+ }
1516
+ }
1517
+ } else if (typeof value === 'object' && value.toJSON) {
1518
+ if (value.toJSON === Node.prototype.toJSON) {
1519
+ queue.push([value, fixed, name]);
1415
1520
  } else {
1416
- return i
1521
+ fixed[name] = value.toJSON(null, inputs);
1417
1522
  }
1418
- });
1419
- } else if (typeof value === 'object' && value.toJSON) {
1420
- fixed[name] = value.toJSON(null, inputs);
1421
- } else if (name === 'source') {
1422
- if (value == null) continue
1423
- let inputId = inputs.get(value.input);
1424
- if (inputId == null) {
1425
- inputId = inputsNextIndex;
1426
- inputs.set(value.input, inputsNextIndex);
1427
- inputsNextIndex++;
1523
+ } else if (name === 'source') {
1524
+ if (value == null) continue
1525
+ let inputId = inputs.get(value.input);
1526
+ if (inputId == null) {
1527
+ inputId = inputs.size;
1528
+ inputs.set(value.input, inputId);
1529
+ }
1530
+ fixed[name] = {
1531
+ end: value.end,
1532
+ inputId,
1533
+ start: value.start
1534
+ };
1535
+ } else {
1536
+ fixed[name] = value;
1428
1537
  }
1429
- fixed[name] = {
1430
- end: value.end,
1431
- inputId,
1432
- start: value.start
1433
- };
1434
- } else {
1435
- fixed[name] = value;
1436
1538
  }
1437
1539
  }
1438
1540
 
1541
+ let fixed = holderOfRoot[0];
1439
1542
  if (emitInputs) {
1440
1543
  fixed.inputs = [...inputs.keys()].map(input => input.toJSON());
1441
1544
  }
@@ -1539,18 +1642,25 @@ function requireContainer$1 () {
1539
1642
  let AtRule, parse, Root, Rule;
1540
1643
 
1541
1644
  function cleanSource(nodes) {
1542
- return nodes.map(i => {
1543
- if (i.nodes) i.nodes = cleanSource(i.nodes);
1544
- delete i.source;
1545
- return i
1546
- })
1645
+ let stack = nodes.slice();
1646
+ while (stack.length > 0) {
1647
+ let node = stack.pop();
1648
+ delete node.source;
1649
+ if (node.nodes) {
1650
+ node.nodes = node.nodes.slice();
1651
+ for (let i of node.nodes) stack.push(i);
1652
+ }
1653
+ }
1654
+ return nodes.slice()
1547
1655
  }
1548
1656
 
1549
1657
  function markTreeDirty(node) {
1550
- node[isClean] = false;
1551
- if (node.proxyOf.nodes) {
1552
- for (let i of node.proxyOf.nodes) {
1553
- markTreeDirty(i);
1658
+ let stack = [node];
1659
+ while (stack.length > 0) {
1660
+ let next = stack.pop();
1661
+ next[isClean] = false;
1662
+ if (next.proxyOf.nodes) {
1663
+ for (let i of next.proxyOf.nodes) stack.push(i);
1554
1664
  }
1555
1665
  }
1556
1666
  }
@@ -1578,9 +1688,18 @@ function requireContainer$1 () {
1578
1688
  }
1579
1689
 
1580
1690
  cleanRaws(keepBetween) {
1581
- super.cleanRaws(keepBetween);
1582
- if (this.nodes) {
1583
- for (let node of this.nodes) node.cleanRaws(keepBetween);
1691
+ let stack = [this];
1692
+ while (stack.length > 0) {
1693
+ let node = stack.pop();
1694
+ if (node !== this && node.cleanRaws !== Container.prototype.cleanRaws) {
1695
+ // Subclass with own logic; let it handle its subtree
1696
+ node.cleanRaws(keepBetween);
1697
+ continue
1698
+ }
1699
+ Node.prototype.cleanRaws.call(node, keepBetween);
1700
+ if (node.nodes) {
1701
+ for (let child of node.nodes) stack.push(child);
1702
+ }
1584
1703
  }
1585
1704
  }
1586
1705
 
@@ -1840,19 +1959,48 @@ function requireContainer$1 () {
1840
1959
  }
1841
1960
 
1842
1961
  walk(callback) {
1843
- return this.each((child, i) => {
1962
+ if (!this.proxyOf.nodes) return undefined
1963
+
1964
+ // An explicit stack instead of recursive `each()` calls to survive
1965
+ // deeply nested trees. Each frame keeps a live `indexes` slot, so
1966
+ // insertion and removal during the walk behave like `each()`: the
1967
+ // slot stays at the current child until its subtree is finished.
1968
+ let stack = [{ iterator: this.getIterator(), node: this.proxyOf }];
1969
+
1970
+ while (stack.length > 0) {
1971
+ let { iterator, node } = stack[stack.length - 1];
1972
+ let index = node.indexes[iterator];
1973
+
1974
+ if (index >= node.proxyOf.nodes.length) {
1975
+ delete node.indexes[iterator];
1976
+ stack.pop();
1977
+ let parent = stack[stack.length - 1];
1978
+ // Finish the parent’s step for the child subtree we just left
1979
+ if (parent) parent.node.indexes[parent.iterator] += 1;
1980
+ continue
1981
+ }
1982
+
1983
+ let child = node.proxyOf.nodes[index];
1844
1984
  let result;
1845
1985
  try {
1846
- result = callback(child, i);
1986
+ result = callback(child, index);
1847
1987
  } catch (e) {
1848
1988
  throw child.addToError(e)
1849
1989
  }
1850
- if (result !== false && child.walk) {
1851
- result = child.walk(callback);
1990
+ if (result === false) {
1991
+ for (let opened of stack) {
1992
+ delete opened.node.indexes[opened.iterator];
1993
+ }
1994
+ return false
1995
+ }
1996
+ if (child.walk && child.proxyOf.nodes) {
1997
+ stack.push({ iterator: child.getIterator(), node: child });
1998
+ } else {
1999
+ node.indexes[iterator] += 1;
1852
2000
  }
2001
+ }
1853
2002
 
1854
- return result
1855
- })
2003
+ return undefined
1856
2004
  }
1857
2005
 
1858
2006
  walkAtRules(name, callback) {
@@ -1955,24 +2103,26 @@ function requireContainer$1 () {
1955
2103
 
1956
2104
  /* c8 ignore start */
1957
2105
  Container.rebuild = node => {
1958
- if (node.type === 'atrule') {
1959
- Object.setPrototypeOf(node, AtRule.prototype);
1960
- } else if (node.type === 'rule') {
1961
- Object.setPrototypeOf(node, Rule.prototype);
1962
- } else if (node.type === 'decl') {
1963
- Object.setPrototypeOf(node, Declaration.prototype);
1964
- } else if (node.type === 'comment') {
1965
- Object.setPrototypeOf(node, Comment.prototype);
1966
- } else if (node.type === 'root') {
1967
- Object.setPrototypeOf(node, Root.prototype);
1968
- }
2106
+ let stack = [node];
2107
+ while (stack.length > 0) {
2108
+ let next = stack.pop();
2109
+ if (next.type === 'atrule') {
2110
+ Object.setPrototypeOf(next, AtRule.prototype);
2111
+ } else if (next.type === 'rule') {
2112
+ Object.setPrototypeOf(next, Rule.prototype);
2113
+ } else if (next.type === 'decl') {
2114
+ Object.setPrototypeOf(next, Declaration.prototype);
2115
+ } else if (next.type === 'comment') {
2116
+ Object.setPrototypeOf(next, Comment.prototype);
2117
+ } else if (next.type === 'root') {
2118
+ Object.setPrototypeOf(next, Root.prototype);
2119
+ }
1969
2120
 
1970
- node[my] = true;
2121
+ next[my] = true;
1971
2122
 
1972
- if (node.nodes) {
1973
- node.nodes.forEach(child => {
1974
- Container.rebuild(child);
1975
- });
2123
+ if (next.nodes) {
2124
+ for (let child of next.nodes) stack.push(child);
2125
+ }
1976
2126
  }
1977
2127
  };
1978
2128
  /* c8 ignore stop */
@@ -2094,7 +2244,7 @@ function requirePreviousMap () {
2094
2244
  hasRequiredPreviousMap = 1;
2095
2245
 
2096
2246
  let { existsSync, readFileSync } = require$$2;
2097
- let { dirname, join } = require$$2;
2247
+ let { dirname, isAbsolute, join, relative, sep } = require$$2;
2098
2248
  let { SourceMapConsumer, SourceMapGenerator } = require$$2;
2099
2249
 
2100
2250
  function fromBase64(str) {
@@ -2178,11 +2328,20 @@ function requirePreviousMap () {
2178
2328
  }
2179
2329
 
2180
2330
  loadFile(path, cssFile, trusted) {
2181
- /* c8 ignore next 5 */
2182
2331
  if (!trusted && !this.unsafeMap) {
2183
2332
  if (!/\.map$/i.test(path)) {
2184
2333
  return undefined
2185
2334
  }
2335
+ if (cssFile) {
2336
+ let relativePath = relative(dirname(cssFile), path);
2337
+ if (
2338
+ relativePath === '..' ||
2339
+ relativePath.startsWith('..' + sep) ||
2340
+ isAbsolute(relativePath)
2341
+ ) {
2342
+ return undefined
2343
+ }
2344
+ }
2186
2345
  }
2187
2346
  this.root = dirname(path);
2188
2347
  if (existsSync(path)) {
@@ -2473,10 +2632,16 @@ function requireInput () {
2473
2632
 
2474
2633
  let to;
2475
2634
  if (typeof endLine === 'number') {
2476
- to = consumer.originalPositionFor({
2635
+ let toPosition = consumer.originalPositionFor({
2477
2636
  column: endColumn - 1,
2478
2637
  line: endLine
2479
2638
  });
2639
+ // The source map may not have a mapping that covers the end position
2640
+ // (`originalPositionFor()` then returns `null` for `line`/`column`
2641
+ // instead of omitting them). Treat that the same as not requesting
2642
+ // an end position at all, so `endLine`/`endColumn` stay a consistent
2643
+ // `undefined` pair instead of a mix of `null` and a bogus number.
2644
+ if (toPosition.source) to = toPosition;
2480
2645
  }
2481
2646
 
2482
2647
  let fromUrl;
@@ -2558,6 +2723,19 @@ function requireRoot () {
2558
2723
  }
2559
2724
 
2560
2725
  normalize(child, sample, type) {
2726
+ let keepBefore = new Set();
2727
+ for (let node of Array.isArray(child) ? child : [child]) {
2728
+ if (
2729
+ node &&
2730
+ typeof node === 'object' &&
2731
+ !node.parent &&
2732
+ node.raws &&
2733
+ typeof node.raws.before !== 'undefined'
2734
+ ) {
2735
+ keepBefore.add(node.raws);
2736
+ }
2737
+ }
2738
+
2561
2739
  let nodes = super.normalize(child);
2562
2740
 
2563
2741
  if (sample) {
@@ -2569,7 +2747,9 @@ function requireRoot () {
2569
2747
  }
2570
2748
  } else if (this.first !== sample) {
2571
2749
  for (let node of nodes) {
2572
- node.raws.before = sample.raws.before;
2750
+ if (!keepBefore.has(node.raws)) {
2751
+ node.raws.before = sample.raws.before;
2752
+ }
2573
2753
  }
2574
2754
  }
2575
2755
  }
@@ -2724,31 +2904,24 @@ function requireFromJSON () {
2724
2904
  let Root = requireRoot();
2725
2905
  let Rule = requireRule();
2726
2906
 
2727
- function fromJSON(json, inputs) {
2728
- if (Array.isArray(json)) return json.map(n => fromJSON(n))
2729
-
2730
- let { inputs: ownInputs, ...defaults } = json;
2731
- if (ownInputs) {
2732
- inputs = [];
2733
- for (let input of ownInputs) {
2734
- let inputHydrated = { ...input, __proto__: Input.prototype };
2735
- if (inputHydrated.map) {
2736
- inputHydrated.map = {
2737
- ...inputHydrated.map,
2738
- __proto__: PreviousMap.prototype
2739
- };
2740
- }
2741
- inputs.push(inputHydrated);
2907
+ function hydrateInputs(json, inputs) {
2908
+ if (!json.inputs) return inputs
2909
+ return json.inputs.map(input => {
2910
+ let inputHydrated = { ...input, __proto__: Input.prototype };
2911
+ if (inputHydrated.map) {
2912
+ inputHydrated.map = {
2913
+ ...inputHydrated.map,
2914
+ __proto__: PreviousMap.prototype
2915
+ };
2742
2916
  }
2743
- }
2744
- // Rehydrate children separately and attach them after construction.
2745
- // Passing them through the container constructor would re-run insertion
2746
- // spacing normalization and overwrite each child's own `raws.before`.
2747
- let nodes;
2748
- if (defaults.nodes) {
2749
- nodes = json.nodes.map(n => fromJSON(n, inputs));
2750
- delete defaults.nodes;
2751
- }
2917
+ return inputHydrated
2918
+ })
2919
+ }
2920
+
2921
+ function constructNode(json, inputs, children) {
2922
+ let defaults = { ...json };
2923
+ delete defaults.inputs;
2924
+ delete defaults.nodes;
2752
2925
  if (defaults.source) {
2753
2926
  let { inputId, ...source } = defaults.source;
2754
2927
  defaults.source = source;
@@ -2772,14 +2945,60 @@ function requireFromJSON () {
2772
2945
  throw new Error('Unknown node type: ' + json.type)
2773
2946
  }
2774
2947
 
2775
- if (nodes) {
2776
- node.nodes = nodes;
2777
- for (let child of nodes) child.parent = node;
2948
+ // Rehydrated children are attached after construction. Passing them
2949
+ // through the container constructor would re-run insertion spacing
2950
+ // normalization and overwrite each child's own `raws.before`.
2951
+ if (children) {
2952
+ node.nodes = children;
2953
+ for (let child of children) child.parent = node;
2778
2954
  }
2779
2955
 
2780
2956
  return node
2781
2957
  }
2782
2958
 
2959
+ function fromJSON(json, inputs) {
2960
+ if (Array.isArray(json)) return json.map(n => fromJSON(n))
2961
+
2962
+ // An explicit stack instead of recursive calls to survive deeply
2963
+ // nested trees. Children are rehydrated before their parent node
2964
+ // is constructed.
2965
+ let result;
2966
+ let stack = [
2967
+ { childIndex: 0, children: [], inputs: hydrateInputs(json, inputs), json }
2968
+ ];
2969
+
2970
+ while (stack.length > 0) {
2971
+ let frame = stack[stack.length - 1];
2972
+ let jsonNodes = frame.json.nodes;
2973
+
2974
+ if (jsonNodes && frame.childIndex < jsonNodes.length) {
2975
+ let childJson = jsonNodes[frame.childIndex];
2976
+ frame.childIndex += 1;
2977
+ stack.push({
2978
+ childIndex: 0,
2979
+ children: [],
2980
+ inputs: hydrateInputs(childJson, frame.inputs),
2981
+ json: childJson
2982
+ });
2983
+ continue
2984
+ }
2985
+
2986
+ stack.pop();
2987
+ let node = constructNode(
2988
+ frame.json,
2989
+ frame.inputs,
2990
+ jsonNodes ? frame.children : undefined
2991
+ );
2992
+ if (stack.length > 0) {
2993
+ stack[stack.length - 1].children.push(node);
2994
+ } else {
2995
+ result = node;
2996
+ }
2997
+ }
2998
+
2999
+ return result
3000
+ }
3001
+
2783
3002
  fromJSON_1 = fromJSON;
2784
3003
  fromJSON.default = fromJSON;
2785
3004
  return fromJSON_1;
@@ -4344,8 +4563,14 @@ function requireLazyResult () {
4344
4563
  }
4345
4564
 
4346
4565
  function cleanMarks(node) {
4347
- node[isClean] = false;
4348
- if (node.nodes) node.nodes.forEach(i => cleanMarks(i));
4566
+ let stack = [node];
4567
+ while (stack.length > 0) {
4568
+ let next = stack.pop();
4569
+ next[isClean] = false;
4570
+ if (next.nodes) {
4571
+ for (let i of next.nodes) stack.push(i);
4572
+ }
4573
+ }
4349
4574
  return node
4350
4575
  }
4351
4576
 
@@ -4776,21 +5001,57 @@ function requireLazyResult () {
4776
5001
  }
4777
5002
 
4778
5003
  walkSync(node) {
5004
+ // An explicit stack like in async `visitTick()` to survive deeply
5005
+ // nested trees. Unlike `visitTick()`, nodes are marked clean only
5006
+ // on entering, so a node dirtied by its own visitors is revisited
5007
+ // on the next pass.
4779
5008
  node[isClean] = true;
4780
- let events = getEvents(node);
4781
- for (let event of events) {
4782
- if (event === CHILDREN) {
4783
- if (node.nodes) {
4784
- node.each(child => {
4785
- if (!child[isClean]) this.walkSync(child);
4786
- });
5009
+ let stack = [{ eventIndex: 0, events: getEvents(node), iterator: 0, node }];
5010
+
5011
+ while (stack.length > 0) {
5012
+ let visit = stack[stack.length - 1];
5013
+ let visitNode = visit.node;
5014
+
5015
+ if (visit.iterator !== 0) {
5016
+ let iterator = visit.iterator;
5017
+ let child;
5018
+ let descended = false;
5019
+ while ((child = visitNode.nodes[visitNode.indexes[iterator]])) {
5020
+ visitNode.indexes[iterator] += 1;
5021
+ if (!child[isClean]) {
5022
+ child[isClean] = true;
5023
+ stack.push({
5024
+ eventIndex: 0,
5025
+ events: getEvents(child),
5026
+ iterator: 0,
5027
+ node: child
5028
+ });
5029
+ descended = true;
5030
+ break
5031
+ }
4787
5032
  }
4788
- } else {
4789
- let visitors = this.listeners[event];
4790
- if (visitors) {
4791
- if (this.visitSync(visitors, node.toProxy())) return
5033
+ if (descended) continue
5034
+ visit.iterator = 0;
5035
+ delete visitNode.indexes[iterator];
5036
+ }
5037
+
5038
+ if (visit.eventIndex < visit.events.length) {
5039
+ let event = visit.events[visit.eventIndex];
5040
+ visit.eventIndex += 1;
5041
+ if (event === CHILDREN) {
5042
+ if (visitNode.nodes && visitNode.nodes.length) {
5043
+ visit.iterator = visitNode.getIterator();
5044
+ }
5045
+ } else {
5046
+ let visitors = this.listeners[event];
5047
+ if (visitors) {
5048
+ if (this.visitSync(visitors, visitNode.toProxy())) stack.pop();
5049
+ }
4792
5050
  }
5051
+ continue
4793
5052
  }
5053
+
5054
+ stack.pop();
4794
5055
  }
4795
5056
  }
4796
5057
 
@@ -4970,7 +5231,7 @@ function requireProcessor () {
4970
5231
 
4971
5232
  class Processor {
4972
5233
  constructor(plugins = []) {
4973
- this.version = '8.5.16';
5234
+ this.version = '8.5.19';
4974
5235
  this.plugins = this.normalize(plugins);
4975
5236
  }
4976
5237
 
@@ -11579,9 +11840,10 @@ function serializeStylesheet(ast, options) {
11579
11840
  }
11580
11841
  return;
11581
11842
  }
11582
- if (type === "end" && result === "}" && node?.raws?.semicolon) {
11843
+ if (type === "end" && result === "}" && node?.raws?.semicolon && (node.type === "rule" || node.type === "atrule")) {
11844
+ const lastChild = node.nodes?.[node.nodes.length - 1];
11583
11845
  const lastItemIdx = cssParts.length - 2;
11584
- if (lastItemIdx >= 0 && cssParts[lastItemIdx]) {
11846
+ if (lastChild?.type === "decl" && lastItemIdx >= 0 && cssParts[lastItemIdx]) {
11585
11847
  cssParts[lastItemIdx] = cssParts[lastItemIdx].slice(0, -1);
11586
11848
  }
11587
11849
  }
@@ -11756,13 +12018,15 @@ function createDocument(html) {
11756
12018
  const document = parseDocument(html, { decodeEntities: false });
11757
12019
  extendDocument(document);
11758
12020
  extendElement(Element.prototype);
11759
- let beastiesContainer = document.querySelector("[data-beasties-container]");
11760
- if (!beastiesContainer) {
12021
+ let beastiesContainers = document.querySelectorAll("[data-beasties-container]");
12022
+ if (!beastiesContainers.length) {
11761
12023
  document.documentElement?.setAttribute("data-beasties-container", "");
11762
- beastiesContainer = document.documentElement || document;
12024
+ beastiesContainers = [document.documentElement || document];
12025
+ }
12026
+ document.beastiesContainers = beastiesContainers;
12027
+ for (const container of beastiesContainers) {
12028
+ buildCache(container);
11763
12029
  }
11764
- document.beastiesContainer = beastiesContainer;
11765
- buildCache(beastiesContainer);
11766
12030
  return document;
11767
12031
  }
11768
12032
  function serializeDocument(document) {
@@ -11940,6 +12204,11 @@ function extendDocument(document) {
11940
12204
  }
11941
12205
  return selectAll(sel, this);
11942
12206
  }
12207
+ },
12208
+ beastiesContainer: {
12209
+ get() {
12210
+ return this.beastiesContainers?.[0];
12211
+ }
11943
12212
  }
11944
12213
  });
11945
12214
  }
@@ -12227,6 +12496,9 @@ class Beasties {
12227
12496
  * Fetch CSS content for a linked stylesheet
12228
12497
  */
12229
12498
  async fetchStylesheet(link, document) {
12499
+ if (link.hasAttribute("data-beasties-skip")) {
12500
+ return void 0;
12501
+ }
12230
12502
  const href = link.getAttribute("href");
12231
12503
  const pathname = href?.split("?")[0]?.split("#")[0];
12232
12504
  if (!pathname?.endsWith(".css")) {
@@ -12363,7 +12635,7 @@ class Beasties {
12363
12635
  return;
12364
12636
  const name = style.$$name ? style.$$name.replace(LEADING_SLASH_RE, "") : "inline CSS";
12365
12637
  const options = this.options;
12366
- const beastiesContainer = document.beastiesContainer;
12638
+ const beastiesContainers = document.beastiesContainers;
12367
12639
  let keyframesMode = options.keyframes ?? "critical";
12368
12640
  if (keyframesMode === true)
12369
12641
  keyframesMode = "all";
@@ -12444,7 +12716,7 @@ class Beasties {
12444
12716
  if (!sel)
12445
12717
  return false;
12446
12718
  try {
12447
- return beastiesContainer.exists(sel);
12719
+ return beastiesContainers.some((container) => container.exists(sel));
12448
12720
  } catch (e) {
12449
12721
  failedSelectors.push(`${sel} -> ${e.message || e.toString()}`);
12450
12722
  return false;