| 3091 | * @param {Node | null} parent enclosing node |
| 3092 | */ |
| 3093 | const walkRule = (node, parent) => { |
| 3094 | const i0 = _ix(node); |
| 3095 | const ty = _soaTy[i0]; |
| 3096 | const b = visitors[ty]; |
| 3097 | let skip = false; |
| 3098 | if (b !== undefined && b.enter.length !== 0) { |
| 3099 | skipFlag = false; |
| 3100 | const e = b.enter; |
| 3101 | for (let i = 0; i < e.length; i++) e[i](node, parent, visitorCtx); |
| 3102 | skip = skipFlag; |
| 3103 | skipFlag = false; |
| 3104 | } |
| 3105 | if (!skip) { |
| 3106 | if (ty === T_AT_RULE || ty === T_QUALIFIED_RULE) { |
| 3107 | const p = /** @type {Node[]} */ (_soaL0[i0]); |
| 3108 | for (let i = 0; i < p.length; i++) walkValue(p[i], node); |
| 3109 | if (recurseBlocks) { |
| 3110 | // Declarations then child rules — downstream consumers don't need them strictly interleaved in source order. |
| 3111 | const decls = _soaL1[i0]; |
| 3112 | if (decls) { |
| 3113 | for (let i = 0; i < decls.length; i++) walkRule(decls[i], node); |
| 3114 | } |
| 3115 | const ch = _soaL2[i0]; |
| 3116 | if (ch) for (let i = 0; i < ch.length; i++) walkRule(ch[i], node); |
| 3117 | } |
| 3118 | } else if (ty === T_DECLARATION) { |
| 3119 | const v = /** @type {Node[]} */ (_soaL0[i0]); |
| 3120 | for (let i = 0; i < v.length; i++) walkValue(v[i], node); |
| 3121 | } |
| 3122 | } |
| 3123 | if (b !== undefined) { |
| 3124 | const x = b.exit; |
| 3125 | for (let i = 0; i < x.length; i++) x[i](node, parent, visitorCtx); |
| 3126 | } |
| 3127 | }; |
| 3128 | |
| 3129 | // Stream each top-level node (selected by `as`) to the walker the moment it's |
| 3130 | // consumed, rather than collecting them first — so the whole AST is never |