chore: refactor `to-functions` to be sane

pull/15538/head
paoloricciuti 4 months ago
parent 1c4503c85c
commit e81c669ae0

@ -1,9 +1,7 @@
/** /**
* @import { TemplateOperations } from "../types.js" * @import { TemplateOperations } from "../types.js"
* @import { Namespace } from "#compiler" * @import { ObjectExpression, Identifier, ArrayExpression, Property, Expression, Literal } from "estree"
* @import { CallExpression, Statement, ObjectExpression, Identifier, ArrayExpression, Property, Expression, Literal } from "estree"
*/ */
import { NAMESPACE_SVG, NAMESPACE_MATHML } from '../../../../../constants.js';
import * as b from '../../../../utils/builders.js'; import * as b from '../../../../utils/builders.js';
import { regex_is_valid_identifier } from '../../../patterns.js'; import { regex_is_valid_identifier } from '../../../patterns.js';
import fix_attribute_casing from './fix-attribute-casing.js'; import fix_attribute_casing from './fix-attribute-casing.js';
@ -30,41 +28,42 @@ export function template_to_functions(items) {
} }
for (let instruction of items) { for (let instruction of items) {
// on push element we add the element to the stack, from this moment on every insert will const args = instruction.args ?? [];
// happen on the last element in the stack const last_element_stack = /** @type {Element} */ (elements_stack.at(-1));
if (instruction.kind === 'push_element' && last_current_element) { /**
elements_stack.push(last_current_element); * @param {Expression | null | void} value
continue; * @returns
} */
// we closed one element, we remove it from the stack and eventually revert back function push(value) {
// the namespace to the previous one if (value === undefined) return;
if (instruction.kind === 'pop_element') { if (last_element_stack) {
elements_stack.pop(); insert(last_element_stack, value);
continue; } else {
}
// @ts-expect-error we can't be here if `swap_current_element` but TS doesn't know that
const value = map[instruction.kind](
...[
...(instruction.kind === 'create_element'
? []
: [instruction.kind === 'set_prop' ? last_current_element : elements_stack.at(-1)]),
...(instruction.args ?? [])
]
);
// with set_prop we don't need to do anything else, in all other cases we also need to
// append the element/node/anchor to the current active element or push it in the elements array
if (instruction.kind !== 'set_prop') {
if (elements_stack.length >= 1 && value !== undefined) {
map.insert(/** @type {Element} */ (elements_stack.at(-1)), value);
} else if (value !== undefined) {
elements.elements.push(value); elements.elements.push(value);
} }
// keep track of the last created element (it will be pushed to the stack after the props are set)
if (instruction.kind === 'create_element') {
last_current_element = /** @type {Element} */ (value);
} }
switch (instruction.kind) {
case 'push_element':
elements_stack.push(/** @type {Element} */ (last_current_element));
break;
case 'pop_element':
elements_stack.pop();
last_current_element = elements_stack.at(-1);
break;
case 'create_element':
last_current_element = create_element(args[0]);
push(last_current_element);
break;
case 'create_text':
push(create_text(last_element_stack, args[0]));
break;
case 'create_anchor':
push(create_anchor(last_element_stack, args[0]));
break;
case 'set_prop':
set_prop(/** @type {Element} */ (last_current_element), args[0], args[1]);
break;
} }
} }
@ -166,17 +165,9 @@ function set_prop(element, prop, value) {
/** /**
* *
* @param {Element} element * @param {Element} element
* @param {Element} child * @param {Expression | null} child
*/ */
function insert(element, child) { function insert(element, child) {
const c = get_or_create_prop(element, 'c', b.array([])); const c = get_or_create_prop(element, 'c', b.array([]));
/** @type {ArrayExpression} */ (c.value).elements.push(child); /** @type {ArrayExpression} */ (c.value).elements.push(child);
} }
let map = {
create_element,
create_text,
create_anchor,
set_prop,
insert
};

Loading…
Cancel
Save