From 0b598e4044ac765598452e9c29f1507735fb310c Mon Sep 17 00:00:00 2001 From: Mateusz Kadlubowski Date: Sat, 7 Dec 2024 18:36:12 +0800 Subject: [PATCH 01/12] add missing `SvelteBoundary` in `ElementLike` --- packages/svelte/src/compiler/types/template.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/svelte/src/compiler/types/template.d.ts b/packages/svelte/src/compiler/types/template.d.ts index a409cf570489..f791b16bacd5 100644 --- a/packages/svelte/src/compiler/types/template.d.ts +++ b/packages/svelte/src/compiler/types/template.d.ts @@ -520,6 +520,7 @@ export type ElementLike = | AST.SlotElement | AST.RegularElement | AST.SvelteBody + | AST.SvelteBoundary | AST.SvelteComponent | AST.SvelteDocument | AST.SvelteElement From 467b741bc457a9251d6a8c2c595fd596f7d3a85c Mon Sep 17 00:00:00 2001 From: Mateusz Kadlubowski Date: Sat, 7 Dec 2024 18:49:58 +0800 Subject: [PATCH 02/12] make union of AST types public and exportable with `AST` namespace --- .../svelte/src/compiler/types/template.d.ts | 93 ++++++++++--------- 1 file changed, 49 insertions(+), 44 deletions(-) diff --git a/packages/svelte/src/compiler/types/template.d.ts b/packages/svelte/src/compiler/types/template.d.ts index f791b16bacd5..70d1124c5b67 100644 --- a/packages/svelte/src/compiler/types/template.d.ts +++ b/packages/svelte/src/compiler/types/template.d.ts @@ -498,51 +498,56 @@ export namespace AST { content: Program; attributes: Attribute[]; } -} -type Tag = AST.ExpressionTag | AST.HtmlTag | AST.ConstTag | AST.DebugTag | AST.RenderTag; - -export type Directive = - | AST.AnimateDirective - | AST.BindDirective - | AST.ClassDirective - | AST.LetDirective - | AST.OnDirective - | AST.StyleDirective - | AST.TransitionDirective - | AST.UseDirective; - -export type Block = AST.EachBlock | AST.IfBlock | AST.AwaitBlock | AST.KeyBlock | AST.SnippetBlock; - -export type ElementLike = - | AST.Component - | AST.TitleElement - | AST.SlotElement - | AST.RegularElement - | AST.SvelteBody - | AST.SvelteBoundary - | AST.SvelteComponent - | AST.SvelteDocument - | AST.SvelteElement - | AST.SvelteFragment - | AST.SvelteHead - | AST.SvelteOptionsRaw - | AST.SvelteSelf - | AST.SvelteWindow - | AST.SvelteBoundary; - -export type TemplateNode = - | AST.Root - | AST.Text - | Tag - | ElementLike - | AST.Attribute - | AST.SpreadAttribute - | Directive - | AST.Comment - | Block; - -export type SvelteNode = Node | TemplateNode | AST.Fragment | Css.Node; + export type Tag = AST.ExpressionTag | AST.HtmlTag | AST.ConstTag | AST.DebugTag | AST.RenderTag; + + export type Directive = + | AST.AnimateDirective + | AST.BindDirective + | AST.ClassDirective + | AST.LetDirective + | AST.OnDirective + | AST.StyleDirective + | AST.TransitionDirective + | AST.UseDirective; + + export type Block = + | AST.EachBlock + | AST.IfBlock + | AST.AwaitBlock + | AST.KeyBlock + | AST.SnippetBlock; + + export type ElementLike = + | AST.Component + | AST.TitleElement + | AST.SlotElement + | AST.RegularElement + | AST.SvelteBody + | AST.SvelteBoundary + | AST.SvelteComponent + | AST.SvelteDocument + | AST.SvelteElement + | AST.SvelteFragment + | AST.SvelteHead + | AST.SvelteOptionsRaw + | AST.SvelteSelf + | AST.SvelteWindow + | AST.SvelteBoundary; + + export type TemplateNode = + | AST.Root + | AST.Text + | Tag + | ElementLike + | AST.Attribute + | AST.SpreadAttribute + | Directive + | AST.Comment + | Block; + + export type SvelteNode = Node | TemplateNode | AST.Fragment | Css.Node; +} declare module 'estree' { export interface BaseNode { From 1d3468ad7717c1b1f84c1a0cf7969c3289d00c8e Mon Sep 17 00:00:00 2001 From: Mateusz Kadlubowski Date: Sat, 7 Dec 2024 19:30:16 +0800 Subject: [PATCH 03/12] apply AST types change to codebase --- packages/svelte/src/compiler/legacy.js | 6 ++--- packages/svelte/src/compiler/migrate/index.js | 10 +++---- .../src/compiler/phases/1-parse/index.js | 4 +-- .../compiler/phases/1-parse/read/script.js | 4 +-- .../src/compiler/phases/1-parse/read/style.js | 4 +-- .../compiler/phases/1-parse/state/element.js | 18 ++++++------- .../phases/2-analyze/css/css-prune.js | 14 +++++----- .../src/compiler/phases/2-analyze/index.js | 8 +++--- .../src/compiler/phases/2-analyze/types.d.ts | 8 +++--- .../visitors/AssignmentExpression.js | 1 - .../phases/2-analyze/visitors/Attribute.js | 4 +-- .../2-analyze/visitors/CallExpression.js | 4 +-- .../2-analyze/visitors/LabeledStatement.js | 4 +-- .../phases/2-analyze/visitors/SnippetBlock.js | 4 +-- .../phases/2-analyze/visitors/shared/a11y.js | 6 ++--- .../2-analyze/visitors/shared/attribute.js | 4 +-- .../2-analyze/visitors/shared/fragment.js | 4 +-- .../3-transform/client/transform-client.js | 10 +++---- .../phases/3-transform/client/types.d.ts | 10 +++---- .../phases/3-transform/client/utils.js | 4 +-- .../client/visitors/BindDirective.js | 4 +-- .../client/visitors/shared/component.js | 4 +-- .../client/visitors/shared/events.js | 4 +-- .../client/visitors/shared/fragment.js | 6 ++--- .../client/visitors/shared/utils.js | 6 ++--- .../3-transform/server/transform-server.js | 10 +++---- .../phases/3-transform/server/types.d.ts | 10 +++---- .../server/visitors/AssignmentExpression.js | 4 +-- .../server/visitors/shared/component.js | 4 +-- .../server/visitors/shared/element.js | 4 +-- .../server/visitors/shared/utils.js | 4 +-- .../compiler/phases/3-transform/types.d.ts | 4 +-- .../src/compiler/phases/3-transform/utils.js | 20 +++++++------- packages/svelte/src/compiler/phases/nodes.js | 4 +-- packages/svelte/src/compiler/phases/scope.js | 26 +++++++++---------- .../svelte/src/compiler/phases/types.d.ts | 6 ++--- packages/svelte/src/compiler/state.js | 8 +++--- packages/svelte/src/compiler/types/index.d.ts | 4 +-- packages/svelte/src/compiler/utils/ast.js | 4 +-- packages/svelte/src/compiler/utils/slot.js | 4 +-- 40 files changed, 135 insertions(+), 136 deletions(-) diff --git a/packages/svelte/src/compiler/legacy.js b/packages/svelte/src/compiler/legacy.js index 2d90988936a8..e3f88c8f1d23 100644 --- a/packages/svelte/src/compiler/legacy.js +++ b/packages/svelte/src/compiler/legacy.js @@ -1,5 +1,5 @@ /** @import { Expression } from 'estree' */ -/** @import { AST, SvelteNode, TemplateNode } from '#compiler' */ +/** @import { AST } from '#compiler' */ /** @import * as Legacy from './types/legacy-nodes.js' */ import { walk } from 'zimmerframe'; import { @@ -11,7 +11,7 @@ import { extract_svelte_ignore } from './utils/extract_svelte_ignore.js'; /** * Some of the legacy Svelte AST nodes remove whitespace from the start and end of their children. - * @param {TemplateNode[]} nodes + * @param {AST.TemplateNode[]} nodes */ function remove_surrounding_whitespace_nodes(nodes) { const first = nodes.at(0); @@ -40,7 +40,7 @@ function remove_surrounding_whitespace_nodes(nodes) { * @returns {Legacy.LegacyRoot} */ export function convert(source, ast) { - const root = /** @type {SvelteNode | Legacy.LegacySvelteNode} */ (ast); + const root = /** @type {AST.SvelteNode | Legacy.LegacySvelteNode} */ (ast); return /** @type {Legacy.LegacyRoot} */ ( walk(root, null, { diff --git a/packages/svelte/src/compiler/migrate/index.js b/packages/svelte/src/compiler/migrate/index.js index 88f9bbf0eed6..1bb7a69a20f9 100644 --- a/packages/svelte/src/compiler/migrate/index.js +++ b/packages/svelte/src/compiler/migrate/index.js @@ -2,7 +2,7 @@ /** @import { Visitors } from 'zimmerframe' */ /** @import { ComponentAnalysis } from '../phases/types.js' */ /** @import { Scope, ScopeRoot } from '../phases/scope.js' */ -/** @import { AST, Binding, SvelteNode, ValidatedCompileOptions } from '#compiler' */ +/** @import { AST, Binding, ValidatedCompileOptions } from '#compiler' */ import MagicString from 'magic-string'; import { walk } from 'zimmerframe'; import { parse } from '../phases/1-parse/index.js'; @@ -479,7 +479,7 @@ export function migrate(source, { filename, use_ts } = {}) { * }} State */ -/** @type {Visitors} */ +/** @type {Visitors} */ const instance_script = { _(node, { state, next }) { // @ts-expect-error @@ -1050,7 +1050,7 @@ function trim_block(state, start, end) { } } -/** @type {Visitors} */ +/** @type {Visitors} */ const template = { Identifier(node, { state, path }) { handle_identifier(node, state, path); @@ -1410,7 +1410,7 @@ const template = { /** * @param {AST.RegularElement | AST.SvelteElement | AST.SvelteComponent | AST.Component | AST.SlotElement | AST.SvelteFragment} node - * @param {SvelteNode[]} path + * @param {AST.SvelteNode[]} path * @param {State} state */ function migrate_slot_usage(node, path, state) { @@ -1580,7 +1580,7 @@ function migrate_slot_usage(node, path, state) { /** * @param {VariableDeclarator} declarator * @param {State} state - * @param {SvelteNode[]} path + * @param {AST.SvelteNode[]} path */ function extract_type_and_comment(declarator, state, path) { const str = state.str; diff --git a/packages/svelte/src/compiler/phases/1-parse/index.js b/packages/svelte/src/compiler/phases/1-parse/index.js index 7639c2f0eda8..c3a8a098d319 100644 --- a/packages/svelte/src/compiler/phases/1-parse/index.js +++ b/packages/svelte/src/compiler/phases/1-parse/index.js @@ -1,4 +1,4 @@ -/** @import { AST, TemplateNode } from '#compiler' */ +/** @import { AST } from '#compiler' */ // @ts-expect-error acorn type definitions are borked in the release we use import { isIdentifierStart, isIdentifierChar } from 'acorn'; import fragment from './state/fragment.js'; @@ -28,7 +28,7 @@ export class Parser { /** Whether we're parsing in TypeScript mode */ ts = false; - /** @type {TemplateNode[]} */ + /** @type {AST.TemplateNode[]} */ stack = []; /** @type {AST.Fragment[]} */ diff --git a/packages/svelte/src/compiler/phases/1-parse/read/script.js b/packages/svelte/src/compiler/phases/1-parse/read/script.js index 87367aff0805..9d9ed3a1efdf 100644 --- a/packages/svelte/src/compiler/phases/1-parse/read/script.js +++ b/packages/svelte/src/compiler/phases/1-parse/read/script.js @@ -1,5 +1,5 @@ /** @import { Program } from 'estree' */ -/** @import { AST, Directive } from '#compiler' */ +/** @import { AST } from '#compiler' */ /** @import { Parser } from '../index.js' */ import * as acorn from '../acorn.js'; import { regex_not_newline_characters } from '../../patterns.js'; @@ -16,7 +16,7 @@ const ALLOWED_ATTRIBUTES = ['context', 'generics', 'lang', 'module']; /** * @param {Parser} parser * @param {number} start - * @param {Array} attributes + * @param {Array} attributes * @returns {AST.Script} */ export function read_script(parser, start, attributes) { diff --git a/packages/svelte/src/compiler/phases/1-parse/read/style.js b/packages/svelte/src/compiler/phases/1-parse/read/style.js index aa835a1d96fe..c225270b02e4 100644 --- a/packages/svelte/src/compiler/phases/1-parse/read/style.js +++ b/packages/svelte/src/compiler/phases/1-parse/read/style.js @@ -1,4 +1,4 @@ -/** @import { AST, Css, Directive } from '#compiler' */ +/** @import { AST, Css } from '#compiler' */ /** @import { Parser } from '../index.js' */ import * as e from '../../../errors.js'; @@ -18,7 +18,7 @@ const REGEX_HTML_COMMENT_CLOSE = /-->/; /** * @param {Parser} parser * @param {number} start - * @param {Array} attributes + * @param {Array} attributes * @returns {Css.StyleSheet} */ export default function read_style(parser, start, attributes) { diff --git a/packages/svelte/src/compiler/phases/1-parse/state/element.js b/packages/svelte/src/compiler/phases/1-parse/state/element.js index 45350bb1aec5..3d94f0721d63 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/element.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/element.js @@ -1,5 +1,5 @@ /** @import { Expression } from 'estree' */ -/** @import { AST, Directive, ElementLike, TemplateNode } from '#compiler' */ +/** @import { AST } from '#compiler' */ /** @import { Parser } from '../index.js' */ import { is_void } from '../../../../utils.js'; import read_expression from '../read/expression.js'; @@ -28,7 +28,7 @@ export const regex_valid_component_name = // (must start with uppercase letter if no dots, can contain dots) /^(?:\p{Lu}[$\u200c\u200d\p{ID_Continue}.]*|\p{ID_Start}[$\u200c\u200d\p{ID_Continue}]*(?:\.[$\u200c\u200d\p{ID_Continue}]+)+)$/u; -/** @type {Map} */ +/** @type {Map} */ const root_only_meta_tags = new Map([ ['svelte:head', 'SvelteHead'], ['svelte:options', 'SvelteOptions'], @@ -37,7 +37,7 @@ const root_only_meta_tags = new Map([ ['svelte:body', 'SvelteBody'] ]); -/** @type {Map} */ +/** @type {Map} */ const meta_tags = new Map([ ...root_only_meta_tags, ['svelte:element', 'SvelteElement'], @@ -137,7 +137,7 @@ export default function element(parser) { ? 'SlotElement' : 'RegularElement'; - /** @type {ElementLike} */ + /** @type {AST.ElementLike} */ const element = type === 'RegularElement' ? { @@ -155,7 +155,7 @@ export default function element(parser) { path: [] } } - : /** @type {ElementLike} */ ({ + : /** @type {AST.ElementLike} */ ({ type, start, end: -1, @@ -358,7 +358,7 @@ export default function element(parser) { } } -/** @param {TemplateNode[]} stack */ +/** @param {AST.TemplateNode[]} stack */ function parent_is_head(stack) { let i = stack.length; while (i--) { @@ -369,7 +369,7 @@ function parent_is_head(stack) { return false; } -/** @param {TemplateNode[]} stack */ +/** @param {AST.TemplateNode[]} stack */ function parent_is_shadowroot_template(stack) { // https://developer.chrome.com/docs/css-ui/declarative-shadow-dom#building_a_declarative_shadow_root let i = stack.length; @@ -433,7 +433,7 @@ function read_static_attribute(parser) { /** * @param {Parser} parser - * @returns {AST.Attribute | AST.SpreadAttribute | Directive | null} + * @returns {AST.Attribute | AST.SpreadAttribute | AST.Directive | null} */ function read_attribute(parser) { const start = parser.index; @@ -548,7 +548,7 @@ function read_attribute(parser) { } } - /** @type {Directive} */ + /** @type {AST.Directive} */ const directive = { start, end, diff --git a/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js b/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js index d017b215f2af..208c80c6df53 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js +++ b/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js @@ -352,7 +352,7 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element) const seen = new Set(); /** - * @param {Compiler.SvelteNode} node + * @param {Compiler.AST.SvelteNode} node * @param {{ is_child: boolean }} state */ function walk_children(node, state) { @@ -611,9 +611,9 @@ function get_following_sibling_elements(element, include_self) { const path = element.metadata.path; let i = path.length; - /** @type {Compiler.SvelteNode} */ + /** @type {Compiler.AST.SvelteNode} */ let start = element; - let nodes = /** @type {Compiler.SvelteNode[]} */ ( + let nodes = /** @type {Compiler.AST.SvelteNode[]} */ ( /** @type {Compiler.AST.Fragment} */ (path[0]).nodes ); @@ -639,7 +639,7 @@ function get_following_sibling_elements(element, include_self) { const seen = new Set(); - /** @param {Compiler.SvelteNode} node */ + /** @param {Compiler.AST.SvelteNode} node */ function get_siblings(node) { walk(node, null, { RegularElement(node) { @@ -836,7 +836,7 @@ function get_possible_element_siblings(node, adjacent_only, seen = new Set()) { const result = new Map(); const path = node.metadata.path; - /** @type {Compiler.SvelteNode} */ + /** @type {Compiler.AST.SvelteNode} */ let current = node; let i = path.length; @@ -1008,7 +1008,7 @@ function higher_existence(exist1, exist2) { } /** - * @param {Compiler.SvelteNode[]} children + * @param {Compiler.AST.SvelteNode[]} children * @param {boolean} adjacent_only */ function loop_child(children, adjacent_only) { @@ -1038,7 +1038,7 @@ function loop_child(children, adjacent_only) { } /** - * @param {Compiler.SvelteNode} node + * @param {Compiler.AST.SvelteNode} node * @returns {node is Compiler.AST.IfBlock | Compiler.AST.EachBlock | Compiler.AST.AwaitBlock | Compiler.AST.KeyBlock | Compiler.AST.SlotElement} */ function is_block(node) { diff --git a/packages/svelte/src/compiler/phases/2-analyze/index.js b/packages/svelte/src/compiler/phases/2-analyze/index.js index 8f1efd7f635f..de12c02f773c 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/index.js +++ b/packages/svelte/src/compiler/phases/2-analyze/index.js @@ -1,5 +1,5 @@ /** @import { Expression, Node, Program } from 'estree' */ -/** @import { Binding, AST, SvelteNode, ValidatedCompileOptions, ValidatedModuleCompileOptions } from '#compiler' */ +/** @import { Binding, AST, ValidatedCompileOptions, ValidatedModuleCompileOptions } from '#compiler' */ /** @import { AnalysisState, Visitors } from './types' */ /** @import { Analysis, ComponentAnalysis, Js, ReactiveStatement, Template } from '../types' */ import { walk } from 'zimmerframe'; @@ -525,7 +525,7 @@ export function analyze_component(root, source, options) { // more legacy nonsense: if an `each` binding is reassigned/mutated, // treat the expression as being mutated as well - walk(/** @type {SvelteNode} */ (template.ast), null, { + walk(/** @type {AST.SvelteNode} */ (template.ast), null, { EachBlock(node) { const scope = /** @type {Scope} */ (template.scopes.get(node)); @@ -608,7 +608,7 @@ export function analyze_component(root, source, options) { reactive_statements: new Map() }; - walk(/** @type {SvelteNode} */ (ast), state, visitors); + walk(/** @type {AST.SvelteNode} */ (ast), state, visitors); } // warn on any nonstate declarations that are a) reassigned and b) referenced in the template @@ -677,7 +677,7 @@ export function analyze_component(root, source, options) { function_depth: scope.function_depth }; - walk(/** @type {SvelteNode} */ (ast), state, visitors); + walk(/** @type {AST.SvelteNode} */ (ast), state, visitors); } for (const [name, binding] of instance.scope.declarations) { diff --git a/packages/svelte/src/compiler/phases/2-analyze/types.d.ts b/packages/svelte/src/compiler/phases/2-analyze/types.d.ts index dedbe95ace7e..b4ca4dc26278 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/types.d.ts +++ b/packages/svelte/src/compiler/phases/2-analyze/types.d.ts @@ -1,11 +1,11 @@ import type { Scope } from '../scope.js'; import type { ComponentAnalysis, ReactiveStatement } from '../types.js'; -import type { ExpressionMetadata, AST, ValidatedCompileOptions, SvelteNode } from '#compiler'; +import type { AST, ExpressionMetadata, ValidatedCompileOptions } from '#compiler'; import type { LabeledStatement } from 'estree'; export interface AnalysisState { scope: Scope; - scopes: Map; + scopes: Map; analysis: ComponentAnalysis; options: ValidatedCompileOptions; ast_type: 'instance' | 'template' | 'module'; @@ -31,11 +31,11 @@ export interface AnalysisState { } export type Context = import('zimmerframe').Context< - SvelteNode, + AST.SvelteNode, State >; export type Visitors = import('zimmerframe').Visitors< - SvelteNode, + AST.SvelteNode, State >; diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/AssignmentExpression.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/AssignmentExpression.js index 54e5b46486ad..a64c89cd88f1 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/AssignmentExpression.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/AssignmentExpression.js @@ -1,5 +1,4 @@ /** @import { AssignmentExpression } from 'estree' */ -/** @import { SvelteNode } from '#compiler' */ /** @import { Context } from '../types' */ import { extract_identifiers, object } from '../../../utils/ast.js'; import { validate_assignment } from './shared/utils.js'; diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/Attribute.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/Attribute.js index 6c050d966a22..6eb9faca6d4e 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/Attribute.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/Attribute.js @@ -1,5 +1,5 @@ /** @import { ArrowFunctionExpression, Expression, FunctionDeclaration, FunctionExpression } from 'estree' */ -/** @import { AST, DelegatedEvent, SvelteNode } from '#compiler' */ +/** @import { AST, DelegatedEvent } from '#compiler' */ /** @import { Context } from '../types' */ import { cannot_be_set_statically, is_capture_event, is_delegated } from '../../../../utils.js'; import { @@ -16,7 +16,7 @@ import { mark_subtree_dynamic } from './shared/fragment.js'; export function Attribute(node, context) { context.next(); - const parent = /** @type {SvelteNode} */ (context.path.at(-1)); + const parent = /** @type {AST.SvelteNode} */ (context.path.at(-1)); if (parent.type === 'RegularElement') { // special case