chore: remove `node.parent` and `node.prev` (#14447)

* make get_possible_element_siblings non-recursive

* treat slots as blocks

* simplify

* simplify

* add test

* changeset

* chore: remove node.parent and node.prev

* simplify
pull/14449/head
Rich Harris 1 month ago committed by GitHub
parent 610bc98f66
commit 1a8aab0e38
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -120,7 +120,6 @@ function to_public_ast(source, ast, modern) {
if (modern) { if (modern) {
const clean = (/** @type {any} */ node) => { const clean = (/** @type {any} */ node) => {
delete node.metadata; delete node.metadata;
delete node.parent;
}; };
ast.options?.attributes.forEach((attribute) => { ast.options?.attributes.forEach((attribute) => {

@ -45,8 +45,6 @@ export function convert(source, ast) {
return /** @type {Legacy.LegacyRoot} */ ( return /** @type {Legacy.LegacyRoot} */ (
walk(root, null, { walk(root, null, {
_(node, { next }) { _(node, { next }) {
// @ts-ignore
delete node.parent;
// @ts-ignore // @ts-ignore
delete node.metadata; delete node.metadata;
next(); next();
@ -62,8 +60,6 @@ export function convert(source, ast) {
idx = node.fragment.nodes.length; idx = node.fragment.nodes.length;
} }
// @ts-ignore
delete options.__raw__.parent;
node.fragment.nodes.splice(idx, 0, /** @type {any} */ (options).__raw__); node.fragment.nodes.splice(idx, 0, /** @type {any} */ (options).__raw__);
} }
@ -85,15 +81,11 @@ export function convert(source, ast) {
} }
if (instance) { if (instance) {
// @ts-ignore
delete instance.parent;
// @ts-ignore // @ts-ignore
delete instance.attributes; delete instance.attributes;
} }
if (module) { if (module) {
// @ts-ignore
delete module.parent;
// @ts-ignore // @ts-ignore
delete module.attributes; delete module.attributes;
} }

@ -262,30 +262,12 @@ export class Parser {
} }
/** /**
* @template T * @template {AST.Fragment['nodes'][number]} T
* @param {Omit<T, 'prev' | 'parent'>} node * @param {T} node
* @returns {T} * @returns {T}
*/ */
append(node) { append(node) {
const current = this.current(); this.fragments.at(-1)?.nodes.push(node);
const fragment = this.fragments.at(-1);
Object.defineProperties(node, {
prev: {
enumerable: false,
value: fragment?.nodes.at(-1) ?? null
},
parent: {
enumerable: false,
configurable: true,
value: current
}
});
// @ts-expect-error
fragment.nodes.push(node);
// @ts-expect-error
return node; return node;
} }
} }

@ -84,7 +84,6 @@ export function read_script(parser, start, attributes) {
end: parser.index, end: parser.index,
context, context,
content: ast, content: ast,
parent: null,
// @ts-ignore // @ts-ignore
attributes attributes
}; };

@ -56,7 +56,6 @@ export default function element(parser) {
const data = parser.read_until(regex_closing_comment); const data = parser.read_until(regex_closing_comment);
parser.eat('-->', true); parser.eat('-->', true);
/** @type {ReturnType<typeof parser.append<AST.Comment>>} */
parser.append({ parser.append({
type: 'Comment', type: 'Comment',
start, start,
@ -153,8 +152,7 @@ export default function element(parser) {
scoped: false, scoped: false,
has_spread: false, has_spread: false,
path: [] path: []
}, }
parent: null
} }
: /** @type {ElementLike} */ ({ : /** @type {ElementLike} */ ({
type, type,
@ -163,7 +161,6 @@ export default function element(parser) {
name, name,
attributes: [], attributes: [],
fragment: create_fragment(true), fragment: create_fragment(true),
parent: null,
metadata: { metadata: {
// unpopulated at first, differs between types // unpopulated at first, differs between types
} }
@ -348,8 +345,7 @@ export default function element(parser) {
end, end,
type: 'Text', type: 'Text',
data, data,
raw: data, raw: data
parent: null
}; };
element.fragment.nodes.push(node); element.fragment.nodes.push(node);
@ -422,8 +418,7 @@ function read_static_attribute(parser) {
end: quoted ? parser.index - 1 : parser.index, end: quoted ? parser.index - 1 : parser.index,
type: 'Text', type: 'Text',
raw: raw, raw: raw,
data: decode_character_references(raw, true), data: decode_character_references(raw, true)
parent: null
} }
]; ];
} }
@ -457,7 +452,6 @@ function read_attribute(parser) {
start, start,
end: parser.index, end: parser.index,
expression, expression,
parent: null,
metadata: { metadata: {
expression: create_expression_metadata() expression: create_expression_metadata()
} }
@ -486,7 +480,6 @@ function read_attribute(parser) {
type: 'Identifier', type: 'Identifier',
name name
}, },
parent: null,
metadata: { metadata: {
expression: create_expression_metadata() expression: create_expression_metadata()
} }
@ -531,7 +524,6 @@ function read_attribute(parser) {
name: directive_name, name: directive_name,
modifiers: /** @type {Array<'important'>} */ (modifiers), modifiers: /** @type {Array<'important'>} */ (modifiers),
value, value,
parent: null,
metadata: { metadata: {
expression: create_expression_metadata() expression: create_expression_metadata()
} }
@ -556,19 +548,20 @@ function read_attribute(parser) {
} }
/** @type {Directive} */ /** @type {Directive} */
// @ts-expect-error TODO can't figure out this error
const directive = { const directive = {
start, start,
end, end,
type, type,
name: directive_name, name: directive_name,
modifiers,
expression, expression,
metadata: { metadata: {
expression: create_expression_metadata() expression: create_expression_metadata()
} }
}; };
// @ts-expect-error we do this separately from the declaration to avoid upsetting typescript
directive.modifiers = modifiers;
if (directive.type === 'TransitionDirective') { if (directive.type === 'TransitionDirective') {
const direction = name.slice(0, colon_index); const direction = name.slice(0, colon_index);
directive.intro = direction === 'in' || direction === 'transition'; directive.intro = direction === 'in' || direction === 'transition';
@ -623,8 +616,7 @@ function read_attribute_value(parser) {
end: parser.index - 1, end: parser.index - 1,
type: 'Text', type: 'Text',
raw: '', raw: '',
data: '', data: ''
parent: null
} }
]; ];
} }
@ -681,8 +673,7 @@ function read_sequence(parser, done, location) {
end: -1, end: -1,
type: 'Text', type: 'Text',
raw: '', raw: '',
data: '', data: ''
parent: null
}; };
/** @type {Array<AST.Text | AST.ExpressionTag>} */ /** @type {Array<AST.Text | AST.ExpressionTag>} */
@ -729,7 +720,6 @@ function read_sequence(parser, done, location) {
start: index, start: index,
end: parser.index, end: parser.index,
expression, expression,
parent: null,
metadata: { metadata: {
expression: create_expression_metadata() expression: create_expression_metadata()
} }
@ -742,8 +732,7 @@ function read_sequence(parser, done, location) {
end: -1, end: -1,
type: 'Text', type: 'Text',
raw: '', raw: '',
data: '', data: ''
parent: null
}; };
} else { } else {
current_chunk.raw += parser.template[parser.index++]; current_chunk.raw += parser.template[parser.index++];

@ -33,7 +33,6 @@ export default function tag(parser) {
parser.allow_whitespace(); parser.allow_whitespace();
parser.eat('}', true); parser.eat('}', true);
/** @type {ReturnType<typeof parser.append<AST.ExpressionTag>>} */
parser.append({ parser.append({
type: 'ExpressionTag', type: 'ExpressionTag',
start, start,
@ -53,7 +52,7 @@ function open(parser) {
if (parser.eat('if')) { if (parser.eat('if')) {
parser.require_whitespace(); parser.require_whitespace();
/** @type {ReturnType<typeof parser.append<AST.IfBlock>>} */ /** @type {AST.IfBlock} */
const block = parser.append({ const block = parser.append({
type: 'IfBlock', type: 'IfBlock',
elseif: false, elseif: false,
@ -174,7 +173,7 @@ function open(parser) {
parser.eat('}', true); parser.eat('}', true);
/** @type {ReturnType<typeof parser.append<AST.EachBlock>>} */ /** @type {AST.EachBlock} */
const block = parser.append({ const block = parser.append({
type: 'EachBlock', type: 'EachBlock',
start, start,
@ -198,7 +197,7 @@ function open(parser) {
const expression = read_expression(parser); const expression = read_expression(parser);
parser.allow_whitespace(); parser.allow_whitespace();
/** @type {ReturnType<typeof parser.append<AST.AwaitBlock>>} */ /** @type {AST.AwaitBlock} */
const block = parser.append({ const block = parser.append({
type: 'AwaitBlock', type: 'AwaitBlock',
start, start,
@ -252,7 +251,7 @@ function open(parser) {
parser.eat('}', true); parser.eat('}', true);
/** @type {ReturnType<typeof parser.append<AST.KeyBlock>>} */ /** @type {AST.KeyBlock} */
const block = parser.append({ const block = parser.append({
type: 'KeyBlock', type: 'KeyBlock',
start, start,
@ -303,7 +302,7 @@ function open(parser) {
parser.allow_whitespace(); parser.allow_whitespace();
parser.eat('}', true); parser.eat('}', true);
/** @type {ReturnType<typeof parser.append<AST.SnippetBlock>>} */ /** @type {AST.SnippetBlock} */
const block = parser.append({ const block = parser.append({
type: 'SnippetBlock', type: 'SnippetBlock',
start, start,
@ -355,7 +354,7 @@ function next(parser) {
let elseif_start = start - 1; let elseif_start = start - 1;
while (parser.template[elseif_start] !== '{') elseif_start -= 1; while (parser.template[elseif_start] !== '{') elseif_start -= 1;
/** @type {ReturnType<typeof parser.append<AST.IfBlock>>} */ /** @type {AST.IfBlock} */
const child = parser.append({ const child = parser.append({
start: elseif_start, start: elseif_start,
end: -1, end: -1,
@ -499,7 +498,6 @@ function special(parser) {
parser.allow_whitespace(); parser.allow_whitespace();
parser.eat('}', true); parser.eat('}', true);
/** @type {ReturnType<typeof parser.append<AST.HtmlTag>>} */
parser.append({ parser.append({
type: 'HtmlTag', type: 'HtmlTag',
start, start,
@ -537,7 +535,6 @@ function special(parser) {
parser.eat('}', true); parser.eat('}', true);
} }
/** @type {ReturnType<typeof parser.append<AST.DebugTag>>} */
parser.append({ parser.append({
type: 'DebugTag', type: 'DebugTag',
start, start,
@ -570,7 +567,6 @@ function special(parser) {
parser.eat('}', true); parser.eat('}', true);
/** @type {ReturnType<typeof parser.append<AST.ConstTag>>} */
parser.append({ parser.append({
type: 'ConstTag', type: 'ConstTag',
start, start,
@ -601,15 +597,15 @@ function special(parser) {
parser.allow_whitespace(); parser.allow_whitespace();
parser.eat('}', true); parser.eat('}', true);
/** @type {ReturnType<typeof parser.append<AST.RenderTag>>} */
parser.append({ parser.append({
type: 'RenderTag', type: 'RenderTag',
start, start,
end: parser.index, end: parser.index,
expression: expression, expression: /** @type {AST.RenderTag['expression']} */ (expression),
metadata: { metadata: {
dynamic: false, dynamic: false,
args_with_call_expression: new Set() args_with_call_expression: new Set(),
path: []
} }
}); });
} }

@ -12,7 +12,7 @@ export default function text(parser) {
data += parser.template[parser.index++]; data += parser.template[parser.index++];
} }
/** @type {ReturnType<typeof parser.append<AST.Text>>} */ /** @type {AST.Text} */
parser.append({ parser.append({
type: 'Text', type: 'Text',
start, start,

@ -758,8 +758,7 @@ export function analyze_component(root, source, options) {
data: ` ${analysis.css.hash}`, data: ` ${analysis.css.hash}`,
raw: ` ${analysis.css.hash}`, raw: ` ${analysis.css.hash}`,
start: -1, start: -1,
end: -1, end: -1
parent: null
}; };
if (Array.isArray(class_attribute.value)) { if (Array.isArray(class_attribute.value)) {
@ -775,7 +774,6 @@ export function analyze_component(root, source, options) {
type: 'Text', type: 'Text',
data: analysis.css.hash, data: analysis.css.hash,
raw: analysis.css.hash, raw: analysis.css.hash,
parent: null,
start: -1, start: -1,
end: -1 end: -1
} }

@ -135,7 +135,6 @@ export function build_element_attributes(node, context) {
type: 'ExpressionTag', type: 'ExpressionTag',
start: -1, start: -1,
end: -1, end: -1,
parent: attribute,
expression: is_checkbox expression: is_checkbox
? b.call( ? b.call(
b.member(attribute.expression, 'includes'), b.member(attribute.expression, 'includes'),
@ -159,7 +158,6 @@ export function build_element_attributes(node, context) {
type: 'ExpressionTag', type: 'ExpressionTag',
start: -1, start: -1,
end: -1, end: -1,
parent: attribute,
expression: attribute.expression, expression: attribute.expression,
metadata: { metadata: {
expression: create_expression_metadata() expression: create_expression_metadata()
@ -376,7 +374,6 @@ function build_class_directives(class_directives, class_attribute) {
type: 'Text', type: 'Text',
start: -1, start: -1,
end: -1, end: -1,
parent: class_attribute,
data: ' ', data: ' ',
raw: ' ' raw: ' '
}); });
@ -386,7 +383,6 @@ function build_class_directives(class_directives, class_attribute) {
type: 'ExpressionTag', type: 'ExpressionTag',
start: -1, start: -1,
end: -1, end: -1,
parent: class_attribute,
expression: b.call( expression: b.call(
b.member(b.call(b.member(b.array(expressions), 'filter'), b.id('Boolean')), b.id('join')), b.member(b.call(b.member(b.array(expressions), 'filter'), b.id('Boolean')), b.id('join')),
b.literal(' ') b.literal(' ')

@ -277,7 +277,6 @@ export function clean_nodes(
trimmed.push({ trimmed.push({
type: 'Comment', type: 'Comment',
data: '', data: '',
parent: first.parent,
start: -1, start: -1,
end: -1 end: -1
}); });

@ -43,7 +43,6 @@ export function create_attribute(name, start, end, value) {
end, end,
name, name,
value, value,
parent: null,
metadata: { metadata: {
expression: create_expression_metadata(), expression: create_expression_metadata(),
delegated: null delegated: null

@ -37,8 +37,6 @@ export namespace AST {
type: string; type: string;
start: number; start: number;
end: number; end: number;
/** @internal This is set during parsing on elements/components/expressions/text (but not attributes etc) */
parent: SvelteNode | null;
} }
export interface Fragment { export interface Fragment {

Loading…
Cancel
Save