(input, visitors, options)
| 3043 | * @param {CssProcessOptions} options process options |
| 3044 | */ |
| 3045 | const grammar = (input, visitors, options) => { |
| 3046 | const { comment } = options; |
| 3047 | const locConverter = options.locConverter || new LocConverter(input); |
| 3048 | useSoaBackend(input, locConverter); |
| 3049 | const recurseBlocks = options.recurseBlocks !== false; |
| 3050 | |
| 3051 | // Babel's `path.skip()`, children-only. Reset per `enter` dispatch. |
| 3052 | let skipFlag = false; |
| 3053 | const visitorCtx = { |
| 3054 | skipChildren() { |
| 3055 | skipFlag = true; |
| 3056 | } |
| 3057 | }; |
| 3058 | |
| 3059 | /** |
| 3060 | * Walk a component-value subtree; children are already materialized. Fetches |
| 3061 | * the node's visitor bucket once (reused for enter + exit) and uses index |
| 3062 | * loops — `for…of` would allocate an iterator per node on this hot path. |
| 3063 | * @param {Node} node component-value root |
| 3064 | * @param {Node | null} parent enclosing node |
| 3065 | */ |
| 3066 | const walkValue = (node, parent) => { |
| 3067 | const ty = _soaTy[_ix(node)]; |
| 3068 | const b = visitors[ty]; |
| 3069 | let skip = false; |
| 3070 | if (b !== undefined && b.enter.length !== 0) { |
| 3071 | skipFlag = false; |
| 3072 | const e = b.enter; |
| 3073 | for (let i = 0; i < e.length; i++) e[i](node, parent, visitorCtx); |
| 3074 | skip = skipFlag; |
| 3075 | skipFlag = false; |
| 3076 | } |
| 3077 | if (!skip && (ty === T_FUNCTION || ty === T_SIMPLE_BLOCK)) { |
| 3078 | const v = /** @type {Node[]} */ (_soaL0[_ix(node)]); |
| 3079 | for (let i = 0; i < v.length; i++) walkValue(v[i], node); |
| 3080 | } |
| 3081 | if (b !== undefined) { |
| 3082 | const x = b.exit; |
| 3083 | for (let i = 0; i < x.length; i++) x[i](node, parent, visitorCtx); |
| 3084 | } |
| 3085 | }; |
| 3086 | |
| 3087 | /** |
| 3088 | * Walk a structural subtree; an at-rule / qualified-rule's block was parsed |
| 3089 | * eagerly (§5.4.4), so its `value` holds the nested rules / declarations. |
| 3090 | * @param {Node} node structural-tree root |
| 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; |
nothing calls this directly
no test coverage detected