feat: Expose more AST types from `"svelte/compiler"` (#14601)

* add missing `SvelteBoundary` in `ElementLike`

* make union of AST types public and exportable with `AST` namespace

* apply AST types change to codebase

* changeset

* manually generate types

* Add `AttributeLike` type

* export namespace `Css` inside `AST`

* manually generate types again

* exported `Css` -> `CSS`

* `Css` -> `AST.CSS`

* fix Prettier issue

* Apply suggestions from code review

---------

Co-authored-by: Rich Harris <hello@rich-harris.dev>
pull/14699/head
Mateusz Kadlubowski 9 months ago committed by GitHub
parent 2e0dcd7872
commit 61a0da8a5f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': minor
---
feat: expose more AST types from `"svelte/compiler"`

@ -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, {

@ -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<SvelteNode, State>} */
/** @type {Visitors<AST.SvelteNode, State>} */
const instance_script = {
_(node, { state, next }) {
// @ts-expect-error
@ -1050,7 +1050,7 @@ function trim_block(state, start, end) {
}
}
/** @type {Visitors<SvelteNode, State>} */
/** @type {Visitors<AST.SvelteNode, State>} */
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;

@ -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[]} */

@ -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<AST.Attribute | AST.SpreadAttribute | Directive>} attributes
* @param {Array<AST.Attribute | AST.SpreadAttribute | AST.Directive>} attributes
* @returns {AST.Script}
*/
export function read_script(parser, start, attributes) {

@ -1,4 +1,4 @@
/** @import { AST, Css, Directive } from '#compiler' */
/** @import { AST } from '#compiler' */
/** @import { Parser } from '../index.js' */
import * as e from '../../../errors.js';
@ -18,8 +18,8 @@ const REGEX_HTML_COMMENT_CLOSE = /-->/;
/**
* @param {Parser} parser
* @param {number} start
* @param {Array<AST.Attribute | AST.SpreadAttribute | Directive>} attributes
* @returns {Css.StyleSheet}
* @param {Array<AST.Attribute | AST.SpreadAttribute | AST.Directive>} attributes
* @returns {AST.CSS.StyleSheet}
*/
export default function read_style(parser, start, attributes) {
const content_start = parser.index;
@ -49,7 +49,7 @@ export default function read_style(parser, start, attributes) {
* @returns {any[]}
*/
function read_body(parser, close) {
/** @type {Array<Css.Rule | Css.Atrule>} */
/** @type {Array<AST.CSS.Rule | AST.CSS.Atrule>} */
const children = [];
while (parser.index < parser.template.length) {
@ -71,7 +71,7 @@ function read_body(parser, close) {
/**
* @param {Parser} parser
* @returns {Css.Atrule}
* @returns {AST.CSS.Atrule}
*/
function read_at_rule(parser) {
const start = parser.index;
@ -81,7 +81,7 @@ function read_at_rule(parser) {
const prelude = read_value(parser);
/** @type {Css.Block | null} */
/** @type {AST.CSS.Block | null} */
let block = null;
if (parser.match('{')) {
@ -104,7 +104,7 @@ function read_at_rule(parser) {
/**
* @param {Parser} parser
* @returns {Css.Rule}
* @returns {AST.CSS.Rule}
*/
function read_rule(parser) {
const start = parser.index;
@ -126,10 +126,10 @@ function read_rule(parser) {
/**
* @param {Parser} parser
* @param {boolean} [inside_pseudo_class]
* @returns {Css.SelectorList}
* @returns {AST.CSS.SelectorList}
*/
function read_selector_list(parser, inside_pseudo_class = false) {
/** @type {Css.ComplexSelector[]} */
/** @type {AST.CSS.ComplexSelector[]} */
const children = [];
allow_comment_or_whitespace(parser);
@ -162,18 +162,18 @@ function read_selector_list(parser, inside_pseudo_class = false) {
/**
* @param {Parser} parser
* @param {boolean} [inside_pseudo_class]
* @returns {Css.ComplexSelector}
* @returns {AST.CSS.ComplexSelector}
*/
function read_selector(parser, inside_pseudo_class = false) {
const list_start = parser.index;
/** @type {Css.RelativeSelector[]} */
/** @type {AST.CSS.RelativeSelector[]} */
const children = [];
/**
* @param {Css.Combinator | null} combinator
* @param {AST.CSS.Combinator | null} combinator
* @param {number} start
* @returns {Css.RelativeSelector}
* @returns {AST.CSS.RelativeSelector}
*/
function create_selector(combinator, start) {
return {
@ -190,7 +190,7 @@ function read_selector(parser, inside_pseudo_class = false) {
};
}
/** @type {Css.RelativeSelector} */
/** @type {AST.CSS.RelativeSelector} */
let relative_selector = create_selector(null, parser.index);
while (parser.index < parser.template.length) {
@ -247,7 +247,7 @@ function read_selector(parser, inside_pseudo_class = false) {
} else if (parser.eat(':')) {
const name = read_identifier(parser);
/** @type {null | Css.SelectorList} */
/** @type {null | AST.CSS.SelectorList} */
let args = null;
if (parser.eat('(')) {
@ -372,7 +372,7 @@ function read_selector(parser, inside_pseudo_class = false) {
/**
* @param {Parser} parser
* @returns {Css.Combinator | null}
* @returns {AST.CSS.Combinator | null}
*/
function read_combinator(parser) {
const start = parser.index;
@ -407,14 +407,14 @@ function read_combinator(parser) {
/**
* @param {Parser} parser
* @returns {Css.Block}
* @returns {AST.CSS.Block}
*/
function read_block(parser) {
const start = parser.index;
parser.eat('{', true);
/** @type {Array<Css.Declaration | Css.Rule | Css.Atrule>} */
/** @type {Array<AST.CSS.Declaration | AST.CSS.Rule | AST.CSS.Atrule>} */
const children = [];
while (parser.index < parser.template.length) {
@ -441,7 +441,7 @@ function read_block(parser) {
* Reads a declaration, rule or at-rule
*
* @param {Parser} parser
* @returns {Css.Declaration | Css.Rule | Css.Atrule}
* @returns {AST.CSS.Declaration | AST.CSS.Rule | AST.CSS.Atrule}
*/
function read_block_item(parser) {
if (parser.match('@')) {
@ -460,7 +460,7 @@ function read_block_item(parser) {
/**
* @param {Parser} parser
* @returns {Css.Declaration}
* @returns {AST.CSS.Declaration}
*/
function read_declaration(parser) {
const start = parser.index;

@ -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<string, ElementLike['type']>} */
/** @type {Map<string, AST.ElementLike['type']>} */
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<string, ElementLike['type']>} */
/** @type {Map<string, AST.ElementLike['type']>} */
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;
@ -564,7 +564,7 @@ function read_attribute(parser) {
}
}
/** @type {Directive} */
/** @type {AST.Directive} */
const directive = {
start,
end,

@ -1,5 +1,5 @@
/** @import { ComponentAnalysis } from '../../types.js' */
/** @import { Css } from '#compiler' */
/** @import { AST } from '#compiler' */
/** @import { Visitors } from 'zimmerframe' */
import { walk } from 'zimmerframe';
import * as e from '../../../errors.js';
@ -8,17 +8,17 @@ import { is_global, is_unscoped_pseudo_class } from './utils.js';
/**
* @typedef {Visitors<
* Css.Node,
* AST.CSS.Node,
* {
* keyframes: string[];
* rule: Css.Rule | null;
* rule: AST.CSS.Rule | null;
* }
* >} CssVisitors
*/
/**
* True if is `:global`
* @param {Css.SimpleSelector} simple_selector
* @param {AST.CSS.SimpleSelector} simple_selector
*/
function is_global_block_selector(simple_selector) {
return (
@ -112,7 +112,7 @@ const css_visitors = {
}
},
RelativeSelector(node, context) {
const parent = /** @type {Css.ComplexSelector} */ (context.path.at(-1));
const parent = /** @type {AST.CSS.ComplexSelector} */ (context.path.at(-1));
if (
node.combinator != null &&
@ -149,7 +149,7 @@ const css_visitors = {
if (node.metadata.is_global_like || node.metadata.is_global) {
// So that nested selectors like `:root:not(.x)` are not marked as unused
for (const child of node.selectors) {
walk(/** @type {Css.Node} */ (child), null, {
walk(/** @type {AST.CSS.Node} */ (child), null, {
ComplexSelector(node, context) {
node.metadata.used = true;
context.next();
@ -177,7 +177,7 @@ const css_visitors = {
if (idx !== -1) {
is_global_block = true;
for (let i = idx + 1; i < child.selectors.length; i++) {
walk(/** @type {Css.Node} */ (child.selectors[i]), null, {
walk(/** @type {AST.CSS.Node} */ (child.selectors[i]), null, {
ComplexSelector(node) {
node.metadata.used = true;
}
@ -240,7 +240,7 @@ const css_visitors = {
});
},
NestingSelector(node, context) {
const rule = /** @type {Css.Rule} */ (context.state.rule);
const rule = /** @type {AST.CSS.Rule} */ (context.state.rule);
const parent_rule = rule.metadata.parent_rule;
if (!parent_rule) {
@ -271,7 +271,7 @@ const css_visitors = {
};
/**
* @param {Css.StyleSheet} stylesheet
* @param {AST.CSS.StyleSheet} stylesheet
* @param {ComponentAnalysis} analysis
*/
export function analyze_css(stylesheet, analysis) {

@ -14,7 +14,7 @@ const whitelist_attribute_selector = new Map([
['dialog', ['open']]
]);
/** @type {Compiler.Css.Combinator} */
/** @type {Compiler.AST.CSS.Combinator} */
const descendant_combinator = {
type: 'Combinator',
name: ' ',
@ -22,7 +22,7 @@ const descendant_combinator = {
end: -1
};
/** @type {Compiler.Css.RelativeSelector} */
/** @type {Compiler.AST.CSS.RelativeSelector} */
const nesting_selector = {
type: 'RelativeSelector',
start: -1,
@ -51,11 +51,11 @@ const seen = new Set();
/**
*
* @param {Compiler.Css.StyleSheet} stylesheet
* @param {Compiler.AST.CSS.StyleSheet} stylesheet
* @param {Compiler.AST.RegularElement | Compiler.AST.SvelteElement} element
*/
export function prune(stylesheet, element) {
walk(/** @type {Compiler.Css.Node} */ (stylesheet), null, {
walk(/** @type {Compiler.AST.CSS.Node} */ (stylesheet), null, {
Rule(node, context) {
if (node.metadata.is_global_block) {
context.visit(node.prelude);
@ -69,7 +69,11 @@ export function prune(stylesheet, element) {
seen.clear();
if (
apply_selector(selectors, /** @type {Compiler.Css.Rule} */ (node.metadata.rule), element)
apply_selector(
selectors,
/** @type {Compiler.AST.CSS.Rule} */ (node.metadata.rule),
element
)
) {
node.metadata.used = true;
}
@ -86,7 +90,7 @@ export function prune(stylesheet, element) {
* Also searches them for any existing `&` selectors and adds one if none are found.
* This ensures we traverse up to the parent rule when the inner selectors match and we're
* trying to see if the parent rule also matches.
* @param {Compiler.Css.ComplexSelector} node
* @param {Compiler.AST.CSS.ComplexSelector} node
*/
function get_relative_selectors(node) {
const selectors = truncate(node);
@ -124,7 +128,7 @@ function get_relative_selectors(node) {
/**
* Discard trailing `:global(...)` selectors, these are unused for scoping purposes
* @param {Compiler.Css.ComplexSelector} node
* @param {Compiler.AST.CSS.ComplexSelector} node
*/
function truncate(node) {
const i = node.children.findLastIndex(({ metadata, selectors }) => {
@ -152,8 +156,8 @@ function truncate(node) {
}
/**
* @param {Compiler.Css.RelativeSelector[]} relative_selectors
* @param {Compiler.Css.Rule} rule
* @param {Compiler.AST.CSS.RelativeSelector[]} relative_selectors
* @param {Compiler.AST.CSS.Rule} rule
* @param {Compiler.AST.RegularElement | Compiler.AST.SvelteElement} element
* @returns {boolean}
*/
@ -178,9 +182,9 @@ function apply_selector(relative_selectors, rule, element) {
}
/**
* @param {Compiler.Css.RelativeSelector} relative_selector
* @param {Compiler.Css.RelativeSelector[]} parent_selectors
* @param {Compiler.Css.Rule} rule
* @param {Compiler.AST.CSS.RelativeSelector} relative_selector
* @param {Compiler.AST.CSS.RelativeSelector[]} parent_selectors
* @param {Compiler.AST.CSS.Rule} rule
* @param {Compiler.AST.RegularElement | Compiler.AST.SvelteElement | Compiler.AST.RenderTag | Compiler.AST.Component | Compiler.AST.SvelteComponent | Compiler.AST.SvelteSelf} node
* @returns {boolean}
*/
@ -263,8 +267,8 @@ function apply_combinator(relative_selector, parent_selectors, rule, node) {
* it's a `:global(...)` or unscopeable selector, or
* is an `:is(...)` or `:where(...)` selector that contains
* a global selector
* @param {Compiler.Css.RelativeSelector} selector
* @param {Compiler.Css.Rule} rule
* @param {Compiler.AST.CSS.RelativeSelector} selector
* @param {Compiler.AST.CSS.Rule} rule
*/
function is_global(selector, rule) {
if (selector.metadata.is_global || selector.metadata.is_global_like) {
@ -272,7 +276,7 @@ function is_global(selector, rule) {
}
for (const s of selector.selectors) {
/** @type {Compiler.Css.SelectorList | null} */
/** @type {Compiler.AST.CSS.SelectorList | null} */
let selector_list = null;
let owner = rule;
@ -283,7 +287,7 @@ function is_global(selector, rule) {
}
if (s.type === 'NestingSelector') {
owner = /** @type {Compiler.Css.Rule} */ (rule.metadata.parent_rule);
owner = /** @type {Compiler.AST.CSS.Rule} */ (rule.metadata.parent_rule);
selector_list = owner.prelude;
}
@ -306,8 +310,8 @@ const regex_backslash_and_following_character = /\\(.)/g;
/**
* Ensure that `element` satisfies each simple selector in `relative_selector`
*
* @param {Compiler.Css.RelativeSelector} relative_selector
* @param {Compiler.Css.Rule} rule
* @param {Compiler.AST.CSS.RelativeSelector} relative_selector
* @param {Compiler.AST.CSS.Rule} rule
* @param {Compiler.AST.RegularElement | Compiler.AST.SvelteElement} element
* @returns {boolean}
*/
@ -352,7 +356,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) {
@ -389,7 +393,7 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element)
// upwards and back-to-front, we need to first check the selectors inside :has(...), then check the rest of the
// selector in a way that is similar to ancestor matching. In a sense, we're treating `.x:has(.y)` as `.x .y`.
for (const has_selector of has_selectors) {
const complex_selectors = /** @type {Compiler.Css.SelectorList} */ (has_selector.args)
const complex_selectors = /** @type {Compiler.AST.CSS.SelectorList} */ (has_selector.args)
.children;
let matched = false;
@ -578,7 +582,7 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element)
case 'NestingSelector': {
let matched = false;
const parent = /** @type {Compiler.Css.Rule} */ (rule.metadata.parent_rule);
const parent = /** @type {Compiler.AST.CSS.Rule} */ (rule.metadata.parent_rule);
for (const complex_selector of parent.prelude.children) {
if (
@ -611,9 +615,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 +643,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 +840,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 +1012,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 +1042,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) {

@ -1,17 +1,17 @@
/** @import { Visitors } from 'zimmerframe' */
/** @import { Css } from '#compiler' */
/** @import { AST } from '#compiler' */
import { walk } from 'zimmerframe';
import * as w from '../../../warnings.js';
import { is_keyframes_node } from '../../css.js';
/**
* @param {Css.StyleSheet} stylesheet
* @param {AST.CSS.StyleSheet} stylesheet
*/
export function warn_unused(stylesheet) {
walk(stylesheet, { stylesheet }, visitors);
}
/** @type {Visitors<Css.Node, { stylesheet: Css.StyleSheet }>} */
/** @type {Visitors<AST.CSS.Node, { stylesheet: AST.CSS.StyleSheet }>} */
const visitors = {
Atrule(node, context) {
if (!is_keyframes_node(node)) {
@ -28,7 +28,7 @@ const visitors = {
!node.metadata.used &&
// prevent double-marking of `.unused:is(.unused)`
(context.path.at(-2)?.type !== 'PseudoClassSelector' ||
/** @type {Css.ComplexSelector} */ (context.path.at(-4))?.metadata.used)
/** @type {AST.CSS.ComplexSelector} */ (context.path.at(-4))?.metadata.used)
) {
const content = context.state.stylesheet.content;
const text = content.styles.substring(node.start - content.start, node.end - content.start);

@ -1,4 +1,4 @@
/** @import { AST, Css } from '#compiler' */
/** @import { AST } from '#compiler' */
/** @import { Node } from 'estree' */
const UNKNOWN = {};
@ -36,7 +36,7 @@ export function get_possible_values(chunk) {
/**
* Returns all parent rules; root is last
* @param {Css.Rule | null} rule
* @param {AST.CSS.Rule | null} rule
*/
export function get_parent_rules(rule) {
const rules = [];
@ -51,8 +51,8 @@ export function get_parent_rules(rule) {
/**
* True if is `:global(...)` or `:global` and no pseudo class that is scoped.
* @param {Css.RelativeSelector} relative_selector
* @returns {relative_selector is Css.RelativeSelector & { selectors: [Css.PseudoClassSelector, ...Array<Css.PseudoClassSelector | Css.PseudoElementSelector>] }}
* @param {AST.CSS.RelativeSelector} relative_selector
* @returns {relative_selector is AST.CSS.RelativeSelector & { selectors: [AST.CSS.PseudoClassSelector, ...Array<AST.CSS.PseudoClassSelector | AST.CSS.PseudoElementSelector>] }}
*/
export function is_global(relative_selector) {
const first = relative_selector.selectors[0];
@ -72,7 +72,7 @@ export function is_global(relative_selector) {
/**
* `true` if is a pseudo class that cannot be or is not scoped
* @param {Css.SimpleSelector} selector
* @param {AST.CSS.SimpleSelector} selector
*/
export function is_unscoped_pseudo_class(selector) {
return (
@ -96,8 +96,8 @@ export function is_unscoped_pseudo_class(selector) {
/**
* True if is `:global(...)` or `:global`, irrespective of whether or not there are any pseudo classes that are scoped.
* Difference to `is_global`: `:global(x):has(y)` is `true` for `is_outer_global` but `false` for `is_global`.
* @param {Css.RelativeSelector} relative_selector
* @returns {relative_selector is Css.RelativeSelector & { selectors: [Css.PseudoClassSelector, ...Array<Css.PseudoClassSelector | Css.PseudoElementSelector>] }}
* @param {AST.CSS.RelativeSelector} relative_selector
* @returns {relative_selector is AST.CSS.RelativeSelector & { selectors: [AST.CSS.PseudoClassSelector, ...Array<AST.CSS.PseudoClassSelector | AST.CSS.PseudoElementSelector>] }}
*/
export function is_outer_global(relative_selector) {
const first = relative_selector.selectors[0];

@ -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) {

@ -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<SvelteNode, Scope>;
scopes: Map<AST.SvelteNode, Scope>;
analysis: ComponentAnalysis;
options: ValidatedCompileOptions;
ast_type: 'instance' | 'template' | 'module';
@ -31,11 +31,11 @@ export interface AnalysisState {
}
export type Context<State extends AnalysisState = AnalysisState> = import('zimmerframe').Context<
SvelteNode,
AST.SvelteNode,
State
>;
export type Visitors<State extends AnalysisState = AnalysisState> = import('zimmerframe').Visitors<
SvelteNode,
AST.SvelteNode,
State
>;

@ -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';

@ -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 <option value="" />

@ -1,5 +1,5 @@
/** @import { CallExpression, VariableDeclarator } from 'estree' */
/** @import { AST, SvelteNode } from '#compiler' */
/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */
import { get_rune } from '../../scope.js';
import * as e from '../../../errors.js';
@ -12,7 +12,7 @@ import { mark_subtree_dynamic } from './shared/fragment.js';
* @param {Context} context
*/
export function CallExpression(node, context) {
const parent = /** @type {SvelteNode} */ (get_parent(context.path, -1));
const parent = /** @type {AST.SvelteNode} */ (get_parent(context.path, -1));
const rune = get_rune(node, context.state.scope);

@ -1,5 +1,5 @@
/** @import { Expression, LabeledStatement } from 'estree' */
/** @import { AST, ReactiveStatement, SvelteNode } from '#compiler' */
/** @import { AST, ReactiveStatement } from '#compiler' */
/** @import { Context } from '../types' */
import * as e from '../../../errors.js';
import { extract_identifiers, object } from '../../../utils/ast.js';
@ -11,7 +11,7 @@ import * as w from '../../../warnings.js';
*/
export function LabeledStatement(node, context) {
if (node.label.name === '$') {
const parent = /** @type {SvelteNode} */ (context.path.at(-1));
const parent = /** @type {AST.SvelteNode} */ (context.path.at(-1));
const is_reactive_statement =
context.state.ast_type === 'instance' && parent.type === 'Program';

@ -1,4 +1,4 @@
/** @import { AST, Binding, SvelteNode } from '#compiler' */
/** @import { AST, Binding } from '#compiler' */
/** @import { Scope } from '../../scope' */
/** @import { Context } from '../types' */
import { validate_block_not_empty, validate_opening_tag } from './shared/utils.js';
@ -80,7 +80,7 @@ export function SnippetBlock(node, context) {
}
/**
* @param {Map<SvelteNode, Scope>} scopes
* @param {Map<AST.SvelteNode, Scope>} scopes
* @param {Scope} scope
*/
function can_hoist_snippet(scope, scopes, visited = new Set()) {

@ -1,5 +1,5 @@
/** @import { Context } from '../../types.js' */
/** @import { AST, SvelteNode, TemplateNode } from '#compiler' */
/** @import { AST } from '#compiler' */
/** @import { ARIARoleDefinitionKey, ARIARoleRelationConcept, ARIAProperty, ARIAPropertyDefinition, ARIARoleDefinition } from 'aria-query' */
import { roles as roles_map, aria, elementRoles } from 'aria-query';
// @ts-expect-error package doesn't provide typings
@ -582,7 +582,7 @@ function get_implicit_role(name, attribute_map) {
const invisible_elements = ['meta', 'html', 'script', 'style'];
/**
* @param {SvelteNode[]} path
* @param {AST.SvelteNode[]} path
* @param {string[]} elements
*/
function is_parent(path, elements) {
@ -1062,7 +1062,7 @@ export function check_element(node, context) {
}
if (node.name === 'label') {
/** @param {TemplateNode} node */
/** @param {AST.TemplateNode} node */
const has_input_child = (node) => {
let has = false;
walk(

@ -1,4 +1,4 @@
/** @import { AST, ElementLike } from '#compiler' */
/** @import { AST } from '#compiler' */
/** @import { Context } from '../../types' */
import * as e from '../../../../errors.js';
import { is_text_attribute } from '../../../../utils/ast.js';
@ -22,7 +22,7 @@ export function validate_attribute_name(attribute) {
/**
* @param {AST.Attribute} attribute
* @param {ElementLike} parent
* @param {AST.ElementLike} parent
*/
export function validate_attribute(attribute, parent) {
if (

@ -1,7 +1,7 @@
/** @import { AST, SvelteNode } from '#compiler' */
/** @import { AST } from '#compiler' */
/**
* @param {SvelteNode[]} path
* @param {AST.SvelteNode[]} path
*/
export function mark_subtree_dynamic(path) {
let i = path.length;

@ -1,5 +1,5 @@
/** @import * as ESTree from 'estree' */
/** @import { ValidatedCompileOptions, AST, ValidatedModuleCompileOptions, SvelteNode } from '#compiler' */
/** @import { AST, ValidatedCompileOptions, ValidatedModuleCompileOptions } from '#compiler' */
/** @import { ComponentAnalysis, Analysis } from '../../types' */
/** @import { Visitors, ComponentClientTransformState, ClientTransformState } from './types' */
import { walk } from 'zimmerframe';
@ -178,7 +178,7 @@ export function client_component(analysis, options) {
};
const module = /** @type {ESTree.Program} */ (
walk(/** @type {SvelteNode} */ (analysis.module.ast), state, visitors)
walk(/** @type {AST.SvelteNode} */ (analysis.module.ast), state, visitors)
);
const instance_state = {
@ -190,12 +190,12 @@ export function client_component(analysis, options) {
};
const instance = /** @type {ESTree.Program} */ (
walk(/** @type {SvelteNode} */ (analysis.instance.ast), instance_state, visitors)
walk(/** @type {AST.SvelteNode} */ (analysis.instance.ast), instance_state, visitors)
);
const template = /** @type {ESTree.Program} */ (
walk(
/** @type {SvelteNode} */ (analysis.template.ast),
/** @type {AST.SvelteNode} */ (analysis.template.ast),
{
...state,
transform: instance_state.transform,
@ -664,7 +664,7 @@ export function client_module(analysis, options) {
};
const module = /** @type {ESTree.Program} */ (
walk(/** @type {SvelteNode} */ (analysis.module.ast), state, visitors)
walk(/** @type {AST.SvelteNode} */ (analysis.module.ast), state, visitors)
);
return {

@ -9,7 +9,7 @@ import type {
UpdateExpression,
VariableDeclaration
} from 'estree';
import type { Namespace, SvelteNode, ValidatedCompileOptions } from '#compiler';
import type { AST, Namespace, ValidatedCompileOptions } from '#compiler';
import type { TransformState } from '../types.js';
import type { ComponentAnalysis } from '../../types.js';
import type { SourceLocation } from '#shared';
@ -98,14 +98,14 @@ export interface StateField {
id: PrivateIdentifier;
}
export type Context = import('zimmerframe').Context<SvelteNode, ClientTransformState>;
export type Visitors = import('zimmerframe').Visitors<SvelteNode, any>;
export type Context = import('zimmerframe').Context<AST.SvelteNode, ClientTransformState>;
export type Visitors = import('zimmerframe').Visitors<AST.SvelteNode, any>;
export type ComponentContext = import('zimmerframe').Context<
SvelteNode,
AST.SvelteNode,
ComponentClientTransformState
>;
export type ComponentVisitors = import('zimmerframe').Visitors<
SvelteNode,
AST.SvelteNode,
ComponentClientTransformState
>;

@ -1,5 +1,5 @@
/** @import { ArrowFunctionExpression, Expression, FunctionDeclaration, FunctionExpression, Identifier, Pattern, PrivateIdentifier, Statement } from 'estree' */
/** @import { Binding, SvelteNode } from '#compiler' */
/** @import { AST, Binding } from '#compiler' */
/** @import { ClientTransformState, ComponentClientTransformState, ComponentContext } from './types.js' */
/** @import { Analysis } from '../../types.js' */
/** @import { Scope } from '../../scope.js' */
@ -271,7 +271,7 @@ export function should_proxy(node, scope) {
/**
* @param {Pattern} node
* @param {import('zimmerframe').Context<SvelteNode, ComponentClientTransformState>} context
* @param {import('zimmerframe').Context<AST.SvelteNode, ComponentClientTransformState>} context
* @returns {{ id: Pattern, declarations: null | Statement[] }}
*/
export function create_derived_block_argument(node, context) {

@ -1,5 +1,5 @@
/** @import { CallExpression, Expression, MemberExpression, Pattern } from 'estree' */
/** @import { AST, SvelteNode } from '#compiler' */
/** @import { CallExpression, Expression, Pattern } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */
import { dev, is_ignored } from '../../../../state.js';
import { is_text_attribute } from '../../../../utils/ast.js';
@ -16,7 +16,7 @@ export function BindDirective(node, context) {
const expression = /** @type {Expression} */ (context.visit(node.expression));
const property = binding_properties[node.name];
const parent = /** @type {SvelteNode} */ (context.path.at(-1));
const parent = /** @type {AST.SvelteNode} */ (context.path.at(-1));
let get, set;

@ -1,5 +1,5 @@
/** @import { BlockStatement, Expression, ExpressionStatement, Identifier, MemberExpression, Pattern, Property, SequenceExpression, Statement } from 'estree' */
/** @import { AST, TemplateNode } from '#compiler' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../../types.js' */
import { dev, is_ignored } from '../../../../../state.js';
import { get_attribute_chunks, object } from '../../../../../utils/ast.js';
@ -35,7 +35,7 @@ export function build_component(node, component_name, context, anchor = context.
}
};
/** @type {Record<string, TemplateNode[]>} */
/** @type {Record<string, AST.TemplateNode[]>} */
const children = {};
/** @type {Record<string, Expression[]>} */

@ -1,5 +1,5 @@
/** @import { Expression } from 'estree' */
/** @import { AST, ExpressionMetadata, SvelteNode } from '#compiler' */
/** @import { AST, ExpressionMetadata } from '#compiler' */
/** @import { ComponentContext } from '../../types' */
import { is_capture_event, is_passive_event } from '../../../../../../utils.js';
import { dev, locator } from '../../../../../state.js';
@ -68,7 +68,7 @@ export function visit_event_attribute(node, context) {
)
);
const type = /** @type {SvelteNode} */ (context.path.at(-1)).type;
const type = /** @type {AST.SvelteNode} */ (context.path.at(-1)).type;
if (type === 'SvelteDocument' || type === 'SvelteWindow' || type === 'SvelteBody') {
// These nodes are above the component tree, and its events should run parent first

@ -1,5 +1,5 @@
/** @import { Expression } from 'estree' */
/** @import { AST, SvelteNode } from '#compiler' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../../types' */
import { cannot_be_set_statically } from '../../../../../../utils.js';
import { is_event_attribute, is_text_attribute } from '../../../../../utils/ast.js';
@ -10,7 +10,7 @@ import { build_template_chunk, build_update } from './utils.js';
* Processes an array of template nodes, joining sibling text/expression nodes
* (e.g. `{a} b {c}`) into a single update function. Along the way it creates
* corresponding template node references these updates are applied to.
* @param {SvelteNode[]} nodes
* @param {AST.SvelteNode[]} nodes
* @param {(is_text: boolean) => Expression} initial
* @param {boolean} is_element
* @param {ComponentContext} context
@ -124,7 +124,7 @@ export function process_children(nodes, initial, is_element, { visit, state }) {
}
/**
* @param {SvelteNode} node
* @param {AST.SvelteNode} node
* @param {ComponentContext["state"]} state
*/
function is_static_element(node, state) {

@ -1,5 +1,5 @@
/** @import { Expression, ExpressionStatement, Identifier, MemberExpression, SequenceExpression, Statement, Super } from 'estree' */
/** @import { AST, SvelteNode } from '#compiler' */
/** @import { AST } from '#compiler' */
/** @import { ComponentClientTransformState } from '../../types' */
import { walk } from 'zimmerframe';
import { object } from '../../../../../utils/ast.js';
@ -12,7 +12,7 @@ import { locator } from '../../../../../state.js';
/**
* @param {Array<AST.Text | AST.ExpressionTag>} values
* @param {(node: SvelteNode, state: any) => any} visit
* @param {(node: AST.SvelteNode, state: any) => any} visit
* @param {ComponentClientTransformState} state
* @returns {{ value: Expression, has_state: boolean, has_call: boolean }}
*/
@ -145,7 +145,7 @@ export function build_update_assignment(state, id, init, value, update) {
* Serializes `bind:this` for components and elements.
* @param {Identifier | MemberExpression | SequenceExpression} expression
* @param {Expression} value
* @param {import('zimmerframe').Context<SvelteNode, ComponentClientTransformState>} context
* @param {import('zimmerframe').Context<AST.SvelteNode, ComponentClientTransformState>} context
*/
export function build_bind_this(expression, value, { state, visit }) {
if (expression.type === 'SequenceExpression') {

@ -1,5 +1,5 @@
/** @import { Visitors } from 'zimmerframe' */
/** @import { ValidatedCompileOptions, Css } from '#compiler' */
/** @import { AST, ValidatedCompileOptions } from '#compiler' */
/** @import { ComponentAnalysis } from '../../types.js' */
import MagicString from 'magic-string';
import { walk } from 'zimmerframe';
@ -41,9 +41,9 @@ export function render_stylesheet(source, analysis, options) {
}
};
const ast = /** @type {Css.StyleSheet} */ (analysis.css.ast);
const ast = /** @type {AST.CSS.StyleSheet} */ (analysis.css.ast);
walk(/** @type {Css.Node} */ (ast), state, visitors);
walk(/** @type {AST.CSS.Node} */ (ast), state, visitors);
code.remove(0, ast.content.start);
code.remove(/** @type {number} */ (ast.content.end), source.length);
@ -71,7 +71,7 @@ export function render_stylesheet(source, analysis, options) {
return css;
}
/** @type {Visitors<Css.Node, State>} */
/** @type {Visitors<AST.CSS.Node, State>} */
const visitors = {
_: (node, context) => {
context.state.code.addSourcemapLocation(node.start);
@ -259,7 +259,7 @@ const visitors = {
if (parent?.type === 'Rule') {
specificity = { bumped: false };
/** @type {Css.Rule | null} */
/** @type {AST.CSS.Rule | null} */
let rule = parent.metadata.parent_rule;
while (rule) {
@ -278,7 +278,7 @@ const visitors = {
for (const relative_selector of node.children) {
if (relative_selector.metadata.is_global) {
const global = /** @type {Css.PseudoClassSelector} */ (relative_selector.selectors[0]);
const global = /** @type {AST.CSS.PseudoClassSelector} */ (relative_selector.selectors[0]);
remove_global_pseudo_class(global, relative_selector.combinator, context.state);
if (
@ -361,15 +361,15 @@ const visitors = {
/**
*
* @param {Array<Css.Node>} path
* @param {Array<AST.CSS.Node>} path
*/
function is_in_global_block(path) {
return path.some((node) => node.type === 'Rule' && node.metadata.is_global_block);
}
/**
* @param {Css.PseudoClassSelector} selector
* @param {Css.Combinator | null} combinator
* @param {AST.CSS.PseudoClassSelector} selector
* @param {AST.CSS.Combinator | null} combinator
* @param {State} state
*/
function remove_global_pseudo_class(selector, combinator, state) {
@ -399,7 +399,7 @@ function remove_preceding_whitespace(end, state) {
}
/**
* @param {Css.Rule} rule
* @param {AST.CSS.Rule} rule
* @param {boolean} is_in_global_block
*/
function is_empty(rule, is_in_global_block) {
@ -426,14 +426,14 @@ function is_empty(rule, is_in_global_block) {
return true;
}
/** @param {Css.Rule} rule */
/** @param {AST.CSS.Rule} rule */
function is_used(rule) {
return rule.prelude.children.some((selector) => selector.metadata.used);
}
/**
*
* @param {Css.Rule} node
* @param {AST.CSS.Rule} node
* @param {MagicString} code
*/
function escape_comment_close(node, code) {

@ -1,5 +1,5 @@
/** @import { Program, Property, Statement, VariableDeclarator } from 'estree' */
/** @import { SvelteNode, ValidatedCompileOptions, ValidatedModuleCompileOptions } from '#compiler' */
/** @import { AST, ValidatedCompileOptions, ValidatedModuleCompileOptions } from '#compiler' */
/** @import { ComponentServerTransformState, ComponentVisitors, ServerTransformState, Visitors } from './types.js' */
/** @import { Analysis, ComponentAnalysis } from '../../types.js' */
import { walk } from 'zimmerframe';
@ -104,12 +104,12 @@ export function server_component(analysis, options) {
};
const module = /** @type {Program} */ (
walk(/** @type {SvelteNode} */ (analysis.module.ast), state, global_visitors)
walk(/** @type {AST.SvelteNode} */ (analysis.module.ast), state, global_visitors)
);
const instance = /** @type {Program} */ (
walk(
/** @type {SvelteNode} */ (analysis.instance.ast),
/** @type {AST.SvelteNode} */ (analysis.instance.ast),
{ ...state, scopes: analysis.instance.scopes },
{
...global_visitors,
@ -130,7 +130,7 @@ export function server_component(analysis, options) {
const template = /** @type {Program} */ (
walk(
/** @type {SvelteNode} */ (analysis.template.ast),
/** @type {AST.SvelteNode} */ (analysis.template.ast),
{ ...state, scopes: analysis.template.scopes },
// @ts-expect-error don't know, don't care
{ ...global_visitors, ...template_visitors }
@ -394,7 +394,7 @@ export function server_module(analysis, options) {
};
const module = /** @type {Program} */ (
walk(/** @type {SvelteNode} */ (analysis.module.ast), state, global_visitors)
walk(/** @type {AST.SvelteNode} */ (analysis.module.ast), state, global_visitors)
);
return {

@ -1,5 +1,5 @@
import type { Expression, Statement, ModuleDeclaration, LabeledStatement } from 'estree';
import type { Namespace, SvelteNode, ValidatedCompileOptions } from '#compiler';
import type { AST, Namespace, ValidatedCompileOptions } from '#compiler';
import type { TransformState } from '../types.js';
import type { ComponentAnalysis } from '../../types.js';
import type { StateField } from '../client/types.js';
@ -25,14 +25,14 @@ export interface ComponentServerTransformState extends ServerTransformState {
readonly skip_hydration_boundaries: boolean;
}
export type Context = import('zimmerframe').Context<SvelteNode, ServerTransformState>;
export type Visitors = import('zimmerframe').Visitors<SvelteNode, ServerTransformState>;
export type Context = import('zimmerframe').Context<AST.SvelteNode, ServerTransformState>;
export type Visitors = import('zimmerframe').Visitors<AST.SvelteNode, ServerTransformState>;
export type ComponentContext = import('zimmerframe').Context<
SvelteNode,
AST.SvelteNode,
ComponentServerTransformState
>;
export type ComponentVisitors = import('zimmerframe').Visitors<
SvelteNode,
AST.SvelteNode,
ComponentServerTransformState
>;

@ -1,5 +1,5 @@
/** @import { AssignmentExpression, AssignmentOperator, Expression, Pattern } from 'estree' */
/** @import { SvelteNode } from '#compiler' */
/** @import { AST } from '#compiler' */
/** @import { Context, ServerTransformState } from '../types.js' */
import * as b from '../../../../utils/builders.js';
import { build_assignment_value } from '../../../../utils/ast.js';
@ -18,7 +18,7 @@ export function AssignmentExpression(node, context) {
* @param {AssignmentOperator} operator
* @param {Pattern} left
* @param {Expression} right
* @param {import('zimmerframe').Context<SvelteNode, ServerTransformState>} context
* @param {import('zimmerframe').Context<AST.SvelteNode, ServerTransformState>} context
* @returns {Expression | null}
*/
function build_assignment(operator, left, right, context) {

@ -1,5 +1,5 @@
/** @import { BlockStatement, Expression, Pattern, Property, SequenceExpression, Statement } from 'estree' */
/** @import { AST, TemplateNode } from '#compiler' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../../types.js' */
import { empty_comment, build_attribute_value } from './utils.js';
import * as b from '../../../../../utils/builders.js';
@ -31,7 +31,7 @@ export function build_inline_component(node, expression, context) {
scope: node.metadata.scopes.default
};
/** @type {Record<string, TemplateNode[]>} */
/** @type {Record<string, AST.TemplateNode[]>} */
const children = {};
/**

@ -1,5 +1,5 @@
/** @import { Expression, Literal } from 'estree' */
/** @import { AST, Namespace, SvelteNode } from '#compiler' */
/** @import { AST, Namespace } from '#compiler' */
/** @import { ComponentContext, ComponentServerTransformState } from '../../types.js' */
import {
get_attribute_chunks,
@ -31,7 +31,7 @@ const WHITESPACE_INSENSITIVE_ATTRIBUTES = ['class', 'style'];
* Writes the output to the template output. Some elements may have attributes on them that require the
* their output to be the child content instead. In this case, an object is returned.
* @param {AST.RegularElement | AST.SvelteElement} node
* @param {import('zimmerframe').Context<SvelteNode, ComponentServerTransformState>} context
* @param {import('zimmerframe').Context<AST.SvelteNode, ComponentServerTransformState>} context
*/
export function build_element_attributes(node, context) {
/** @type {Array<AST.Attribute | AST.SpreadAttribute>} */

@ -1,5 +1,5 @@
/** @import { AssignmentOperator, Expression, Identifier, Node, Statement, TemplateElement } from 'estree' */
/** @import { AST, SvelteNode } from '#compiler' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext, ServerTransformState } from '../../types.js' */
import { escape_html } from '../../../../../../escaping.js';
@ -24,7 +24,7 @@ export const empty_comment = b.literal(EMPTY_COMMENT);
/**
* Processes an array of template nodes, joining sibling text/expression nodes and
* recursing into child nodes.
* @param {Array<SvelteNode>} nodes
* @param {Array<AST.SvelteNode>} nodes
* @param {ComponentContext} context
*/
export function process_children(nodes, { visit, state }) {

@ -1,10 +1,10 @@
import type { Scope } from '../scope.js';
import type { SvelteNode, ValidatedModuleCompileOptions } from '#compiler';
import type { AST, ValidatedModuleCompileOptions } from '#compiler';
import type { Analysis } from '../types.js';
export interface TransformState {
readonly analysis: Analysis;
readonly options: ValidatedModuleCompileOptions;
readonly scope: Scope;
readonly scopes: Map<SvelteNode, Scope>;
readonly scopes: Map<AST.SvelteNode, Scope>;
}

@ -1,6 +1,6 @@
/** @import { Context } from 'zimmerframe' */
/** @import { TransformState } from './types.js' */
/** @import { AST, Binding, Namespace, SvelteNode, ValidatedCompileOptions } from '#compiler' */
/** @import { AST, Binding, Namespace, ValidatedCompileOptions } from '#compiler' */
/** @import { Node, Expression, CallExpression } from 'estree' */
import {
regex_ends_with_whitespaces,
@ -33,7 +33,7 @@ export function is_hoisted_function(node) {
/**
* Match Svelte 4 behaviour by sorting ConstTag nodes in topological order
* @param {SvelteNode[]} nodes
* @param {AST.SvelteNode[]} nodes
* @param {TransformState} state
*/
function sort_const_tags(nodes, state) {
@ -133,9 +133,9 @@ function sort_const_tags(nodes, state) {
* unless it's whitespace-only, in which case collapse to a single whitespace for all cases
* except when it's children of certain elements where we know ignore whitespace (like td/option/head),
* in which case we remove it entirely
* @param {SvelteNode} parent
* @param {SvelteNode[]} nodes
* @param {SvelteNode[]} path
* @param {AST.SvelteNode} parent
* @param {AST.SvelteNode[]} nodes
* @param {AST.SvelteNode[]} path
* @param {Namespace} namespace
* @param {TransformState & { options: ValidatedCompileOptions }} state
* @param {boolean} preserve_whitespace
@ -157,10 +157,10 @@ export function clean_nodes(
nodes = sort_const_tags(nodes, state);
}
/** @type {SvelteNode[]} */
/** @type {AST.SvelteNode[]} */
const hoisted = [];
/** @type {SvelteNode[]} */
/** @type {AST.SvelteNode[]} */
const regular = [];
for (const node of nodes) {
@ -316,8 +316,8 @@ export function clean_nodes(
/**
* Infers the namespace for the children of a node that should be used when creating the `$.template(...)`.
* @param {Namespace} namespace
* @param {SvelteNode} parent
* @param {SvelteNode[]} nodes
* @param {AST.SvelteNode} parent
* @param {AST.SvelteNode[]} nodes
*/
export function infer_namespace(namespace, parent, nodes) {
if (parent.type === 'RegularElement' && parent.name === 'foreignObject') {
@ -371,7 +371,7 @@ export function infer_namespace(namespace, parent, nodes) {
* Heuristic: Keep current namespace, unless we find a regular element,
* in which case we always want html, or we only find svg nodes,
* in which case we assume svg.
* @param {SvelteNode[]} nodes
* @param {AST.SvelteNode[]} nodes
* @param {Namespace | 'keep' | 'maybe_html'} namespace
*/
function check_nodes_for_namespace(nodes, namespace) {

@ -1,4 +1,4 @@
/** @import { Css } from '#compiler' */
/** @import { AST } from '#compiler' */
const regex_css_browser_prefix = /^-((webkit)|(moz)|(o)|(ms))-/;
export const regex_css_name_boundary = /^[\s,;}]$/;
@ -10,5 +10,5 @@ export function remove_css_prefix(name) {
return name.replace(regex_css_browser_prefix, '');
}
/** @param {Css.Atrule} node */
/** @param {AST.CSS.Atrule} node */
export const is_keyframes_node = (node) => remove_css_prefix(node.name) === 'keyframes';

@ -1,4 +1,4 @@
/** @import { AST, ExpressionMetadata, SvelteNode } from '#compiler' */
/** @import { AST, ExpressionMetadata } from '#compiler' */
/**
* All nodes that can appear elsewhere than the top level, have attributes and can contain children
*/
@ -14,7 +14,7 @@ const element_nodes = [
/**
* Returns true for all nodes that can appear elsewhere than the top level, have attributes and can contain children
* @param {SvelteNode} node
* @param {AST.SvelteNode} node
* @returns {node is AST.Component | AST.RegularElement | AST.SlotElement | AST.SvelteComponent | AST.SvelteElement | AST.SvelteFragment | AST.SvelteSelf}
*/
export function is_element_node(node) {

@ -1,6 +1,6 @@
/** @import { ClassDeclaration, Expression, FunctionDeclaration, Identifier, ImportDeclaration, MemberExpression, Node, Pattern, VariableDeclarator } from 'estree' */
/** @import { Context, Visitor } from 'zimmerframe' */
/** @import { AST, Binding, DeclarationKind, ElementLike, SvelteNode } from '#compiler' */
/** @import { AST, Binding, DeclarationKind } from '#compiler' */
import is_reference from 'is-reference';
import { walk } from 'zimmerframe';
import { create_expression_metadata } from './nodes.js';
@ -48,7 +48,7 @@ export class Scope {
/**
* A set of all the names referenced with this scope
* useful for generating unique names
* @type {Map<string, { node: Identifier; path: SvelteNode[] }[]>}
* @type {Map<string, { node: Identifier; path: AST.SvelteNode[] }[]>}
*/
references = new Map();
@ -179,7 +179,7 @@ export class Scope {
/**
* @param {Identifier} node
* @param {SvelteNode[]} path
* @param {AST.SvelteNode[]} path
*/
reference(node, path) {
path = [...path]; // ensure that mutations to path afterwards don't affect this reference
@ -225,7 +225,7 @@ export class ScopeRoot {
}
/**
* @param {SvelteNode} ast
* @param {AST.SvelteNode} ast
* @param {ScopeRoot} root
* @param {boolean} allow_reactive_declarations
* @param {Scope | null} parent
@ -235,7 +235,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
/**
* A map of node->associated scope. A node appearing in this map does not necessarily mean that it created a scope
* @type {Map<SvelteNode, Scope>}
* @type {Map<AST.SvelteNode, Scope>}
*/
const scopes = new Map();
const scope = new Scope(root, parent, false);
@ -244,7 +244,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
/** @type {State} */
const state = { scope };
/** @type {[Scope, { node: Identifier; path: SvelteNode[] }][]} */
/** @type {[Scope, { node: Identifier; path: AST.SvelteNode[] }][]} */
const references = [];
/** @type {[Scope, Pattern | MemberExpression][]} */
@ -269,7 +269,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
}
/**
* @type {Visitor<Node, State, SvelteNode>}
* @type {Visitor<Node, State, AST.SvelteNode>}
*/
const create_block_scope = (node, { state, next }) => {
const scope = state.scope.child(true);
@ -279,7 +279,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
};
/**
* @type {Visitor<ElementLike, State, SvelteNode>}
* @type {Visitor<AST.ElementLike, State, AST.SvelteNode>}
*/
const SvelteFragment = (node, { state, next }) => {
const scope = state.scope.child();
@ -288,7 +288,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
};
/**
* @type {Visitor<AST.Component | AST.SvelteComponent | AST.SvelteSelf, State, SvelteNode>}
* @type {Visitor<AST.Component | AST.SvelteComponent | AST.SvelteSelf, State, AST.SvelteNode>}
*/
const Component = (node, context) => {
node.metadata.scopes = {
@ -329,7 +329,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
};
/**
* @type {Visitor<AST.AnimateDirective | AST.TransitionDirective | AST.UseDirective, State, SvelteNode>}
* @type {Visitor<AST.AnimateDirective | AST.TransitionDirective | AST.UseDirective, State, AST.SvelteNode>}
*/
const SvelteDirective = (node, { state, path, visit }) => {
state.scope.reference(b.id(node.name.split('.')[0]), path);
@ -713,9 +713,9 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
}
/**
* @template {{ scope: Scope, scopes: Map<SvelteNode, Scope> }} State
* @param {SvelteNode} node
* @param {Context<SvelteNode, State>} context
* @template {{ scope: Scope, scopes: Map<AST.SvelteNode, Scope> }} State
* @param {AST.SvelteNode} node
* @param {Context<AST.SvelteNode, State>} context
*/
export function set_scope(node, { next, state }) {
const scope = state.scopes.get(node);

@ -1,17 +1,17 @@
import type { AST, Binding, Css, SvelteNode } from '#compiler';
import type { AST, Binding } from '#compiler';
import type { Identifier, LabeledStatement, Node, Program } from 'estree';
import type { Scope, ScopeRoot } from './scope.js';
export interface Js {
ast: Program;
scope: Scope;
scopes: Map<SvelteNode, Scope>;
scopes: Map<AST.SvelteNode, Scope>;
}
export interface Template {
ast: AST.Fragment;
scope: Scope;
scopes: Map<SvelteNode, Scope>;
scopes: Map<AST.SvelteNode, Scope>;
}
export interface ReactiveStatement {
@ -66,7 +66,7 @@ export interface ComponentAnalysis extends Analysis {
binding_groups: Map<[key: string, bindings: Array<Binding | null>], Identifier>;
slot_names: Map<string, AST.SlotElement>;
css: {
ast: Css.StyleSheet | null;
ast: AST.CSS.StyleSheet | null;
hash: string;
keyframes: string[];
};

@ -1,5 +1,5 @@
/** @import { CompileOptions, SvelteNode } from './types' */
/** @import { Warning } from '#compiler' */
/** @import { CompileOptions } from './types' */
/** @import { AST, Warning } from '#compiler' */
import { getLocator } from 'locate-character';
/** @typedef {{ start?: number, end?: number }} NodeLike */
@ -41,7 +41,7 @@ export let ignore_stack = [];
* For each node the list of warnings that should be ignored for that node.
* Exists in addition to `ignore_stack` because not all warnings are emitted
* while the stack is being built.
* @type {Map<SvelteNode | NodeLike, Set<string>[]>}
* @type {Map<AST.SvelteNode | NodeLike, Set<string>[]>}
*/
export let ignore_map = new Map();
@ -66,7 +66,7 @@ export function reset_warning_filter(fn = () => true) {
}
/**
* @param {SvelteNode | NodeLike} node
* @param {AST.SvelteNode | NodeLike} node
* @param {import('../constants.js').IGNORABLE_RUNTIME_WARNINGS[number]} code
* @returns
*/

@ -1,6 +1,6 @@
import type { AST } from '#compiler';
export namespace Css {
export namespace _CSS {
export interface BaseNode {
start: number;
end: number;

@ -7,8 +7,7 @@ import type {
} from 'estree';
import type { SourceMap } from 'magic-string';
import type { Scope } from '../phases/scope.js';
import type { Css } from './css.js';
import type { AST, Namespace, SvelteNode } from './template.js';
import type { AST, Namespace } from './template.js';
import type { ICompileDiagnostic } from '../utils/compile_diagnostic.js';
/** The return value of `compile` from `svelte/compiler` */
@ -295,7 +294,7 @@ export interface Binding {
| AST.EachBlock
| AST.SnippetBlock;
is_called: boolean;
references: { node: Identifier; path: SvelteNode[] }[];
references: { node: Identifier; path: AST.SvelteNode[] }[];
mutated: boolean;
reassigned: boolean;
/** `true` if mutated _or_ reassigned */
@ -322,7 +321,6 @@ export interface ExpressionMetadata {
}
export * from './template.js';
export { Css };
// TODO this chain is a bit weird
export { ReactiveStatement } from '../phases/types.js';

@ -1,4 +1,4 @@
import type { AST, Css } from '#compiler';
import type { AST } from '#compiler';
import type {
ArrayExpression,
AssignmentExpression,
@ -260,7 +260,7 @@ export interface LegacyStyle extends BaseNode {
export interface LegacySelector extends BaseNode {
type: 'Selector';
children: Array<Css.Combinator | Css.SimpleSelector>;
children: Array<AST.CSS.Combinator | AST.CSS.SimpleSelector>;
}
export type LegacyCssNode = LegacyStyle | LegacySelector;

@ -1,4 +1,4 @@
import type { Binding, Css, ExpressionMetadata } from '#compiler';
import type { Binding, ExpressionMetadata } from '#compiler';
import type {
ArrayExpression,
ArrowFunctionExpression,
@ -18,6 +18,7 @@ import type {
SequenceExpression
} from 'estree';
import type { Scope } from '../phases/scope';
import type { _CSS } from './css';
/**
* - `html` the default, for e.g. `<div>` or `<span>`
@ -66,7 +67,7 @@ export namespace AST {
options: SvelteOptions | null;
fragment: Fragment;
/** The parsed `<style>` element, if exists */
css: Css.StyleSheet | null;
css: AST.CSS.StyleSheet | null;
/** The parsed `<script>` element, if exists */
instance: Script | null;
/** The parsed `<script module>` element, if exists */
@ -499,50 +500,60 @@ 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.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 AttributeLike = Attribute | SpreadAttribute | Directive;
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 Tag = AST.ExpressionTag | AST.HtmlTag | AST.ConstTag | AST.DebugTag | AST.RenderTag;
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 { _CSS as CSS };
}
declare module 'estree' {
export interface BaseNode {

@ -1,4 +1,4 @@
/** @import { AST, SvelteNode } from '#compiler' */
/** @import { AST } from '#compiler' */
/** @import * as ESTree from 'estree' */
import { walk } from 'zimmerframe';
import * as b from '../utils/builders.js';
@ -393,7 +393,7 @@ function _extract_paths(assignments = [], param, expression, update_expression,
* Like `path.at(x)`, but skips over `TSNonNullExpression` and `TSAsExpression` nodes and eases assertions a bit
* by removing the `| undefined` from the resulting type.
*
* @template {SvelteNode} T
* @template {AST.SvelteNode} T
* @param {T[]} path
* @param {number} at
*/

@ -1,9 +1,9 @@
/** @import { SvelteNode } from '#compiler' */
/** @import { AST } from '#compiler' */
import { is_element_node } from '../phases/nodes.js';
import { is_text_attribute } from './ast.js';
/**
* @param {SvelteNode} node
* @param {AST.SvelteNode} node
*/
export function determine_slot(node) {
if (!is_element_node(node)) return null;

@ -606,7 +606,7 @@ declare module 'svelte/animate' {
}
declare module 'svelte/compiler' {
import type { Expression, Identifier, ArrayExpression, ArrowFunctionExpression, VariableDeclaration, VariableDeclarator, MemberExpression, ObjectExpression, Pattern, Program, ChainExpression, SimpleCallExpression, SequenceExpression } from 'estree';
import type { Expression, Identifier, ArrayExpression, ArrowFunctionExpression, VariableDeclaration, VariableDeclarator, MemberExpression, Node, ObjectExpression, Pattern, Program, ChainExpression, SimpleCallExpression, SequenceExpression } from 'estree';
import type { SourceMap } from 'magic-string';
import type { Location } from 'locate-character';
/**
@ -943,7 +943,7 @@ declare module 'svelte/compiler' {
options: SvelteOptions | null;
fragment: Fragment;
/** The parsed `<style>` element, if exists */
css: Css.StyleSheet | null;
css: AST.CSS.StyleSheet | null;
/** The parsed `<script>` element, if exists */
instance: Script | null;
/** The parsed `<script module>` element, if exists */
@ -1257,37 +1257,60 @@ declare module 'svelte/compiler' {
content: Program;
attributes: Attribute[];
}
}
type Tag = AST.ExpressionTag | AST.HtmlTag | AST.ConstTag | AST.DebugTag | AST.RenderTag;
type Directive =
| AST.AnimateDirective
| AST.BindDirective
| AST.ClassDirective
| AST.LetDirective
| AST.OnDirective
| AST.StyleDirective
| AST.TransitionDirective
| AST.UseDirective;
type Block = AST.EachBlock | AST.IfBlock | AST.AwaitBlock | AST.KeyBlock | AST.SnippetBlock;
type ElementLike =
| AST.Component
| AST.TitleElement
| AST.SlotElement
| AST.RegularElement
| AST.SvelteBody
| AST.SvelteComponent
| AST.SvelteDocument
| AST.SvelteElement
| AST.SvelteFragment
| AST.SvelteHead
| AST.SvelteOptionsRaw
| AST.SvelteSelf
| AST.SvelteWindow
| AST.SvelteBoundary;
export type AttributeLike = Attribute | SpreadAttribute | Directive;
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 Tag = AST.ExpressionTag | AST.HtmlTag | AST.ConstTag | AST.DebugTag | AST.RenderTag;
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 { _CSS as CSS };
}
/**
* The preprocess function provides convenient hooks for arbitrarily transforming component source code.
* For example, it can be used to convert a `<style lang="sass">` block into vanilla CSS.
@ -1313,7 +1336,17 @@ declare module 'svelte/compiler' {
} | undefined): {
code: string;
};
namespace Css {
type ICompileDiagnostic = {
code: string;
message: string;
stack?: string;
filename?: string;
start?: Location;
end?: Location;
position?: [number, number];
frame?: string;
};
namespace _CSS {
export interface BaseNode {
start: number;
end: number;
@ -1471,16 +1504,6 @@ declare module 'svelte/compiler' {
| SimpleSelector
| Declaration;
}
type ICompileDiagnostic = {
code: string;
message: string;
stack?: string;
filename?: string;
start?: Location;
end?: Location;
position?: [number, number];
frame?: string;
};
export {};
}

Loading…
Cancel
Save