chore: use JSDoc type imports in more files (#12239)

* chore: use JSDoc type imports in more files

* Location_1 -> Location

* merge

* fix

* oops

---------

Co-authored-by: Rich Harris <rich.harris@vercel.com>
pull/12262/head
Damian Stasik 6 months ago committed by GitHub
parent bcf23cafce
commit 84325bf89b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,3 +1,4 @@
/** @import { FlipParams, AnimationConfig } from './public.js' */
import { cubicOut } from '../easing/index.js';
/**
@ -7,8 +8,8 @@ import { cubicOut } from '../easing/index.js';
* https://svelte.dev/docs/svelte-animate#flip
* @param {Element} node
* @param {{ from: DOMRect; to: DOMRect }} fromTo
* @param {import('./public.js').FlipParams} params
* @returns {import('./public.js').AnimationConfig}
* @param {FlipParams} params
* @returns {AnimationConfig}
*/
export function flip(node, { from, to }, params = {}) {
const style = getComputedStyle(node);

@ -1,3 +1,5 @@
/** @import { LegacyRoot } from './types/legacy-nodes.js' */
/** @import { CompileOptions, CompileResult, ValidatedCompileOptions, ModuleCompileOptions, Root } from '#compiler' */
import { walk as zimmerframe_walk } from 'zimmerframe';
import { convert } from './legacy.js';
import { parse as parse_acorn } from './phases/1-parse/acorn.js';
@ -14,8 +16,8 @@ export { default as preprocess } from './preprocess/index.js';
*
* https://svelte.dev/docs/svelte-compiler#svelte-compile
* @param {string} source The component source code
* @param {import('#compiler').CompileOptions} options The compiler options
* @returns {import('#compiler').CompileResult}
* @param {CompileOptions} options The compiler options
* @returns {CompileResult}
*/
export function compile(source, options) {
const validated = validate_component_options(options, '');
@ -25,7 +27,7 @@ export function compile(source, options) {
const { customElement: customElementOptions, ...parsed_options } = parsed.options || {};
/** @type {import('#compiler').ValidatedCompileOptions} */
/** @type {ValidatedCompileOptions} */
const combined_options = {
...validated,
...parsed_options,
@ -52,8 +54,8 @@ export function compile(source, options) {
*
* https://svelte.dev/docs/svelte-compiler#svelte-compile
* @param {string} source The component source code
* @param {import('#compiler').ModuleCompileOptions} options
* @returns {import('#compiler').CompileResult}
* @param {ModuleCompileOptions} options
* @returns {CompileResult}
*/
export function compileModule(source, options) {
const validated = validate_module_options(options, '');
@ -73,7 +75,7 @@ export function compileModule(source, options) {
* @overload
* @param {string} source
* @param {{ filename?: string; modern: true }} options
* @returns {import('#compiler').Root}
* @returns {Root}
*/
/**
@ -86,7 +88,7 @@ export function compileModule(source, options) {
* @overload
* @param {string} source
* @param {{ filename?: string; modern?: false }} [options]
* @returns {import('./types/legacy-nodes.js').LegacyRoot}
* @returns {LegacyRoot}
*/
/**
@ -98,7 +100,7 @@ export function compileModule(source, options) {
* https://svelte.dev/docs/svelte-compiler#svelte-parse
* @param {string} source
* @param {{ filename?: string; rootDir?: string; modern?: boolean }} [options]
* @returns {import('#compiler').Root | import('./types/legacy-nodes.js').LegacyRoot}
* @returns {Root | LegacyRoot}
*/
export function parse(source, { filename, rootDir, modern } = {}) {
state.reset(source, { filename, rootDir }); // TODO it's weird to require filename/rootDir here. reconsider the API
@ -109,7 +111,7 @@ export function parse(source, { filename, rootDir, modern } = {}) {
/**
* @param {string} source
* @param {import('#compiler').Root} ast
* @param {Root} ast
* @param {boolean | undefined} modern
*/
function to_public_ast(source, ast, modern) {

@ -1,3 +1,9 @@
/** @import { VariableDeclarator, Node, Identifier } from 'estree' */
/** @import { SvelteNode } from '../types/template.js' */
/** @import { Visitors } from 'zimmerframe' */
/** @import { ComponentAnalysis } from '../phases/types.js' */
/** @import { Scope } from '../phases/scope.js' */
/** @import * as Compiler from '#compiler' */
import MagicString from 'magic-string';
import { walk } from 'zimmerframe';
import { parse } from '../phases/1-parse/index.js';
@ -24,7 +30,7 @@ export function migrate(source) {
const { customElement: customElementOptions, ...parsed_options } = parsed.options || {};
/** @type {import('#compiler').ValidatedCompileOptions} */
/** @type {Compiler.ValidatedCompileOptions} */
const combined_options = {
...validate_component_options({}, ''),
...parsed_options,
@ -160,9 +166,9 @@ export function migrate(source) {
/**
* @typedef {{
* scope: import('../phases/scope.js').Scope;
* scope: Scope;
* str: MagicString;
* analysis: import('../phases/types.js').ComponentAnalysis;
* analysis: ComponentAnalysis;
* indent: string;
* props: Array<{ local: string; exported: string; init: string; bindable: boolean; slot_name?: string; optional: boolean; type: string; comment?: string }>;
* props_insertion_point: number;
@ -175,7 +181,7 @@ export function migrate(source) {
* }} State
*/
/** @type {import('zimmerframe').Visitors<import('../types/template.js').SvelteNode, State>} */
/** @type {Visitors<SvelteNode, State>} */
const instance_script = {
_(node, { state, next }) {
// @ts-expect-error
@ -281,9 +287,7 @@ const instance_script = {
// }
}
const binding = /** @type {import('#compiler').Binding} */ (
state.scope.get(declarator.id.name)
);
const binding = /** @type {Compiler.Binding} */ (state.scope.get(declarator.id.name));
if (
state.analysis.uses_props &&
@ -429,7 +433,7 @@ const instance_script = {
}
};
/** @type {import('zimmerframe').Visitors<import('../types/template.js').SvelteNode, State>} */
/** @type {Visitors<SvelteNode, State>} */
const template = {
Identifier(node, { state, path }) {
handle_identifier(node, state, path);
@ -543,15 +547,15 @@ const template = {
};
/**
* @param {import('estree').VariableDeclarator} declarator
* @param {VariableDeclarator} declarator
* @param {MagicString} str
* @param {import('#compiler').SvelteNode[]} path
* @param {Compiler.SvelteNode[]} path
*/
function extract_type_and_comment(declarator, str, path) {
const parent = path.at(-1);
// Try to find jsdoc above the declaration
let comment_node = /** @type {import('estree').Node} */ (parent)?.leadingComments?.at(-1);
let comment_node = /** @type {Node} */ (parent)?.leadingComments?.at(-1);
if (comment_node?.type !== 'Block') comment_node = undefined;
const comment_start = /** @type {any} */ (comment_node)?.start;
@ -590,11 +594,11 @@ function extract_type_and_comment(declarator, str, path) {
}
/**
* @param {import('#compiler').RegularElement | import('#compiler').SvelteElement | import('#compiler').SvelteWindow | import('#compiler').SvelteDocument | import('#compiler').SvelteBody} element
* @param {Compiler.RegularElement | Compiler.SvelteElement | Compiler.SvelteWindow | Compiler.SvelteDocument | Compiler.SvelteBody} element
* @param {State} state
*/
function handle_events(element, state) {
/** @type {Map<string, import('#compiler').OnDirective[]>} */
/** @type {Map<string, Compiler.OnDirective[]>} */
const handlers = new Map();
for (const attribute of element.attributes) {
if (attribute.type !== 'OnDirective') continue;
@ -805,7 +809,7 @@ function get_indent(state, ...nodes) {
}
/**
* @param {import('#compiler').OnDirective} last
* @param {Compiler.OnDirective} last
* @param {State} state
*/
function generate_event_name(last, state) {
@ -821,7 +825,7 @@ function generate_event_name(last, state) {
}
/**
* @param {import('estree').Identifier} node
* @param {Identifier} node
* @param {State} state
* @param {any[]} path
*/

@ -1,3 +1,4 @@
/** @import { TemplateNode, Fragment, Root, SvelteOptionsRaw } 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';
@ -26,13 +27,13 @@ export class Parser {
/** Whether we're parsing in TypeScript mode */
ts = false;
/** @type {import('#compiler').TemplateNode[]} */
/** @type {TemplateNode[]} */
stack = [];
/** @type {import('#compiler').Fragment[]} */
/** @type {Fragment[]} */
fragments = [];
/** @type {import('#compiler').Root} */
/** @type {Root} */
root;
/** @type {Record<string, boolean>} */
@ -120,9 +121,7 @@ export class Parser {
(thing) => thing.type === 'SvelteOptions'
);
if (options_index !== -1) {
const options = /** @type {import('#compiler').SvelteOptionsRaw} */ (
this.root.fragment.nodes[options_index]
);
const options = /** @type {SvelteOptionsRaw} */ (this.root.fragment.nodes[options_index]);
this.root.fragment.nodes.splice(options_index, 1);
this.root.options = read_options(options);
// We need this for the old AST format
@ -289,7 +288,7 @@ export class Parser {
/**
* @param {string} template
* @returns {import('#compiler').Root}
* @returns {Root}
*/
export function parse(template) {
const parser = new Parser(template);

@ -1,3 +1,6 @@
/** @import { Location } from 'locate-character' */
/** @import { Pattern } from 'estree' */
/** @import { Parser } from '../index.js' */
// @ts-expect-error acorn type definitions are borked in the release we use
import { isIdentifierStart } from 'acorn';
import full_char_code_at from '../utils/full_char_code_at.js';
@ -13,8 +16,8 @@ import * as e from '../../../errors.js';
import { locator } from '../../../state.js';
/**
* @param {import('../index.js').Parser} parser
* @returns {import('estree').Pattern}
* @param {Parser} parser
* @returns {Pattern}
*/
export default function read_pattern(parser) {
const start = parser.index;
@ -30,8 +33,8 @@ export default function read_pattern(parser) {
name,
start,
loc: {
start: /** @type {import('locate-character').Location} */ (locator(start)),
end: /** @type {import('locate-character').Location} */ (locator(parser.index))
start: /** @type {Location} */ (locator(start)),
end: /** @type {Location} */ (locator(parser.index))
},
end: parser.index,
typeAnnotation: annotation
@ -95,7 +98,7 @@ export default function read_pattern(parser) {
}
/**
* @param {import('../index.js').Parser} parser
* @param {Parser} parser
* @returns {any}
*/
function read_type_annotation(parser) {

@ -1,14 +1,16 @@
/** @import { ObjectExpression } from 'estree' */
/** @import { SvelteOptionsRaw, Root, SvelteOptions } from '#compiler' */
import { namespace_mathml, namespace_svg } from '../../../../constants.js';
import * as e from '../../../errors.js';
const regex_valid_tag_name = /^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/;
/**
* @param {import('#compiler').SvelteOptionsRaw} node
* @returns {import('#compiler').Root['options']}
* @param {SvelteOptionsRaw} node
* @returns {Root['options']}
*/
export default function read_options(node) {
/** @type {import('#compiler').SvelteOptions} */
/** @type {SvelteOptions} */
const component_options = {
start: node.start,
end: node.end,
@ -37,7 +39,7 @@ export default function read_options(node) {
break; // eslint doesn't know this is unnecessary
}
case 'customElement': {
/** @type {import('#compiler').SvelteOptions['customElement']} */
/** @type {SvelteOptions['customElement']} */
const ce = { tag: '' };
const { value } = attribute;
@ -86,8 +88,7 @@ export default function read_options(node) {
e.svelte_options_invalid_customelement_props(attribute);
}
ce.props = {};
for (const property of /** @type {import('estree').ObjectExpression} */ (props)
.properties) {
for (const property of /** @type {ObjectExpression} */ (props).properties) {
if (
property.type !== 'Property' ||
property.computed ||

@ -1,3 +1,6 @@
/** @import { Program } from 'estree' */
/** @import { Attribute, SpreadAttribute, Directive, Script } from '#compiler' */
/** @import { Parser } from '../index.js' */
import * as acorn from '../acorn.js';
import { regex_not_newline_characters } from '../../patterns.js';
import * as e from '../../../errors.js';
@ -29,10 +32,10 @@ function get_context(attributes) {
}
/**
* @param {import('../index.js').Parser} parser
* @param {Parser} parser
* @param {number} start
* @param {Array<import('#compiler').Attribute | import('#compiler').SpreadAttribute | import('#compiler').Directive>} attributes
* @returns {import('#compiler').Script}
* @param {Array<Attribute | SpreadAttribute | Directive>} attributes
* @returns {Script}
*/
export function read_script(parser, start, attributes) {
const script_start = parser.index;
@ -45,7 +48,7 @@ export function read_script(parser, start, attributes) {
parser.template.slice(0, script_start).replace(regex_not_newline_characters, ' ') + data;
parser.read(regex_starts_with_closing_script_tag);
/** @type {import('estree').Program} */
/** @type {Program} */
let ast;
try {

@ -1,3 +1,5 @@
/** @import { Attribute, SpreadAttribute, Directive, Css } from '#compiler' */
/** @import { Parser } from '../index.js' */
import * as e from '../../../errors.js';
const REGEX_MATCHER = /^[~^$*|]?=/;
@ -14,10 +16,10 @@ const REGEX_COMMENT_CLOSE = /\*\//;
const REGEX_HTML_COMMENT_CLOSE = /-->/;
/**
* @param {import('../index.js').Parser} parser
* @param {Parser} parser
* @param {number} start
* @param {Array<import('#compiler').Attribute | import('#compiler').SpreadAttribute | import('#compiler').Directive>} attributes
* @returns {import('#compiler').Css.StyleSheet}
* @param {Array<Attribute | SpreadAttribute | Directive>} attributes
* @returns {Css.StyleSheet}
*/
export default function read_style(parser, start, attributes) {
const content_start = parser.index;
@ -42,12 +44,12 @@ export default function read_style(parser, start, attributes) {
}
/**
* @param {import('../index.js').Parser} parser
* @param {Parser} parser
* @param {string} close
* @returns {any[]}
*/
function read_body(parser, close) {
/** @type {Array<import('#compiler').Css.Rule | import('#compiler').Css.Atrule>} */
/** @type {Array<Css.Rule | Css.Atrule>} */
const children = [];
while (parser.index < parser.template.length) {
@ -68,8 +70,8 @@ function read_body(parser, close) {
}
/**
* @param {import('../index.js').Parser} parser
* @returns {import('#compiler').Css.Atrule}
* @param {Parser} parser
* @returns {Css.Atrule}
*/
function read_at_rule(parser) {
const start = parser.index;
@ -79,7 +81,7 @@ function read_at_rule(parser) {
const prelude = read_value(parser);
/** @type {import('#compiler').Css.Block | null} */
/** @type {Css.Block | null} */
let block = null;
if (parser.match('{')) {
@ -101,8 +103,8 @@ function read_at_rule(parser) {
}
/**
* @param {import('../index.js').Parser} parser
* @returns {import('#compiler').Css.Rule}
* @param {Parser} parser
* @returns {Css.Rule}
*/
function read_rule(parser) {
const start = parser.index;
@ -122,12 +124,12 @@ function read_rule(parser) {
}
/**
* @param {import('../index.js').Parser} parser
* @param {Parser} parser
* @param {boolean} [inside_pseudo_class]
* @returns {import('#compiler').Css.SelectorList}
* @returns {Css.SelectorList}
*/
function read_selector_list(parser, inside_pseudo_class = false) {
/** @type {import('#compiler').Css.ComplexSelector[]} */
/** @type {Css.ComplexSelector[]} */
const children = [];
allow_comment_or_whitespace(parser);
@ -158,20 +160,20 @@ function read_selector_list(parser, inside_pseudo_class = false) {
}
/**
* @param {import('../index.js').Parser} parser
* @param {Parser} parser
* @param {boolean} [inside_pseudo_class]
* @returns {import('#compiler').Css.ComplexSelector}
* @returns {Css.ComplexSelector}
*/
function read_selector(parser, inside_pseudo_class = false) {
const list_start = parser.index;
/** @type {import('#compiler').Css.RelativeSelector[]} */
/** @type {Css.RelativeSelector[]} */
const children = [];
/**
* @param {import('#compiler').Css.Combinator | null} combinator
* @param {Css.Combinator | null} combinator
* @param {number} start
* @returns {import('#compiler').Css.RelativeSelector}
* @returns {Css.RelativeSelector}
*/
function create_selector(combinator, start) {
return {
@ -188,7 +190,7 @@ function read_selector(parser, inside_pseudo_class = false) {
};
}
/** @type {import('#compiler').Css.RelativeSelector} */
/** @type {Css.RelativeSelector} */
let relative_selector = create_selector(null, parser.index);
while (parser.index < parser.template.length) {
@ -245,7 +247,7 @@ function read_selector(parser, inside_pseudo_class = false) {
} else if (parser.eat(':')) {
const name = read_identifier(parser);
/** @type {null | import('#compiler').Css.SelectorList} */
/** @type {null | Css.SelectorList} */
let args = null;
if (parser.eat('(')) {
@ -373,8 +375,8 @@ function read_selector(parser, inside_pseudo_class = false) {
}
/**
* @param {import('../index.js').Parser} parser
* @returns {import('#compiler').Css.Combinator | null}
* @param {Parser} parser
* @returns {Css.Combinator | null}
*/
function read_combinator(parser) {
const start = parser.index;
@ -408,15 +410,15 @@ function read_combinator(parser) {
}
/**
* @param {import('../index.js').Parser} parser
* @returns {import('#compiler').Css.Block}
* @param {Parser} parser
* @returns {Css.Block}
*/
function read_block(parser) {
const start = parser.index;
parser.eat('{', true);
/** @type {Array<import('#compiler').Css.Declaration | import('#compiler').Css.Rule | import('#compiler').Css.Atrule>} */
/** @type {Array<Css.Declaration | Css.Rule | Css.Atrule>} */
const children = [];
while (parser.index < parser.template.length) {
@ -442,8 +444,8 @@ function read_block(parser) {
/**
* Reads a declaration, rule or at-rule
*
* @param {import('../index.js').Parser} parser
* @returns {import('#compiler').Css.Declaration | import('#compiler').Css.Rule | import('#compiler').Css.Atrule}
* @param {Parser} parser
* @returns {Css.Declaration | Css.Rule | Css.Atrule}
*/
function read_block_item(parser) {
if (parser.match('@')) {
@ -461,8 +463,8 @@ function read_block_item(parser) {
}
/**
* @param {import('../index.js').Parser} parser
* @returns {import('#compiler').Css.Declaration}
* @param {Parser} parser
* @returns {Css.Declaration}
*/
function read_declaration(parser) {
const start = parser.index;
@ -495,7 +497,7 @@ function read_declaration(parser) {
}
/**
* @param {import('../index.js').Parser} parser
* @param {Parser} parser
* @returns {string}
*/
function read_value(parser) {
@ -537,7 +539,7 @@ function read_value(parser) {
/**
* Read a property that may or may not be quoted, e.g.
* `foo` or `'foo bar'` or `"foo bar"`
* @param {import('../index.js').Parser} parser
* @param {Parser} parser
*/
function read_attribute_value(parser) {
let value = '';
@ -569,7 +571,7 @@ function read_attribute_value(parser) {
/**
* https://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
* @param {import('../index.js').Parser} parser
* @param {Parser} parser
*/
function read_identifier(parser) {
const start = parser.index;
@ -608,7 +610,7 @@ function read_identifier(parser) {
return identifier;
}
/** @param {import('../index.js').Parser} parser */
/** @param {Parser} parser */
function allow_comment_or_whitespace(parser) {
parser.allow_whitespace();
while (parser.match('/*') || parser.match('<!--')) {

@ -1,9 +1,11 @@
/** @import { Context, Visitors } from 'zimmerframe' */
/** @import { FunctionExpression, FunctionDeclaration } from 'estree' */
import { walk } from 'zimmerframe';
import * as b from '../../utils/builders.js';
/**
* @param {import('estree').FunctionExpression | import('estree').FunctionDeclaration} node
* @param {import('zimmerframe').Context<any, any>} context
* @param {FunctionExpression | FunctionDeclaration} node
* @param {Context<any, any>} context
*/
function remove_this_param(node, context) {
if (node.params[0]?.type === 'Identifier' && node.params[0].name === 'this') {
@ -12,7 +14,7 @@ function remove_this_param(node, context) {
return context.next();
}
/** @type {import('zimmerframe').Visitors<any, null>} */
/** @type {Visitors<any, null>} */
const visitors = {
ImportDeclaration(node) {
if (node.importKind === 'type') return b.empty;

@ -1,3 +1,5 @@
/** @import { Parser } from '../index.js' */
/** @import * as Compiler from '#compiler' */
import { is_void } from '../utils/names.js';
import read_expression from '../read/expression.js';
import { read_script } from '../read/script.js';
@ -14,7 +16,7 @@ const valid_tag_name = /^\!?[a-zA-Z]{1,}:?[a-zA-Z0-9\-]*/;
/** Invalid attribute characters if the attribute is not surrounded by quotes */
const regex_starts_with_invalid_attr_value = /^(\/>|[\s"'=<>`])/;
/** @type {Map<string, import('#compiler').ElementLike['type']>} */
/** @type {Map<string, Compiler.ElementLike['type']>} */
const root_only_meta_tags = new Map([
['svelte:head', 'SvelteHead'],
['svelte:options', 'SvelteOptions'],
@ -23,7 +25,7 @@ const root_only_meta_tags = new Map([
['svelte:body', 'SvelteBody']
]);
/** @type {Map<string, import('#compiler').ElementLike['type']>} */
/** @type {Map<string, Compiler.ElementLike['type']>} */
const meta_tags = new Map([
...root_only_meta_tags,
['svelte:element', 'SvelteElement'],
@ -39,7 +41,7 @@ const COMPONENT = /^svelte:component(?=[\s/>])/;
const SLOT = /^svelte:fragment(?=[\s/>])/;
const ELEMENT = /^svelte:element(?=[\s/>])/;
/** @param {import('#compiler').TemplateNode[]} stack */
/** @param {Compiler.TemplateNode[]} stack */
function parent_is_head(stack) {
let i = stack.length;
while (i--) {
@ -50,14 +52,14 @@ function parent_is_head(stack) {
return false;
}
/** @param {import('#compiler').TemplateNode[]} stack */
/** @param {Compiler.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;
while (i--) {
if (
stack[i].type === 'RegularElement' &&
/** @type {import('#compiler').RegularElement} */ (stack[i]).attributes.some(
/** @type {Compiler.RegularElement} */ (stack[i]).attributes.some(
(a) => a.type === 'Attribute' && a.name === 'shadowrootmode'
)
) {
@ -71,7 +73,7 @@ const regex_closing_textarea_tag = /^<\/textarea(\s[^>]*)?>/i;
const regex_closing_comment = /-->/;
const regex_capital_letter = /[A-Z]/;
/** @param {import('../index.js').Parser} parser */
/** @param {Parser} parser */
export default function element(parser) {
const start = parser.index++;
@ -81,7 +83,7 @@ export default function element(parser) {
const data = parser.read_until(regex_closing_comment);
parser.eat('-->', true);
/** @type {ReturnType<typeof parser.append<import('#compiler').Comment>>} */
/** @type {ReturnType<typeof parser.append<Compiler.Comment>>} */
parser.append({
type: 'Comment',
start,
@ -100,10 +102,10 @@ export default function element(parser) {
if (is_closing_tag) {
if (
['svelte:options', 'svelte:window', 'svelte:body', 'svelte:document'].includes(name) &&
/** @type {import('#compiler').ElementLike} */ (parent).fragment.nodes.length
/** @type {Compiler.ElementLike} */ (parent).fragment.nodes.length
) {
e.svelte_meta_invalid_content(
/** @type {import('#compiler').ElementLike} */ (parent).fragment.nodes[0].start,
/** @type {Compiler.ElementLike} */ (parent).fragment.nodes[0].start,
name
);
}
@ -131,7 +133,7 @@ export default function element(parser) {
? 'SlotElement'
: 'RegularElement';
/** @type {import('#compiler').ElementLike} */
/** @type {Compiler.ElementLike} */
const element =
type === 'RegularElement'
? {
@ -149,7 +151,7 @@ export default function element(parser) {
},
parent: null
}
: /** @type {import('#compiler').ElementLike} */ ({
: /** @type {Compiler.ElementLike} */ ({
type,
start,
end: -1,
@ -172,7 +174,7 @@ export default function element(parser) {
parser.eat('>', true);
// close any elements that don't have their own closing tags, e.g. <div><p></div>
while (/** @type {import('#compiler').RegularElement} */ (parent).name !== name) {
while (/** @type {Compiler.RegularElement} */ (parent).name !== name) {
if (parent.type !== 'RegularElement') {
if (parser.last_auto_closed_tag && parser.last_auto_closed_tag.tag === name) {
e.element_invalid_closing_tag_autoclosed(start, name, parser.last_auto_closed_tag.reason);
@ -238,9 +240,7 @@ export default function element(parser) {
e.svelte_component_missing_this(start);
}
const definition = /** @type {import('#compiler').Attribute} */ (
element.attributes.splice(index, 1)[0]
);
const definition = /** @type {Compiler.Attribute} */ (element.attributes.splice(index, 1)[0]);
if (
definition.value === true ||
definition.value.length !== 1 ||
@ -261,9 +261,7 @@ export default function element(parser) {
e.svelte_element_missing_this(start);
}
const definition = /** @type {import('#compiler').Attribute} */ (
element.attributes.splice(index, 1)[0]
);
const definition = /** @type {Compiler.Attribute} */ (element.attributes.splice(index, 1)[0]);
if (definition.value === true) {
e.svelte_element_missing_this(definition);
@ -296,7 +294,7 @@ export default function element(parser) {
if (is_top_level_script_or_style) {
parser.eat('>', true);
/** @type {import('#compiler').Comment | null} */
/** @type {Compiler.Comment | null} */
let prev_comment = null;
for (let i = current.fragment.nodes.length - 1; i >= 0; i--) {
const node = current.fragment.nodes[i];
@ -363,7 +361,7 @@ export default function element(parser) {
const data = parser.read_until(new RegExp(`</${name}>`));
const end = parser.index;
/** @type {import('#compiler').Text} */
/** @type {Compiler.Text} */
const node = {
start,
end,
@ -384,7 +382,7 @@ export default function element(parser) {
const regex_whitespace_or_slash_or_closing_tag = /(\s|\/|>)/;
/** @param {import('../index.js').Parser} parser */
/** @param {Parser} parser */
function read_tag_name(parser) {
const start = parser.index;
@ -441,8 +439,8 @@ const regex_starts_with_quote_characters = /^["']/;
const regex_attribute_value = /^(?:"([^"]*)"|'([^'])*'|([^>\s]+))/;
/**
* @param {import('../index.js').Parser} parser
* @returns {import('#compiler').Attribute | null}
* @param {Parser} parser
* @returns {Compiler.Attribute | null}
*/
function read_static_attribute(parser) {
const start = parser.index;
@ -450,7 +448,7 @@ function read_static_attribute(parser) {
const name = parser.read_until(regex_token_ending_character);
if (!name) return null;
/** @type {true | Array<import('#compiler').Text | import('#compiler').ExpressionTag>} */
/** @type {true | Array<Compiler.Text | Compiler.ExpressionTag>} */
let value = true;
if (parser.eat('=')) {
@ -487,8 +485,8 @@ function read_static_attribute(parser) {
}
/**
* @param {import('../index.js').Parser} parser
* @returns {import('#compiler').Attribute | import('#compiler').SpreadAttribute | import('#compiler').Directive | null}
* @param {Parser} parser
* @returns {Compiler.Attribute | Compiler.SpreadAttribute | Compiler.Directive | null}
*/
function read_attribute(parser) {
const start = parser.index;
@ -502,7 +500,7 @@ function read_attribute(parser) {
parser.allow_whitespace();
parser.eat('}', true);
/** @type {import('#compiler').SpreadAttribute} */
/** @type {Compiler.SpreadAttribute} */
const spread = {
type: 'SpreadAttribute',
start,
@ -527,7 +525,7 @@ function read_attribute(parser) {
parser.allow_whitespace();
parser.eat('}', true);
/** @type {import('#compiler').ExpressionTag} */
/** @type {Compiler.ExpressionTag} */
const expression = {
type: 'ExpressionTag',
start: value_start,
@ -559,7 +557,7 @@ function read_attribute(parser) {
const colon_index = name.indexOf(':');
const type = colon_index !== -1 && get_directive_type(name.slice(0, colon_index));
/** @type {true | Array<import('#compiler').Text | import('#compiler').ExpressionTag>} */
/** @type {true | Array<Compiler.Text | Compiler.ExpressionTag>} */
let value = true;
if (parser.eat('=')) {
parser.allow_whitespace();
@ -604,7 +602,7 @@ function read_attribute(parser) {
}
}
/** @type {import('#compiler').Directive} */
/** @type {Compiler.Directive} */
// @ts-expect-error TODO can't figure out this error
const directive = {
start,
@ -663,7 +661,7 @@ function get_directive_type(name) {
}
/**
* @param {import('../index.js').Parser} parser
* @param {Parser} parser
*/
function read_attribute_value(parser) {
const quote_mark = parser.eat("'") ? "'" : parser.eat('"') ? '"' : null;
@ -714,13 +712,13 @@ function read_attribute_value(parser) {
}
/**
* @param {import('../index.js').Parser} parser
* @param {Parser} parser
* @param {() => boolean} done
* @param {string} location
* @returns {any[]}
*/
function read_sequence(parser, done, location) {
/** @type {import('#compiler').Text} */
/** @type {Compiler.Text} */
let current_chunk = {
start: parser.index,
end: -1,
@ -730,7 +728,7 @@ function read_sequence(parser, done, location) {
parent: null
};
/** @type {Array<import('#compiler').Text | import('#compiler').ExpressionTag>} */
/** @type {Array<Compiler.Text | Compiler.ExpressionTag>} */
const chunks = [];
/** @param {number} end */
@ -768,7 +766,7 @@ function read_sequence(parser, done, location) {
parser.allow_whitespace();
parser.eat('}', true);
/** @type {import('#compiler').ExpressionTag} */
/** @type {Compiler.ExpressionTag} */
const chunk = {
type: 'ExpressionTag',
start: index,

@ -1,8 +1,9 @@
/** @import { Parser } from '../index.js' */
import element from './element.js';
import tag from './tag.js';
import text from './text.js';
/** @param {import('../index.js').Parser} parser */
/** @param {Parser} parser */
export default function fragment(parser) {
if (parser.match('<')) {
return element;

@ -1,6 +1,8 @@
/** @import { Text } from '#compiler' */
/** @import { Parser } from '../index.js' */
import { decode_character_references } from '../utils/html.js';
/** @param {import('../index.js').Parser} parser */
/** @param {Parser} parser */
export default function text(parser) {
const start = parser.index;
@ -10,7 +12,7 @@ export default function text(parser) {
data += parser.template[parser.index++];
}
/** @type {ReturnType<typeof parser.append<import('#compiler').Text>>} */
/** @type {ReturnType<typeof parser.append<Text>>} */
parser.append({
type: 'Text',
start,

@ -1,6 +1,7 @@
/** @import { Fragment } from '#compiler' */
/**
* @param {any} transparent
* @returns {import('#compiler').Fragment}
* @returns {Fragment}
*/
export function create_fragment(transparent = false) {
return {

@ -1,3 +1,7 @@
/** @import { Visitors } from 'zimmerframe' */
/** @import { AnalysisState } from './types.js' */
/** @import { Attribute, SvelteNode, TemplateNode, RegularElement, SvelteElement } 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
import { AXObjects, AXObjectRoles, elementAXObjects } from 'axobject-query';
@ -43,21 +47,21 @@ const interactive_roles = non_abstract_roles.filter(
);
/**
* @param {import('aria-query').ARIARoleDefinitionKey} role
* @param {ARIARoleDefinitionKey} role
*/
function is_non_interactive_roles(role) {
return non_interactive_roles.includes(role);
}
/**
* @param {import('aria-query').ARIARoleDefinitionKey} role
* @param {ARIARoleDefinitionKey} role
*/
function is_interactive_roles(role) {
return interactive_roles.includes(role);
}
/**
* @param {import('aria-query').ARIARoleDefinitionKey} role
* @param {ARIARoleDefinitionKey} role
*/
function is_abstract_role(role) {
return abstract_roles.includes(role);
@ -66,7 +70,7 @@ function is_abstract_role(role) {
const presentation_roles = ['presentation', 'none'];
/**
* @param {import('aria-query').ARIARoleDefinitionKey} role
* @param {ARIARoleDefinitionKey} role
*/
function is_presentation_role(role) {
return presentation_roles.includes(role);
@ -74,7 +78,7 @@ function is_presentation_role(role) {
/**
* @param {string} tag_name
* @param {Map<string, import('#compiler').Attribute>} attribute_map
* @param {Map<string, Attribute>} attribute_map
*/
function is_hidden_from_screen_reader(tag_name, attribute_map) {
if (tag_name === 'input') {
@ -92,7 +96,7 @@ function is_hidden_from_screen_reader(tag_name, attribute_map) {
}
/**
* @param {Map<string, import('#compiler').Attribute>} attribute_map
* @param {Map<string, Attribute>} attribute_map
*/
function has_disabled_attribute(attribute_map) {
const disabled_attr_value = get_static_value(attribute_map.get('disabled'));
@ -111,7 +115,7 @@ function has_disabled_attribute(attribute_map) {
}
/**
* @type {import('aria-query').ARIARoleRelationConcept[]}
* @type {ARIARoleRelationConcept[]}
*/
const non_interactive_element_role_schemas = [];
elementRoles.entries().forEach(([schema, roles]) => {
@ -121,7 +125,7 @@ elementRoles.entries().forEach(([schema, roles]) => {
});
/**
* @type {import('aria-query').ARIARoleRelationConcept[]}
* @type {ARIARoleRelationConcept[]}
*/
const interactive_element_role_schemas = [];
elementRoles.entries().forEach(([schema, roles]) => {
@ -137,7 +141,7 @@ const non_interactive_ax_objects = [...AXObjects.keys()].filter((name) =>
);
/**
* @type {import('aria-query').ARIARoleRelationConcept[]}
* @type {ARIARoleRelationConcept[]}
*/
const interactive_element_ax_object_schemas = [];
elementAXObjects.entries().forEach(
@ -152,7 +156,7 @@ elementAXObjects.entries().forEach(
);
/**
* @type {import('aria-query').ARIARoleRelationConcept[]}
* @type {ARIARoleRelationConcept[]}
*/
const non_interactive_element_ax_object_schemas = [];
elementAXObjects.entries().forEach(
@ -167,9 +171,9 @@ elementAXObjects.entries().forEach(
);
/**
* @param {import('aria-query').ARIARoleRelationConcept} schema
* @param {ARIARoleRelationConcept} schema
* @param {string} tag_name
* @param {Map<string, import('#compiler').Attribute>} attribute_map
* @param {Map<string, Attribute>} attribute_map
*/
function match_schema(schema, tag_name, attribute_map) {
if (schema.name !== tag_name) return false;
@ -192,7 +196,7 @@ const ElementInteractivity = /** @type {const} */ ({
/**
* @param {string} tag_name
* @param {Map<string, import('#compiler').Attribute>} attribute_map
* @param {Map<string, Attribute>} attribute_map
* @returns {ElementInteractivity[keyof ElementInteractivity]}
*/
function element_interactivity(tag_name, attribute_map) {
@ -228,7 +232,7 @@ function element_interactivity(tag_name, attribute_map) {
/**
* @param {string} tag_name
* @param {Map<string, import('#compiler').Attribute>} attribute_map
* @param {Map<string, Attribute>} attribute_map
* @returns {boolean}
*/
function is_interactive_element(tag_name, attribute_map) {
@ -237,7 +241,7 @@ function is_interactive_element(tag_name, attribute_map) {
/**
* @param {string} tag_name
* @param {Map<string, import('#compiler').Attribute>} attribute_map
* @param {Map<string, Attribute>} attribute_map
* @returns {boolean}
*/
function is_non_interactive_element(tag_name, attribute_map) {
@ -246,7 +250,7 @@ function is_non_interactive_element(tag_name, attribute_map) {
/**
* @param {string} tag_name
* @param {Map<string, import('#compiler').Attribute>} attribute_map
* @param {Map<string, Attribute>} attribute_map
* @returns {boolean}
*/
function is_static_element(tag_name, attribute_map) {
@ -254,9 +258,9 @@ function is_static_element(tag_name, attribute_map) {
}
/**
* @param {import('aria-query').ARIARoleDefinitionKey} role
* @param {ARIARoleDefinitionKey} role
* @param {string} tag_name
* @param {Map<string, import('#compiler').Attribute>} attribute_map
* @param {Map<string, Attribute>} attribute_map
*/
function is_semantic_role_element(role, tag_name, attribute_map) {
for (const [schema, ax_object] of elementAXObjects.entries()) {
@ -540,7 +544,7 @@ const a11y_non_interactive_element_to_interactive_role_exceptions = {
const combobox_if_list = ['email', 'search', 'tel', 'text', 'url'];
/** @param {Map<string, import('#compiler').Attribute>} attribute_map */
/** @param {Map<string, Attribute>} attribute_map */
function input_implicit_role(attribute_map) {
const type_attribute = attribute_map.get('type');
if (!type_attribute) return;
@ -553,7 +557,7 @@ function input_implicit_role(attribute_map) {
return input_type_to_implicit_role.get(type);
}
/** @param {Map<string, import('#compiler').Attribute>} attribute_map */
/** @param {Map<string, Attribute>} attribute_map */
function menuitem_implicit_role(attribute_map) {
const type_attribute = attribute_map.get('type');
if (!type_attribute) return;
@ -564,7 +568,7 @@ function menuitem_implicit_role(attribute_map) {
/**
* @param {string} name
* @param {Map<string, import('#compiler').Attribute>} attribute_map
* @param {Map<string, Attribute>} attribute_map
*/
function get_implicit_role(name, attribute_map) {
if (name === 'menuitem') {
@ -579,7 +583,7 @@ function get_implicit_role(name, attribute_map) {
const invisible_elements = ['meta', 'html', 'script', 'style'];
/**
* @param {import('#compiler').SvelteNode | null} parent
* @param {SvelteNode | null} parent
* @param {string[]} elements
*/
function is_parent(parent, elements) {
@ -588,15 +592,15 @@ function is_parent(parent, elements) {
if (parent.type === 'RegularElement') {
return elements.includes(parent.name);
}
parent = /** @type {import('#compiler').TemplateNode} */ (parent).parent;
parent = /** @type {TemplateNode} */ (parent).parent;
}
return false;
}
/**
* @param {import('#compiler').Attribute} attribute
* @param {import('aria-query').ARIAProperty} name
* @param {import('aria-query').ARIAPropertyDefinition} schema
* @param {Attribute} attribute
* @param {ARIAProperty} name
* @param {ARIAPropertyDefinition} schema
* @param {string | true | null} value
*/
function validate_aria_attribute_value(attribute, name, schema, value) {
@ -644,7 +648,7 @@ function validate_aria_attribute_value(attribute, name, schema, value) {
}
/**
* @param {import('#compiler').RegularElement |import('#compiler').SvelteElement} node
* @param {RegularElement |SvelteElement} node
* @param {string[]} attributes
* @param {string} name
*/
@ -660,7 +664,7 @@ function warn_missing_attribute(node, attributes, name = node.name) {
}
/**
* @param {import('#compiler').Attribute | undefined} attribute
* @param {Attribute | undefined} attribute
*/
function get_static_value(attribute) {
if (!attribute) return null;
@ -670,7 +674,7 @@ function get_static_value(attribute) {
}
/**
* @param {import('#compiler').Attribute | undefined} attribute
* @param {Attribute | undefined} attribute
*/
function get_static_text_value(attribute) {
const value = get_static_value(attribute);
@ -679,20 +683,20 @@ function get_static_text_value(attribute) {
}
/**
* @param {import('#compiler').RegularElement | import('#compiler').SvelteElement} node
* @param {import('./types.js').AnalysisState} state
* @param {RegularElement | SvelteElement} node
* @param {AnalysisState} state
*/
function check_element(node, state) {
// foreign namespace means elements can have completely different meanings, therefore we don't check them
if (state.options.namespace === 'foreign') return;
/** @type {Map<string, import('#compiler').Attribute>} */
/** @type {Map<string, Attribute>} */
const attribute_map = new Map();
/** @type {Set<string>} */
const handlers = new Set();
/** @type {import('#compiler').Attribute[]} */
/** @type {Attribute[]} */
const attributes = [];
const is_dynamic_element = node.type === 'SvelteElement';
@ -748,14 +752,9 @@ function check_element(node, state) {
// aria-proptypes
let value = get_static_value(attribute);
const schema = aria.get(/** @type {import('aria-query').ARIAProperty} */ (name));
const schema = aria.get(/** @type {ARIAProperty} */ (name));
if (schema !== undefined) {
validate_aria_attribute_value(
attribute,
/** @type {import('aria-query').ARIAProperty} */ (name),
schema,
value
);
validate_aria_attribute_value(attribute, /** @type {ARIAProperty} */ (name), schema, value);
}
// aria-activedescendant-has-tabindex
@ -779,8 +778,7 @@ function check_element(node, state) {
const value = get_static_value(attribute);
if (typeof value === 'string') {
for (const c_r of value.split(regex_whitespaces)) {
const current_role =
/** @type {import('aria-query').ARIARoleDefinitionKey} current_role */ (c_r);
const current_role = /** @type {ARIARoleDefinitionKey} current_role */ (c_r);
if (current_role && is_abstract_role(current_role)) {
w.a11y_no_abstract_role(attribute, current_role);
@ -899,9 +897,7 @@ function check_element(node, state) {
}
const role = attribute_map.get('role');
const role_static_value = /** @type {import('aria-query').ARIARoleDefinitionKey} */ (
get_static_text_value(role)
);
const role_static_value = /** @type {ARIARoleDefinitionKey} */ (get_static_text_value(role));
// click-events-have-key-events
if (handlers.has('click')) {
@ -922,7 +918,7 @@ function check_element(node, state) {
}
}
const role_value = /** @type {import('aria-query').ARIARoleDefinitionKey} */ (
const role_value = /** @type {ARIARoleDefinitionKey} */ (
role ? role_static_value : get_implicit_role(node.name, attribute_map)
);
@ -941,15 +937,11 @@ function check_element(node, state) {
// role-supports-aria-props
if (typeof role_value === 'string' && roles_map.has(role_value)) {
const { props } = /** @type {import('aria-query').ARIARoleDefinition} */ (
roles_map.get(role_value)
);
const { props } = /** @type {ARIARoleDefinition} */ (roles_map.get(role_value));
const invalid_aria_props = aria.keys().filter((attribute) => !(attribute in props));
const is_implicit = role_value && role === undefined;
for (const attr of attributes) {
if (
invalid_aria_props.includes(/** @type {import('aria-query').ARIAProperty} */ (attr.name))
) {
if (invalid_aria_props.includes(/** @type {ARIAProperty} */ (attr.name))) {
if (is_implicit) {
w.a11y_role_supports_aria_props_implicit(attr, attr.name, role_value, node.name);
} else {
@ -1075,7 +1067,7 @@ function check_element(node, state) {
}
if (node.name === 'label') {
/** @param {import('#compiler').TemplateNode} node */
/** @param {TemplateNode} node */
const has_input_child = (node) => {
let has = false;
walk(
@ -1112,7 +1104,7 @@ function check_element(node, state) {
return;
}
let has_caption = false;
const track = /** @type {import('#compiler').RegularElement | undefined} */ (
const track = /** @type {RegularElement | undefined} */ (
node.fragment.nodes.find((i) => i.type === 'RegularElement' && i.name === 'track')
);
if (track) {
@ -1164,7 +1156,7 @@ function check_element(node, state) {
}
/**
* @type {import('zimmerframe').Visitors<import('#compiler').SvelteNode, import('./types.js').AnalysisState>}
* @type {Visitors<SvelteNode, AnalysisState>}
*/
export const a11y_validators = {
RegularElement(node, context) {

@ -1,19 +1,22 @@
/** @import { ComponentAnalysis } from '../../types.js' */
/** @import { Css } from '#compiler' */
/** @import { Visitors } from 'zimmerframe' */
import { walk } from 'zimmerframe';
import * as e from '../../../errors.js';
import { is_keyframes_node } from '../../css.js';
import { merge } from '../../visitors.js';
/**
* @typedef {import('zimmerframe').Visitors<
* import('#compiler').Css.Node,
* @typedef {Visitors<
* Css.Node,
* {
* keyframes: string[];
* rule: import('#compiler').Css.Rule | null;
* rule: Css.Rule | null;
* }
* >} Visitors
* >} CssVisitors
*/
/** @param {import('#compiler').Css.RelativeSelector} relative_selector */
/** @param {Css.RelativeSelector} relative_selector */
function is_global(relative_selector) {
const first = relative_selector.selectors[0];
@ -27,7 +30,7 @@ function is_global(relative_selector) {
);
}
/** @type {Visitors} */
/** @type {CssVisitors} */
const analysis_visitors = {
Atrule(node, context) {
if (is_keyframes_node(node)) {
@ -102,7 +105,7 @@ const analysis_visitors = {
}
};
/** @type {Visitors} */
/** @type {CssVisitors} */
const validation_visitors = {
Rule(node, context) {
if (node.metadata.is_global_block) {
@ -178,7 +181,7 @@ const validation_visitors = {
}
},
NestingSelector(node, context) {
const rule = /** @type {import('#compiler').Css.Rule} */ (context.state.rule);
const rule = /** @type {Css.Rule} */ (context.state.rule);
if (!rule.metadata.parent_rule) {
e.css_nesting_selector_invalid_placement(node);
}
@ -188,8 +191,8 @@ const validation_visitors = {
const css_visitors = merge(analysis_visitors, validation_visitors);
/**
* @param {import('#compiler').Css.StyleSheet} stylesheet
* @param {import('../../types.js').ComponentAnalysis} analysis
* @param {Css.StyleSheet} stylesheet
* @param {ComponentAnalysis} analysis
*/
export function analyze_css(stylesheet, analysis) {
walk(stylesheet, { keyframes: analysis.css.keyframes, rule: null }, css_visitors);

@ -1,11 +1,13 @@
/** @import { Visitors } from 'zimmerframe' */
/** @import * as Compiler from '#compiler' */
import { walk } from 'zimmerframe';
import { get_possible_values } from './utils.js';
import { regex_ends_with_whitespace, regex_starts_with_whitespace } from '../../patterns.js';
/**
* @typedef {{
* stylesheet: import('#compiler').Css.StyleSheet;
* element: import('#compiler').RegularElement | import('#compiler').SvelteElement;
* stylesheet: Compiler.Css.StyleSheet;
* element: Compiler.RegularElement | Compiler.SvelteElement;
* }} State
*/
/** @typedef {NODE_PROBABLY_EXISTS | NODE_DEFINITELY_EXISTS} NodeExistsValue */
@ -18,7 +20,7 @@ const whitelist_attribute_selector = new Map([
['dialog', ['open']]
]);
/** @type {import('#compiler').Css.Combinator} */
/** @type {Compiler.Css.Combinator} */
const descendant_combinator = {
type: 'Combinator',
name: ' ',
@ -26,7 +28,7 @@ const descendant_combinator = {
end: -1
};
/** @type {import('#compiler').Css.RelativeSelector} */
/** @type {Compiler.Css.RelativeSelector} */
const nesting_selector = {
type: 'RelativeSelector',
start: -1,
@ -49,14 +51,14 @@ const nesting_selector = {
/**
*
* @param {import('#compiler').Css.StyleSheet} stylesheet
* @param {import('#compiler').RegularElement | import('#compiler').SvelteElement} element
* @param {Compiler.Css.StyleSheet} stylesheet
* @param {Compiler.RegularElement | Compiler.SvelteElement} element
*/
export function prune(stylesheet, element) {
walk(stylesheet, { stylesheet, element }, visitors);
}
/** @type {import('zimmerframe').Visitors<import('#compiler').Css.Node, State>} */
/** @type {Visitors<Compiler.Css.Node, State>} */
const visitors = {
Rule(node, context) {
if (node.metadata.is_global_block) {
@ -87,7 +89,7 @@ const visitors = {
if (
apply_selector(
selectors,
/** @type {import('#compiler').Css.Rule} */ (node.metadata.rule),
/** @type {Compiler.Css.Rule} */ (node.metadata.rule),
context.state.element,
context.state.stylesheet
)
@ -104,7 +106,7 @@ const visitors = {
/**
* Discard trailing `:global(...)` selectors, these are unused for scoping purposes
* @param {import('#compiler').Css.ComplexSelector} node
* @param {Compiler.Css.ComplexSelector} node
*/
function truncate(node) {
const i = node.children.findLastIndex(({ metadata }) => {
@ -115,10 +117,10 @@ function truncate(node) {
}
/**
* @param {import('#compiler').Css.RelativeSelector[]} relative_selectors
* @param {import('#compiler').Css.Rule} rule
* @param {import('#compiler').RegularElement | import('#compiler').SvelteElement} element
* @param {import('#compiler').Css.StyleSheet} stylesheet
* @param {Compiler.Css.RelativeSelector[]} relative_selectors
* @param {Compiler.Css.Rule} rule
* @param {Compiler.RegularElement | Compiler.SvelteElement} element
* @param {Compiler.Css.StyleSheet} stylesheet
* @returns {boolean}
*/
function apply_selector(relative_selectors, rule, element, stylesheet) {
@ -144,7 +146,7 @@ function apply_selector(relative_selectors, rule, element, stylesheet) {
switch (name) {
case ' ':
case '>': {
let parent = /** @type {import('#compiler').TemplateNode | null} */ (element.parent);
let parent = /** @type {Compiler.TemplateNode | null} */ (element.parent);
let parent_matched = false;
let crossed_component_boundary = false;
@ -167,7 +169,7 @@ function apply_selector(relative_selectors, rule, element, stylesheet) {
if (name === '>') return parent_matched;
}
parent = /** @type {import('#compiler').TemplateNode | null} */ (parent.parent);
parent = /** @type {Compiler.TemplateNode | null} */ (parent.parent);
}
return parent_matched || parent_selectors.every((selector) => is_global(selector, rule));
@ -218,8 +220,8 @@ function apply_selector(relative_selectors, rule, element, stylesheet) {
/**
* Mark both the compound selector and the node it selects as encapsulated,
* for transformation in a later step
* @param {import('#compiler').Css.RelativeSelector} relative_selector
* @param {import('#compiler').RegularElement | import('#compiler').SvelteElement} element
* @param {Compiler.Css.RelativeSelector} relative_selector
* @param {Compiler.RegularElement | Compiler.SvelteElement} element
*/
function mark(relative_selector, element) {
relative_selector.metadata.scoped = true;
@ -231,8 +233,8 @@ function mark(relative_selector, element) {
* it's a `:global(...)` or unscopeable selector, or
* is an `:is(...)` or `:where(...)` selector that contains
* a global selector
* @param {import('#compiler').Css.RelativeSelector} selector
* @param {import('#compiler').Css.Rule} rule
* @param {Compiler.Css.RelativeSelector} selector
* @param {Compiler.Css.Rule} rule
*/
function is_global(selector, rule) {
if (selector.metadata.is_global || selector.metadata.is_global_like) {
@ -240,7 +242,7 @@ function is_global(selector, rule) {
}
for (const s of selector.selectors) {
/** @type {import('#compiler').Css.SelectorList | null} */
/** @type {Compiler.Css.SelectorList | null} */
let selector_list = null;
let owner = rule;
@ -251,7 +253,7 @@ function is_global(selector, rule) {
}
if (s.type === 'NestingSelector') {
owner = /** @type {import('#compiler').Css.Rule} */ (rule.metadata.parent_rule);
owner = /** @type {Compiler.Css.Rule} */ (rule.metadata.parent_rule);
selector_list = owner.prelude;
}
@ -274,10 +276,10 @@ const regex_backslash_and_following_character = /\\(.)/g;
/**
* Ensure that `element` satisfies each simple selector in `relative_selector`
*
* @param {import('#compiler').Css.RelativeSelector} relative_selector
* @param {import('#compiler').Css.Rule} rule
* @param {import('#compiler').RegularElement | import('#compiler').SvelteElement} element
* @param {import('#compiler').Css.StyleSheet} stylesheet
* @param {Compiler.Css.RelativeSelector} relative_selector
* @param {Compiler.Css.Rule} rule
* @param {Compiler.RegularElement | Compiler.SvelteElement} element
* @param {Compiler.Css.StyleSheet} stylesheet
* @returns {boolean}
*/
function relative_selector_might_apply_to_node(relative_selector, rule, element, stylesheet) {
@ -293,7 +295,7 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
}
if (name === 'global' && relative_selector.selectors.length === 1) {
const args = /** @type {import('#compiler').Css.SelectorList} */ (selector.args);
const args = /** @type {Compiler.Css.SelectorList} */ (selector.args);
const complex_selector = args.children[0];
return apply_selector(complex_selector.children, rule, element, stylesheet);
}
@ -373,7 +375,7 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
case 'NestingSelector': {
let matched = false;
const parent = /** @type {import('#compiler').Css.Rule} */ (rule.metadata.parent_rule);
const parent = /** @type {Compiler.Css.Rule} */ (rule.metadata.parent_rule);
for (const complex_selector of parent.prelude.children) {
if (apply_selector(truncate(complex_selector), parent, element, stylesheet)) {
@ -425,7 +427,7 @@ function test_attribute(operator, expected_value, case_insensitive, value) {
}
/**
* @param {import('#compiler').RegularElement | import('#compiler').SvelteElement} node
* @param {Compiler.RegularElement | Compiler.SvelteElement} node
* @param {string} name
* @param {string | null} expected_value
* @param {string | null} operator
@ -535,11 +537,11 @@ function unquote(str) {
}
/**
* @param {import('#compiler').RegularElement | import('#compiler').SvelteElement} node
* @returns {import('#compiler').RegularElement | import('#compiler').SvelteElement | null}
* @param {Compiler.RegularElement | Compiler.SvelteElement} node
* @returns {Compiler.RegularElement | Compiler.SvelteElement | null}
*/
function get_element_parent(node) {
/** @type {import('#compiler').SvelteNode | null} */
/** @type {Compiler.SvelteNode | null} */
let parent = node;
while (
// @ts-expect-error TODO figure out a more elegant solution
@ -569,11 +571,11 @@ function get_element_parent(node) {
* <h1>Heading 1</h1>
* <h2>Heading 2</h2>
* ```
* @param {import('#compiler').SvelteNode} node
* @returns {import('#compiler').SvelteNode}
* @param {Compiler.SvelteNode} node
* @returns {Compiler.SvelteNode}
*/
function find_previous_sibling(node) {
/** @type {import('#compiler').SvelteNode} */
/** @type {Compiler.SvelteNode} */
let current_node = node;
while (
@ -602,15 +604,15 @@ function find_previous_sibling(node) {
}
/**
* @param {import('#compiler').SvelteNode} node
* @param {Compiler.SvelteNode} node
* @param {boolean} adjacent_only
* @returns {Map<import('#compiler').RegularElement | import('#compiler').SvelteElement | import('#compiler').SlotElement | import('#compiler').RenderTag, NodeExistsValue>}
* @returns {Map<Compiler.RegularElement | Compiler.SvelteElement | Compiler.SlotElement | Compiler.RenderTag, NodeExistsValue>}
*/
function get_possible_element_siblings(node, adjacent_only) {
/** @type {Map<import('#compiler').RegularElement | import('#compiler').SvelteElement | import('#compiler').SlotElement | import('#compiler').RenderTag, NodeExistsValue>} */
/** @type {Map<Compiler.RegularElement | Compiler.SvelteElement | Compiler.SlotElement | Compiler.RenderTag, NodeExistsValue>} */
const result = new Map();
/** @type {import('#compiler').SvelteNode} */
/** @type {Compiler.SvelteNode} */
let prev = node;
while ((prev = find_previous_sibling(prev))) {
if (prev.type === 'RegularElement') {
@ -642,7 +644,7 @@ function get_possible_element_siblings(node, adjacent_only) {
}
if (!prev || !adjacent_only) {
/** @type {import('#compiler').SvelteNode | null} */
/** @type {Compiler.SvelteNode | null} */
let parent = node;
while (
@ -669,12 +671,12 @@ function get_possible_element_siblings(node, adjacent_only) {
}
/**
* @param {import('#compiler').EachBlock | import('#compiler').IfBlock | import('#compiler').AwaitBlock} relative_selector
* @param {Compiler.EachBlock | Compiler.IfBlock | Compiler.AwaitBlock} relative_selector
* @param {boolean} adjacent_only
* @returns {Map<import('#compiler').RegularElement, NodeExistsValue>}
* @returns {Map<Compiler.RegularElement, NodeExistsValue>}
*/
function get_possible_last_child(relative_selector, adjacent_only) {
/** @typedef {Map<import('#compiler').RegularElement, NodeExistsValue>} NodeMap */
/** @typedef {Map<Compiler.RegularElement, NodeExistsValue>} NodeMap */
/** @type {NodeMap} */
const result = new Map();
@ -776,7 +778,7 @@ function higher_existence(exist1, exist2) {
return exist1 > exist2 ? exist1 : exist2;
}
/** @param {Map<import('#compiler').RegularElement, NodeExistsValue>} result */
/** @param {Map<Compiler.RegularElement, NodeExistsValue>} result */
function mark_as_probably(result) {
for (const key of result.keys()) {
result.set(key, NODE_PROBABLY_EXISTS);
@ -784,11 +786,11 @@ function mark_as_probably(result) {
}
/**
* @param {import('#compiler').SvelteNode[]} children
* @param {Compiler.SvelteNode[]} children
* @param {boolean} adjacent_only
*/
function loop_child(children, adjacent_only) {
/** @type {Map<import('#compiler').RegularElement, NodeExistsValue>} */
/** @type {Map<Compiler.RegularElement, NodeExistsValue>} */
const result = new Map();
for (let i = children.length - 1; i >= 0; i--) {
const child = children[i];

@ -1,15 +1,17 @@
/** @import { Visitors } from 'zimmerframe' */
/** @import { Css } from '#compiler' */
import { walk } from 'zimmerframe';
import * as w from '../../../warnings.js';
import { is_keyframes_node } from '../../css.js';
/**
* @param {import('#compiler').Css.StyleSheet} stylesheet
* @param {Css.StyleSheet} stylesheet
*/
export function warn_unused(stylesheet) {
walk(stylesheet, { stylesheet }, visitors);
}
/** @type {import('zimmerframe').Visitors<import('#compiler').Css.Node, { stylesheet: import('#compiler').Css.StyleSheet }>} */
/** @type {Visitors<Css.Node, { stylesheet: Css.StyleSheet }>} */
const visitors = {
Atrule(node, context) {
if (!is_keyframes_node(node)) {

@ -1,7 +1,9 @@
/** @import { Text, ExpressionTag } from '#compiler' */
/** @import { Node } from 'estree' */
const UNKNOWN = {};
/**
* @param {import('estree').Node} node
* @param {Node} node
* @param {Set<any>} set
*/
function gather_possible_values(node, set) {
@ -16,7 +18,7 @@ function gather_possible_values(node, set) {
}
/**
* @param {import('#compiler').Text | import('#compiler').ExpressionTag} chunk
* @param {Text | ExpressionTag} chunk
* @returns {Set<string> | null}
*/
export function get_possible_values(chunk) {

@ -1,3 +1,7 @@
/** @import * as ESTree from 'estree' */
/** @import { ValidatedCompileOptions, SvelteNode, ValidatedModuleCompileOptions } from '#compiler' */
/** @import { ComponentAnalysis, Analysis } from '../../types' */
/** @import { Visitors, ComponentClientTransformState, ClientTransformState } from './types' */
import { walk } from 'zimmerframe';
import * as b from '../../../utils/builders.js';
import { set_scope } from '../../scope.js';
@ -12,8 +16,8 @@ import { filename } from '../../../state.js';
/**
* This function ensures visitor sets don't accidentally clobber each other
* @param {...import('./types').Visitors} array
* @returns {import('./types').Visitors}
* @param {...Visitors} array
* @returns {Visitors}
*/
function combine_visitors(...array) {
/** @type {Record<string, any>} */
@ -35,12 +39,12 @@ function combine_visitors(...array) {
/**
* @param {string} source
* @param {import('../../types').ComponentAnalysis} analysis
* @param {import('#compiler').ValidatedCompileOptions} options
* @returns {import('estree').Program}
* @param {ComponentAnalysis} analysis
* @param {ValidatedCompileOptions} options
* @returns {ESTree.Program}
*/
export function client_component(source, analysis, options) {
/** @type {import('./types').ComponentClientTransformState} */
/** @type {ComponentClientTransformState} */
const state = {
analysis,
options,
@ -72,9 +76,9 @@ export function client_component(source, analysis, options) {
locations: /** @type {any} */ (null)
};
const module = /** @type {import('estree').Program} */ (
const module = /** @type {ESTree.Program} */ (
walk(
/** @type {import('#compiler').SvelteNode} */ (analysis.module.ast),
/** @type {SvelteNode} */ (analysis.module.ast),
state,
combine_visitors(
set_scope(analysis.module.scopes),
@ -87,9 +91,9 @@ export function client_component(source, analysis, options) {
);
const instance_state = { ...state, scope: analysis.instance.scope };
const instance = /** @type {import('estree').Program} */ (
const instance = /** @type {ESTree.Program} */ (
walk(
/** @type {import('#compiler').SvelteNode} */ (analysis.instance.ast),
/** @type {SvelteNode} */ (analysis.instance.ast),
instance_state,
combine_visitors(
set_scope(analysis.instance.scopes),
@ -114,9 +118,9 @@ export function client_component(source, analysis, options) {
)
);
const template = /** @type {import('estree').Program} */ (
const template = /** @type {ESTree.Program} */ (
walk(
/** @type {import('#compiler').SvelteNode} */ (analysis.template.ast),
/** @type {SvelteNode} */ (analysis.template.ast),
{ ...state, scope: analysis.instance.scope },
combine_visitors(
set_scope(analysis.template.scopes),
@ -138,10 +142,10 @@ export function client_component(source, analysis, options) {
}
}
/** @type {import('estree').Statement[]} */
/** @type {ESTree.Statement[]} */
const store_setup = [];
/** @type {import('estree').VariableDeclaration[]} */
/** @type {ESTree.VariableDeclaration[]} */
const legacy_reactive_declarations = [];
for (const [name, binding] of analysis.instance.scope.declarations) {
@ -193,14 +197,14 @@ export function client_component(source, analysis, options) {
/**
* Used to store the group nodes
* @type {import('estree').VariableDeclaration[]}
* @type {ESTree.VariableDeclaration[]}
*/
const group_binding_declarations = [];
for (const group of analysis.binding_groups.values()) {
group_binding_declarations.push(b.const(group.name, b.array([])));
}
/** @type {Array<import('estree').Property | import('estree').SpreadElement>} */
/** @type {Array<ESTree.Property | ESTree.SpreadElement>} */
const component_returned_object = analysis.exports.map(({ name, alias }) => {
const expression = serialize_get_binding(b.id(name), instance_state);
@ -218,7 +222,7 @@ export function client_component(source, analysis, options) {
if (analysis.runes && options.dev) {
const exports = analysis.exports.map(({ name, alias }) => b.literal(alias ?? name));
/** @type {import('estree').Literal[]} */
/** @type {ESTree.Literal[]} */
const bindable = [];
for (const [name, binding] of properties) {
if (binding.kind === 'bindable_prop') {
@ -254,7 +258,7 @@ export function client_component(source, analysis, options) {
setter.value.params[0] = {
type: 'AssignmentPattern',
left: b.id('$$value'),
right: /** @type {import('estree').Expression} */ (binding.initial)
right: /** @type {ESTree.Expression} */ (binding.initial)
};
}
@ -290,9 +294,9 @@ export function client_component(source, analysis, options) {
...legacy_reactive_declarations,
...group_binding_declarations,
...analysis.top_level_snippets,
.../** @type {import('estree').Statement[]} */ (instance.body),
.../** @type {ESTree.Statement[]} */ (instance.body),
analysis.runes || !analysis.needs_context ? b.empty : b.stmt(b.call('$.init')),
.../** @type {import('estree').Statement[]} */ (template.body)
.../** @type {ESTree.Statement[]} */ (template.body)
]);
if (!analysis.runes) {
@ -480,7 +484,7 @@ export function client_component(source, analysis, options) {
if (analysis.custom_element) {
const ce = analysis.custom_element;
/** @type {import('estree').Property[]} */
/** @type {ESTree.Property[]} */
const props_str = [];
for (const [name, binding] of properties) {
@ -495,7 +499,7 @@ export function client_component(source, analysis, options) {
}
const value = b.object(
/** @type {import('estree').Property[]} */ (
/** @type {ESTree.Property[]} */ (
[
prop_def.attribute ? b.init('attribute', b.literal(prop_def.attribute)) : undefined,
prop_def.reflect ? b.init('reflect', b.literal(true)) : undefined,
@ -539,12 +543,12 @@ export function client_component(source, analysis, options) {
}
/**
* @param {import('../../types').Analysis} analysis
* @param {import('#compiler').ValidatedModuleCompileOptions} options
* @returns {import('estree').Program}
* @param {Analysis} analysis
* @param {ValidatedModuleCompileOptions} options
* @returns {ESTree.Program}
*/
export function client_module(analysis, options) {
/** @type {import('./types').ClientTransformState} */
/** @type {ClientTransformState} */
const state = {
analysis,
options,
@ -556,9 +560,9 @@ export function client_module(analysis, options) {
in_constructor: false
};
const module = /** @type {import('estree').Program} */ (
const module = /** @type {ESTree.Program} */ (
walk(
/** @type {import('#compiler').SvelteNode} */ (analysis.module.ast),
/** @type {SvelteNode} */ (analysis.module.ast),
state,
combine_visitors(
set_scope(analysis.module.scopes),

@ -1,3 +1,7 @@
/** @import { Binding, ReactiveStatement } from '#compiler' */
/** @import { ComponentVisitors } from '../types.js' */
/** @import { Scope } from '../../../scope.js' */
/** @import { VariableDeclarator, Expression, Identifier, Statement } from 'estree' */
import { is_hoistable_function } from '../../utils.js';
import * as b from '../../../../utils/builders.js';
import { extract_paths } from '../../../../utils/ast.js';
@ -5,9 +9,9 @@ import { get_prop_source, serialize_get_binding } from '../utils.js';
/**
* Creates the output for a state declaration.
* @param {import('estree').VariableDeclarator} declarator
* @param {import('../../../scope.js').Scope} scope
* @param {import('estree').Expression} value
* @param {VariableDeclarator} declarator
* @param {Scope} scope
* @param {Expression} value
*/
function create_state_declarators(declarator, scope, value) {
if (declarator.id.type === 'Identifier') {
@ -20,7 +24,7 @@ function create_state_declarators(declarator, scope, value) {
b.declarator(b.id(tmp), value),
...paths.map((path) => {
const value = path.expression?.(b.id(tmp));
const binding = scope.get(/** @type {import('estree').Identifier} */ (path.node).name);
const binding = scope.get(/** @type {Identifier} */ (path.node).name);
return b.declarator(
path.node,
binding?.kind === 'state' ? b.call('$.mutable_source', value) : value
@ -29,16 +33,14 @@ function create_state_declarators(declarator, scope, value) {
];
}
/** @type {import('../types.js').ComponentVisitors} */
/** @type {ComponentVisitors} */
export const javascript_visitors_legacy = {
VariableDeclaration(node, { state, visit }) {
/** @type {import('estree').VariableDeclarator[]} */
/** @type {VariableDeclarator[]} */
const declarations = [];
for (const declarator of node.declarations) {
const bindings = /** @type {import('#compiler').Binding[]} */ (
state.scope.get_bindings(declarator)
);
const bindings = /** @type {Binding[]} */ (state.scope.get_bindings(declarator));
const has_state = bindings.some((binding) => binding.kind === 'state');
const has_props = bindings.some((binding) => binding.kind === 'bindable_prop');
@ -47,15 +49,11 @@ export const javascript_visitors_legacy = {
if (init != null && is_hoistable_function(init)) {
const hoistable_function = visit(init);
state.hoisted.push(
b.declaration(
'const',
declarator.id,
/** @type {import('estree').Expression} */ (hoistable_function)
)
b.declaration('const', declarator.id, /** @type {Expression} */ (hoistable_function))
);
continue;
}
declarations.push(/** @type {import('estree').VariableDeclarator} */ (visit(declarator)));
declarations.push(/** @type {VariableDeclarator} */ (visit(declarator)));
continue;
}
@ -68,14 +66,12 @@ export const javascript_visitors_legacy = {
declarations.push(
b.declarator(
b.id(tmp),
/** @type {import('estree').Expression} */ (
visit(/** @type {import('estree').Expression} */ (declarator.init))
)
/** @type {Expression} */ (visit(/** @type {Expression} */ (declarator.init)))
)
);
for (const path of paths) {
const name = /** @type {import('estree').Identifier} */ (path.node).name;
const binding = /** @type {import('#compiler').Binding} */ (state.scope.get(name));
const name = /** @type {Identifier} */ (path.node).name;
const binding = /** @type {Binding} */ (state.scope.get(name));
const value = path.expression?.(b.id(tmp));
declarations.push(
b.declarator(
@ -89,9 +85,7 @@ export const javascript_visitors_legacy = {
continue;
}
const binding = /** @type {import('#compiler').Binding} */ (
state.scope.get(declarator.id.name)
);
const binding = /** @type {Binding} */ (state.scope.get(declarator.id.name));
declarations.push(
b.declarator(
@ -100,7 +94,7 @@ export const javascript_visitors_legacy = {
binding,
state,
binding.prop_alias ?? declarator.id.name,
declarator.init && /** @type {import('estree').Expression} */ (visit(declarator.init))
declarator.init && /** @type {Expression} */ (visit(declarator.init))
)
)
);
@ -112,7 +106,7 @@ export const javascript_visitors_legacy = {
...create_state_declarators(
declarator,
state.scope,
/** @type {import('estree').Expression} */ (declarator.init && visit(declarator.init))
/** @type {Expression} */ (declarator.init && visit(declarator.init))
)
);
}
@ -135,7 +129,7 @@ export const javascript_visitors_legacy = {
const state = context.state;
// To recreate Svelte 4 behaviour, we track the dependencies
// the compiler can 'see', but we untrack the effect itself
const reactive_stmt = /** @type {import('#compiler').ReactiveStatement} */ (
const reactive_stmt = /** @type {ReactiveStatement} */ (
state.analysis.reactive_statements.get(node)
);
@ -143,7 +137,7 @@ export const javascript_visitors_legacy = {
const { dependencies } = reactive_stmt;
let serialized_body = /** @type {import('estree').Statement} */ (context.visit(node.body));
let serialized_body = /** @type {Statement} */ (context.visit(node.body));
if (serialized_body.type !== 'BlockStatement') {
serialized_body = b.block([serialized_body]);
@ -151,7 +145,7 @@ export const javascript_visitors_legacy = {
const body = serialized_body.body;
/** @type {import('estree').Expression[]} */
/** @type {Expression[]} */
const sequence = [];
for (const binding of dependencies) {
if (binding.kind === 'normal') continue;

@ -1,7 +1,9 @@
/** @import { FunctionDeclaration } from 'estree' */
/** @import { ComponentVisitors } from '../types.js' */
import * as b from '../../../../utils/builders.js';
import { function_visitor, serialize_hoistable_params } from '../utils.js';
/** @type {import('../types.js').ComponentVisitors} */
/** @type {ComponentVisitors} */
export const javascript_visitors = {
FunctionExpression: function_visitor,
ArrowFunctionExpression: function_visitor,
@ -14,7 +16,7 @@ export const javascript_visitors = {
const params = serialize_hoistable_params(node, context);
context.state.hoisted.push(
/** @type {import('estree').FunctionDeclaration} */ ({
/** @type {FunctionDeclaration} */ ({
...node,
id: node.id !== null ? context.visit(node.id, state) : null,
params,

@ -1,3 +1,6 @@
/** @import { Visitors } from 'zimmerframe' */
/** @import { ValidatedCompileOptions, Css } from '#compiler' */
/** @import { ComponentAnalysis } from '../../types.js' */
import MagicString from 'magic-string';
import { walk } from 'zimmerframe';
import { is_keyframes_node, regex_css_name_boundary, remove_css_prefix } from '../../css.js';
@ -19,8 +22,8 @@ import { merge_with_preprocessor_map } from '../../../utils/mapped_code.js';
/**
*
* @param {string} source
* @param {import('../../types.js').ComponentAnalysis} analysis
* @param {import('#compiler').ValidatedCompileOptions} options
* @param {ComponentAnalysis} analysis
* @param {ValidatedCompileOptions} options
*/
export function render_stylesheet(source, analysis, options) {
const code = new MagicString(source);
@ -37,9 +40,9 @@ export function render_stylesheet(source, analysis, options) {
}
};
const ast = /** @type {import('#compiler').Css.StyleSheet} */ (analysis.css.ast);
const ast = /** @type {Css.StyleSheet} */ (analysis.css.ast);
walk(/** @type {import('#compiler').Css.Node} */ (ast), state, visitors);
walk(/** @type {Css.Node} */ (ast), state, visitors);
code.remove(0, ast.content.start);
code.remove(/** @type {number} */ (ast.content.end), source.length);
@ -64,7 +67,7 @@ export function render_stylesheet(source, analysis, options) {
return css;
}
/** @type {import('zimmerframe').Visitors<import('#compiler').Css.Node, State>} */
/** @type {Visitors<Css.Node, State>} */
const visitors = {
_: (node, context) => {
context.state.code.addSourcemapLocation(node.start);
@ -196,7 +199,7 @@ const visitors = {
if (parent?.type === 'Rule') {
specificity = { bumped: false };
/** @type {import('#compiler').Css.Rule | null} */
/** @type {Css.Rule | null} */
let rule = parent.metadata.parent_rule;
while (rule) {
@ -213,7 +216,7 @@ const visitors = {
ComplexSelector(node, context) {
const before_bumped = context.state.specificity.bumped;
/** @param {import('#compiler').Css.SimpleSelector} selector */
/** @param {Css.SimpleSelector} selector */
function remove_global_pseudo_class(selector) {
context.state.code
.remove(selector.start, selector.start + ':global('.length)
@ -293,7 +296,7 @@ const visitors = {
}
};
/** @param {import('#compiler').Css.Rule} rule */
/** @param {Css.Rule} rule */
function is_empty(rule) {
if (rule.metadata.is_global_block) {
return rule.block.children.length === 0;
@ -316,7 +319,7 @@ function is_empty(rule) {
return true;
}
/** @param {import('#compiler').Css.Rule} rule */
/** @param {Css.Rule} rule */
function is_used(rule) {
for (const selector of rule.prelude.children) {
if (selector.metadata.used) return true;
@ -335,7 +338,7 @@ function is_used(rule) {
/**
*
* @param {import('#compiler').Css.Rule} node
* @param {Css.Rule} node
* @param {MagicString} code
*/
function escape_comment_close(node, code) {

@ -1,3 +1,5 @@
/** @import { ValidatedCompileOptions, CompileResult, ValidatedModuleCompileOptions } from '#compiler' */
/** @import { ComponentAnalysis, Analysis } from '../types' */
import { print } from 'esrap';
import { VERSION } from '../../../version.js';
import { server_component, server_module } from './server/transform-server.js';
@ -7,10 +9,10 @@ import { merge_with_preprocessor_map, get_source_name } from '../../utils/mapped
import * as state from '../../state.js';
/**
* @param {import('../types').ComponentAnalysis} analysis
* @param {ComponentAnalysis} analysis
* @param {string} source
* @param {import('#compiler').ValidatedCompileOptions} options
* @returns {import('#compiler').CompileResult}
* @param {ValidatedCompileOptions} options
* @returns {CompileResult}
*/
export function transform_component(analysis, source, options) {
if (options.generate === false) {
@ -55,10 +57,10 @@ export function transform_component(analysis, source, options) {
}
/**
* @param {import('../types').Analysis} analysis
* @param {Analysis} analysis
* @param {string} source
* @param {import('#compiler').ValidatedModuleCompileOptions} options
* @returns {import('#compiler').CompileResult}
* @param {ValidatedModuleCompileOptions} options
* @returns {CompileResult}
*/
export function transform_module(analysis, source, options) {
if (options.generate === false) {

@ -1,3 +1,7 @@
/** @import { Context } from 'zimmerframe' */
/** @import { TransformState } from './types.js' */
/** @import * as Compiler from '#compiler' */
/** @import { Node, Expression, CallExpression } from 'estree' */
import {
regex_ends_with_whitespaces,
regex_not_whitespace,
@ -12,7 +16,7 @@ import is_reference from 'is-reference';
import { set_scope } from '../scope.js';
/**
* @param {import('estree').Node} node
* @param {Node} node
* @returns {boolean}
*/
export function is_hoistable_function(node) {
@ -28,20 +32,20 @@ export function is_hoistable_function(node) {
/**
* Match Svelte 4 behaviour by sorting ConstTag nodes in topological order
* @param {import("#compiler").SvelteNode[]} nodes
* @param {import('./types.js').TransformState} state
* @param {Compiler.SvelteNode[]} nodes
* @param {TransformState} state
*/
function sort_const_tags(nodes, state) {
/**
* @typedef {{
* node: import('#compiler').ConstTag;
* deps: Set<import('#compiler').Binding>;
* node: Compiler.ConstTag;
* deps: Set<Compiler.Binding>;
* }} Tag
*/
const other = [];
/** @type {Map<import('#compiler').Binding, Tag>} */
/** @type {Map<Compiler.Binding, Tag>} */
const tags = new Map();
const { _ } = set_scope(state.scopes);
@ -51,16 +55,16 @@ function sort_const_tags(nodes, state) {
const declaration = node.declaration.declarations[0];
const bindings = extract_identifiers(declaration.id).map((id) => {
return /** @type {import('#compiler').Binding} */ (state.scope.get(id.name));
return /** @type {Compiler.Binding} */ (state.scope.get(id.name));
});
/** @type {Set<import('#compiler').Binding>} */
/** @type {Set<Compiler.Binding>} */
const deps = new Set();
walk(declaration.init, state, {
_,
Identifier(node, context) {
const parent = /** @type {import('estree').Expression} */ (context.path.at(-1));
const parent = /** @type {Expression} */ (context.path.at(-1));
if (is_reference(node, parent)) {
const binding = context.state.scope.get(node.name);
@ -81,7 +85,7 @@ function sort_const_tags(nodes, state) {
return nodes;
}
/** @type {Array<[import('#compiler').Binding, import('#compiler').Binding]>} */
/** @type {Array<[Compiler.Binding, Compiler.Binding]>} */
const edges = [];
for (const [id, tag] of tags) {
@ -98,7 +102,7 @@ function sort_const_tags(nodes, state) {
e.const_tag_cycle(tag.node, cycle.map((binding) => binding.node.name).join(' → '));
}
/** @type {import('#compiler').ConstTag[]} */
/** @type {Compiler.ConstTag[]} */
const sorted = [];
/** @param {Tag} tag */
@ -129,11 +133,11 @@ 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 {import('#compiler').SvelteNode} parent
* @param {import('#compiler').SvelteNode[]} nodes
* @param {import('#compiler').SvelteNode[]} path
* @param {import('#compiler').Namespace} namespace
* @param {import('./types.js').TransformState} state
* @param {Compiler.SvelteNode} parent
* @param {Compiler.SvelteNode[]} nodes
* @param {Compiler.SvelteNode[]} path
* @param {Compiler.Namespace} namespace
* @param {TransformState} state
* @param {boolean} preserve_whitespace
* @param {boolean} preserve_comments
*/
@ -153,10 +157,10 @@ export function clean_nodes(
nodes = sort_const_tags(nodes, state);
}
/** @type {import('#compiler').SvelteNode[]} */
/** @type {Compiler.SvelteNode[]} */
const hoisted = [];
/** @type {import('#compiler').SvelteNode[]} */
/** @type {Compiler.SvelteNode[]} */
const regular = [];
for (const node of nodes) {
@ -220,7 +224,7 @@ export function clean_nodes(
parent.name === 'colgroup' ||
parent.name === 'datalist'));
/** @type {import('#compiler').SvelteNode[]} */
/** @type {Compiler.SvelteNode[]} */
const trimmed = [];
// Replace any whitespace between a text and non-text node with a single spaceand keep whitespace
@ -262,9 +266,9 @@ export function clean_nodes(
/**
* Infers the namespace for the children of a node that should be used when creating the `$.template(...)`.
* @param {import('#compiler').Namespace} namespace
* @param {import('#compiler').SvelteNode} parent
* @param {import('#compiler').SvelteNode[]} nodes
* @param {Compiler.Namespace} namespace
* @param {Compiler.SvelteNode} parent
* @param {Compiler.SvelteNode[]} nodes
*/
export function infer_namespace(namespace, parent, nodes) {
if (namespace !== 'foreign') {
@ -303,12 +307,12 @@ 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 {import('#compiler').SvelteNode[]} nodes
* @param {import('#compiler').Namespace | 'keep' | 'maybe_html'} namespace
* @param {Compiler.SvelteNode[]} nodes
* @param {Compiler.Namespace | 'keep' | 'maybe_html'} namespace
*/
function check_nodes_for_namespace(nodes, namespace) {
/**
* @param {import('#compiler').SvelteElement | import('#compiler').RegularElement} node}
* @param {Compiler.SvelteElement | Compiler.RegularElement} node}
* @param {{stop: () => void}} context
*/
const RegularElement = (node, { stop }) => {
@ -357,9 +361,9 @@ function check_nodes_for_namespace(nodes, namespace) {
/**
* Determines the namespace the children of this node are in.
* @param {import('#compiler').RegularElement | import('#compiler').SvelteElement} node
* @param {import('#compiler').Namespace} namespace
* @returns {import('#compiler').Namespace}
* @param {Compiler.RegularElement | Compiler.SvelteElement} node
* @param {Compiler.Namespace} namespace
* @returns {Compiler.Namespace}
*/
export function determine_namespace_for_children(node, namespace) {
if (namespace === 'foreign') {
@ -378,9 +382,9 @@ export function determine_namespace_for_children(node, namespace) {
}
/**
* @template {import('./types.js').TransformState} T
* @param {import('estree').CallExpression} node
* @param {import('zimmerframe').Context<any, T>} context
* @template {TransformState} T
* @param {CallExpression} node
* @param {Context<any, T>} context
*/
export function transform_inspect_rune(node, context) {
const { state, visit } = context;
@ -389,12 +393,11 @@ export function transform_inspect_rune(node, context) {
if (!state.options.dev) return b.unary('void', b.literal(0));
if (node.callee.type === 'MemberExpression') {
const raw_inspect_args = /** @type {import('estree').CallExpression} */ (node.callee.object)
.arguments;
const raw_inspect_args = /** @type {CallExpression} */ (node.callee.object).arguments;
const inspect_args =
/** @type {Array<import('estree').Expression>} */
/** @type {Array<Expression>} */
(raw_inspect_args.map((arg) => visit(arg)));
const with_arg = /** @type {import('estree').Expression} */ (visit(node.arguments[0]));
const with_arg = /** @type {Expression} */ (visit(node.arguments[0]));
return b.call(
'$.inspect',
@ -402,9 +405,7 @@ export function transform_inspect_rune(node, context) {
with_arg
);
} else {
const arg = node.arguments.map(
(arg) => /** @type {import('estree').Expression} */ (visit(arg))
);
const arg = node.arguments.map((arg) => /** @type {Expression} */ (visit(arg)));
return b.call('$.inspect', as_fn ? b.thunk(b.array(arg)) : b.array(arg));
}
}

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

@ -1,3 +1,4 @@
/** @import * as Compiler from '#compiler' */
/**
* All nodes that can appear elsewhere than the top level, have attributes and can contain children
*/
@ -13,15 +14,15 @@ const element_nodes = [
/**
* Returns true for all nodes that can appear elsewhere than the top level, have attributes and can contain children
* @param {import('#compiler').SvelteNode} node
* @returns {node is import('#compiler').Component | import('#compiler').RegularElement | import('#compiler').SlotElement | import('#compiler').SvelteComponent | import('#compiler').SvelteElement | import('#compiler').SvelteFragment | import('#compiler').SvelteSelf}
* @param {Compiler.SvelteNode} node
* @returns {node is Compiler.Component | Compiler.RegularElement | Compiler.SlotElement | Compiler.SvelteComponent | Compiler.SvelteElement | Compiler.SvelteFragment | Compiler.SvelteSelf}
*/
export function is_element_node(node) {
return element_nodes.includes(node.type);
}
/**
* @param {import('#compiler').RegularElement | import('#compiler').SvelteElement} node
* @param {Compiler.RegularElement | Compiler.SvelteElement} node
* @returns {boolean}
*/
export function is_custom_element_node(node) {
@ -32,8 +33,8 @@ export function is_custom_element_node(node) {
* @param {string} name
* @param {number} start
* @param {number} end
* @param {true | Array<import('#compiler').Text | import('#compiler').ExpressionTag>} value
* @returns {import('#compiler').Attribute}
* @param {true | Array<Compiler.Text | Compiler.ExpressionTag>} value
* @returns {Compiler.Attribute}
*/
export function create_attribute(name, start, end, value) {
return {

@ -1,3 +1,4 @@
/** @import { Visitors, Context } from 'zimmerframe' */
const overrides = {
visit() {
throw new Error('Cannot call visit() during analysis');
@ -10,7 +11,7 @@ const overrides = {
/**
* @template {{ type: string }} T
* @template U
* @param {...import('zimmerframe').Visitors<T, U>} tasks
* @param {...Visitors<T, U>} tasks
* @returns
*/
export function merge(...tasks) {
@ -24,7 +25,7 @@ export function merge(...tasks) {
}
}
/** @type {import('zimmerframe').Visitors<T, U>} */
/** @type {Visitors<T, U>} */
// @ts-expect-error
const combined = {};
@ -33,7 +34,7 @@ export function merge(...tasks) {
/**
* @param {T} node
* @param {import('zimmerframe').Context<T, U>} context
* @param {Context<T, U>} context
*/
function visitor(node, context) {
/**

@ -1,3 +1,4 @@
/** @import { Processed } from './public.js' */
import { decode as decode_mappings } from '@jridgewell/sourcemap-codec';
/**
@ -80,7 +81,7 @@ function decoded_sourcemap_from_generator(generator) {
}
/**
* @param {import('./public.js').Processed} processed
* @param {Processed} processed
*/
export function decode_map(processed) {
let decoded_map = typeof processed.map === 'string' ? JSON.parse(processed.map) : processed.map;

@ -1,3 +1,6 @@
/** @import { Processed, Preprocessor, MarkupPreprocessor, PreprocessorGroup } from './public.js' */
/** @import { SourceUpdate, Source } from './private.js' */
/** @import { DecodedSourceMap, RawSourceMap } from '@ampproject/remapping' */
import { getLocator } from 'locate-character';
import {
MappedCode,
@ -26,7 +29,7 @@ class PreprocessResult {
/**
* @default []
* @type {Array<import('@ampproject/remapping').DecodedSourceMap | import('@ampproject/remapping').RawSourceMap>}
* @type {Array<DecodedSourceMap | RawSourceMap>}
*/
sourcemap_list = [];
@ -59,7 +62,7 @@ class PreprocessResult {
}
/**
* @param {import('./private.js').SourceUpdate} opts
* @param {SourceUpdate} opts
*/
update_source({ string: source, map, dependencies }) {
if (source != null) {
@ -75,7 +78,7 @@ class PreprocessResult {
}
/**
* @returns {import('./public.js').Processed}
* @returns {Processed}
*/
to_processed() {
// Combine all the source maps for each preprocessor function into one
@ -96,7 +99,7 @@ class PreprocessResult {
}
/**
* Convert preprocessor output for the tag content into MappedCode
* @param {import('./public.js').Processed} processed
* @param {Processed} processed
* @param {{ line: number; column: number; }} location
* @param {string} file_basename
* @returns {MappedCode}
@ -105,7 +108,7 @@ function processed_content_to_code(processed, location, file_basename) {
// Convert the preprocessed code and its sourcemap to a MappedCode
/**
* @type {import('@ampproject/remapping').DecodedSourceMap | undefined}
* @type {DecodedSourceMap | undefined}
*/
let decoded_map = undefined;
if (processed.map) {
@ -124,11 +127,11 @@ function processed_content_to_code(processed, location, file_basename) {
/**
* Given the whole tag including content, return a `MappedCode`
* representing the tag content replaced with `processed`.
* @param {import('./public.js').Processed} processed
* @param {Processed} processed
* @param {'style' | 'script'} tag_name
* @param {string} original_attributes
* @param {string} generated_attributes
* @param {import('./private.js').Source} source
* @param {Source} source
* @returns {MappedCode}
*/
function processed_tag_to_code(
@ -157,7 +160,7 @@ function processed_tag_to_code(
if (original_tag_open.length !== tag_open.length) {
// Generate a source map for the open tag
/** @type {import('@ampproject/remapping').DecodedSourceMap['mappings']} */
/** @type {DecodedSourceMap['mappings']} */
const mappings = [
[
// start of tag
@ -183,7 +186,7 @@ function processed_tag_to_code(
original_tag_open.length - original_tag_open.lastIndexOf('\n') - 1
]);
/** @type {import('@ampproject/remapping').DecodedSourceMap} */
/** @type {DecodedSourceMap} */
const map = {
version: 3,
names: [],
@ -255,9 +258,9 @@ const regex_script_tags =
/**
* Calculate the updates required to process all instances of the specified tag.
* @param {'style' | 'script'} tag_name
* @param {import('./public.js').Preprocessor} preprocessor
* @param {import('./private.js').Source} source
* @returns {Promise<import('./private.js').SourceUpdate>}
* @param {Preprocessor} preprocessor
* @param {Source} source
* @returns {Promise<SourceUpdate>}
*/
async function process_tag(tag_name, preprocessor, source) {
const { filename, source: markup } = source;
@ -299,8 +302,8 @@ async function process_tag(tag_name, preprocessor, source) {
}
/**
* @param {import('./public.js').MarkupPreprocessor} process
* @param {import('./private.js').Source} source
* @param {MarkupPreprocessor} process
* @param {Source} source
*/
async function process_markup(process, source) {
const processed = await process({
@ -329,9 +332,9 @@ async function process_markup(process, source) {
*
* https://svelte.dev/docs/svelte-compiler#svelte-preprocess
* @param {string} source
* @param {import('./public.js').PreprocessorGroup | import('./public.js').PreprocessorGroup[]} preprocessor
* @param {PreprocessorGroup | PreprocessorGroup[]} preprocessor
* @param {{ filename?: string }} [options]
* @returns {Promise<import('./public.js').Processed>}
* @returns {Promise<Processed>}
*/
export default async function preprocess(source, preprocessor, options) {
/**

@ -1,10 +1,11 @@
/** @import { Source, Replacement } from './private.js' */
import { MappedCode } from '../utils/mapped_code.js';
/**
* @param {string} code_slice
* @param {number} offset
* @param {import('./private.js').Source} opts
* @returns {import('./private.js').Source}
* @param {Source} opts
* @returns {Source}
*/
export function slice_source(code_slice, offset, { file_basename, filename, get_location }) {
return {
@ -22,7 +23,7 @@ export function slice_source(code_slice, offset, { file_basename, filename, get_
*/
function calculate_replacements(re, get_replacement, source) {
/**
* @type {Array<Promise<import('./private.js').Replacement>>}
* @type {Array<Promise<Replacement>>}
*/
const replacements = [];
source.replace(re, (...match) => {
@ -39,8 +40,8 @@ function calculate_replacements(re, get_replacement, source) {
}
/**
* @param {import('./private.js').Replacement[]} replacements
* @param {import('./private.js').Source} source
* @param {Replacement[]} replacements
* @param {Source} source
* @returns {MappedCode}
*/
function perform_replacements(replacements, source) {
@ -62,7 +63,7 @@ function perform_replacements(replacements, source) {
/**
* @param {RegExp} regex
* @param {(...match: any[]) => Promise<MappedCode>} get_replacement
* @param {import('./private.js').Source} location
* @param {Source} location
* @returns {Promise<MappedCode>}
*/
export async function replace_in_code(regex, get_replacement, location) {

@ -1,8 +1,10 @@
/** @import { SvelteNode } from './types' */
/** @import { Warning } from '#compiler' */
import { getLocator } from 'locate-character';
/** @typedef {{ start?: number, end?: number }} NodeLike */
/** @type {import('#compiler').Warning[]} */
/** @type {Warning[]} */
export let warnings = [];
/**
@ -24,7 +26,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<import("./types").SvelteNode | NodeLike, Set<string>[]>}
* @type {Map<SvelteNode | NodeLike, Set<string>[]>}
*/
export let ignore_map = new Map();

@ -1,16 +1,16 @@
/** @import { Attribute, Text, ExpressionTag, SvelteNode } from '#compiler' */
/** @import * as ESTree from 'estree' */
import { walk } from 'zimmerframe';
import * as b from '../utils/builders.js';
/**
* Gets the left-most identifier of a member expression or identifier.
* @param {import('estree').MemberExpression | import('estree').Identifier} expression
* @returns {import('estree').Identifier | null}
* @param {ESTree.MemberExpression | ESTree.Identifier} expression
* @returns {ESTree.Identifier | null}
*/
export function object(expression) {
while (expression.type === 'MemberExpression') {
expression = /** @type {import('estree').MemberExpression | import('estree').Identifier} */ (
expression.object
);
expression = /** @type {ESTree.MemberExpression | ESTree.Identifier} */ (expression.object);
}
if (expression.type !== 'Identifier') {
@ -22,8 +22,8 @@ export function object(expression) {
/**
* Returns true if the attribute contains a single static text node.
* @param {import('#compiler').Attribute} attribute
* @returns {attribute is import('#compiler').Attribute & { value: [import('#compiler').Text] }}
* @param {Attribute} attribute
* @returns {attribute is Attribute & { value: [Text] }}
*/
export function is_text_attribute(attribute) {
return (
@ -33,8 +33,8 @@ export function is_text_attribute(attribute) {
/**
* Returns true if the attribute contains a single expression node.
* @param {import('#compiler').Attribute} attribute
* @returns {attribute is import('#compiler').Attribute & { value: [import('#compiler').ExpressionTag] }}
* @param {Attribute} attribute
* @returns {attribute is Attribute & { value: [ExpressionTag] }}
*/
export function is_expression_attribute(attribute) {
return (
@ -46,8 +46,8 @@ export function is_expression_attribute(attribute) {
/**
* Returns true if the attribute starts with `on` and contains a single expression node.
* @param {import('#compiler').Attribute} attribute
* @returns {attribute is import('#compiler').Attribute & { value: [import('#compiler').ExpressionTag] }}
* @param {Attribute} attribute
* @returns {attribute is Attribute & { value: [ExpressionTag] }}
*/
export function is_event_attribute(attribute) {
return is_expression_attribute(attribute) && attribute.name.startsWith('on');
@ -55,9 +55,9 @@ export function is_event_attribute(attribute) {
/**
* Extracts all identifiers from a pattern.
* @param {import('estree').Pattern} param
* @param {import('estree').Identifier[]} [nodes]
* @returns {import('estree').Identifier[]}
* @param {ESTree.Pattern} param
* @param {ESTree.Identifier[]} [nodes]
* @returns {ESTree.Identifier[]}
*/
export function extract_identifiers(param, nodes = []) {
switch (param.type) {
@ -97,11 +97,11 @@ export function extract_identifiers(param, nodes = []) {
/**
* Extracts all identifiers and a stringified keypath from an expression.
* @param {import('estree').Expression} expr
* @returns {[keypath: string, ids: import('estree').Identifier[]]}
* @param {ESTree.Expression} expr
* @returns {[keypath: string, ids: ESTree.Identifier[]]}
*/
export function extract_all_identifiers_from_expression(expr) {
/** @type {import('estree').Identifier[]} */
/** @type {ESTree.Identifier[]} */
let nodes = [];
/** @type {string[]} */
let keypath = [];
@ -143,8 +143,8 @@ export function extract_all_identifiers_from_expression(expr) {
/**
* Extracts all leaf identifiers from a destructuring expression.
* @param {import('estree').Identifier | import('estree').ObjectExpression | import('estree').ArrayExpression} node
* @param {import('estree').Identifier[]} [nodes]
* @param {ESTree.Identifier | ESTree.ObjectExpression | ESTree.ArrayExpression} node
* @param {ESTree.Identifier[]} [nodes]
* @returns
*/
export function extract_identifiers_from_destructuring(node, nodes = []) {
@ -181,33 +181,33 @@ export function extract_identifiers_from_destructuring(node, nodes = []) {
* or assignment expression. For example, given `const { foo: { bar: baz } } = quux`,
* the path of `baz` is `foo.bar`
* @typedef {Object} DestructuredAssignment
* @property {import('estree').Identifier | import('estree').MemberExpression} node The node the destructuring path end in. Can be a member expression only for assignment expressions
* @property {ESTree.Identifier | ESTree.MemberExpression} node The node the destructuring path end in. Can be a member expression only for assignment expressions
* @property {boolean} is_rest `true` if this is a `...rest` destructuring
* @property {boolean} has_default_value `true` if this has a fallback value like `const { foo = 'bar } = ..`
* @property {(expression: import('estree').Expression) => import('estree').Identifier | import('estree').MemberExpression | import('estree').CallExpression | import('estree').AwaitExpression} expression Returns an expression which walks the path starting at the given expression.
* @property {(expression: ESTree.Expression) => ESTree.Identifier | ESTree.MemberExpression | ESTree.CallExpression | ESTree.AwaitExpression} expression Returns an expression which walks the path starting at the given expression.
* This will be a call expression if a rest element or default is involved e.g. `const { foo: { bar: baz = 42 }, ...rest } = quux` since we can't represent `baz` or `rest` purely as a path
* Will be an await expression in case of an async default value (`const { foo = await bar } = ...`)
* @property {(expression: import('estree').Expression) => import('estree').Identifier | import('estree').MemberExpression | import('estree').CallExpression | import('estree').AwaitExpression} update_expression Like `expression` but without default values.
* @property {(expression: ESTree.Expression) => ESTree.Identifier | ESTree.MemberExpression | ESTree.CallExpression | ESTree.AwaitExpression} update_expression Like `expression` but without default values.
*/
/**
* Extracts all destructured assignments from a pattern.
* @param {import('estree').Node} param
* @param {ESTree.Node} param
* @returns {DestructuredAssignment[]}
*/
export function extract_paths(param) {
return _extract_paths(
[],
param,
(node) => /** @type {import('estree').Identifier | import('estree').MemberExpression} */ (node),
(node) => /** @type {import('estree').Identifier | import('estree').MemberExpression} */ (node),
(node) => /** @type {ESTree.Identifier | ESTree.MemberExpression} */ (node),
(node) => /** @type {ESTree.Identifier | ESTree.MemberExpression} */ (node),
false
);
}
/**
* @param {DestructuredAssignment[]} assignments
* @param {import('estree').Node} param
* @param {ESTree.Node} param
* @param {DestructuredAssignment['expression']} expression
* @param {DestructuredAssignment['update_expression']} update_expression
* @param {boolean} has_default_value
@ -231,7 +231,7 @@ function _extract_paths(assignments = [], param, expression, update_expression,
if (prop.type === 'RestElement') {
/** @type {DestructuredAssignment['expression']} */
const rest_expression = (object) => {
/** @type {import('estree').Expression[]} */
/** @type {ESTree.Expression[]} */
const props = [];
for (const p of param.properties) {
if (p.type === 'Property' && p.key.type !== 'PrivateIdentifier') {
@ -351,7 +351,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 {import('#compiler').SvelteNode} T
* @template {SvelteNode} T
* @param {T[]} path
* @param {number} at
*/
@ -369,7 +369,7 @@ export function get_parent(path, at) {
* or a logical expression that only contains simple expressions. Used to determine whether
* something needs to be treated as though accessing it could have side-effects (i.e.
* reading signals prematurely)
* @param {import('estree').Expression} node
* @param {ESTree.Expression} node
* @returns {boolean}
*/
export function is_simple_expression(node) {
@ -398,8 +398,8 @@ export function is_simple_expression(node) {
}
/**
* @template {import('estree').SimpleCallExpression | import('estree').MemberExpression} T
* @param {import('estree').ChainExpression & { expression : T } | T} node
* @template {ESTree.SimpleCallExpression | ESTree.MemberExpression} T
* @param {ESTree.ChainExpression & { expression : T } | T} node
* @returns {T}
*/
export function unwrap_optional(node) {
@ -407,7 +407,7 @@ export function unwrap_optional(node) {
}
/**
* @param {import('estree').Expression | import('estree').Pattern} expression
* @param {ESTree.Expression | ESTree.Pattern} expression
* @returns {boolean}
*/
export function is_expression_async(expression) {

@ -1,35 +1,36 @@
/** @import * as ESTree from 'estree' */
import { regex_is_valid_identifier } from '../phases/patterns.js';
import { sanitize_template_string } from './sanitize_template_string.js';
/**
* @param {Array<import('estree').Expression | import('estree').SpreadElement | null>} elements
* @returns {import('estree').ArrayExpression}
* @param {Array<ESTree.Expression | ESTree.SpreadElement | null>} elements
* @returns {ESTree.ArrayExpression}
*/
export function array(elements = []) {
return { type: 'ArrayExpression', elements };
}
/**
* @param {Array<import('estree').Pattern | null>} elements
* @returns {import('estree').ArrayPattern}
* @param {Array<ESTree.Pattern | null>} elements
* @returns {ESTree.ArrayPattern}
*/
export function array_pattern(elements) {
return { type: 'ArrayPattern', elements };
}
/**
* @param {import('estree').Pattern} left
* @param {import('estree').Expression} right
* @returns {import('estree').AssignmentPattern}
* @param {ESTree.Pattern} left
* @param {ESTree.Expression} right
* @returns {ESTree.AssignmentPattern}
*/
export function assignment_pattern(left, right) {
return { type: 'AssignmentPattern', left, right };
}
/**
* @param {Array<import('estree').Pattern>} params
* @param {import('estree').BlockStatement | import('estree').Expression} body
* @returns {import('estree').ArrowFunctionExpression}
* @param {Array<ESTree.Pattern>} params
* @param {ESTree.BlockStatement | ESTree.Expression} body
* @returns {ESTree.ArrowFunctionExpression}
*/
export function arrow(params, body) {
return {
@ -44,10 +45,10 @@ export function arrow(params, body) {
}
/**
* @param {import('estree').AssignmentOperator} operator
* @param {import('estree').Pattern} left
* @param {import('estree').Expression} right
* @returns {import('estree').AssignmentExpression}
* @param {ESTree.AssignmentOperator} operator
* @param {ESTree.Pattern} left
* @param {ESTree.Expression} right
* @returns {ESTree.AssignmentExpression}
*/
export function assignment(operator, left, right) {
return { type: 'AssignmentExpression', operator, left, right };
@ -55,34 +56,34 @@ export function assignment(operator, left, right) {
/**
* @template T
* @param {T & import('estree').BaseFunction} func
* @returns {T & import('estree').BaseFunction}
* @param {T & ESTree.BaseFunction} func
* @returns {T & ESTree.BaseFunction}
*/
export function async(func) {
return { ...func, async: true };
}
/**
* @param {import('estree').Expression} argument
* @returns {import('estree').AwaitExpression}
* @param {ESTree.Expression} argument
* @returns {ESTree.AwaitExpression}
*/
function await_builder(argument) {
return { type: 'AwaitExpression', argument };
}
/**
* @param {import('estree').BinaryOperator} operator
* @param {import('estree').Expression} left
* @param {import('estree').Expression} right
* @returns {import('estree').BinaryExpression}
* @param {ESTree.BinaryOperator} operator
* @param {ESTree.Expression} left
* @param {ESTree.Expression} right
* @returns {ESTree.BinaryExpression}
*/
export function binary(operator, left, right) {
return { type: 'BinaryExpression', operator, left, right };
}
/**
* @param {import('estree').Statement[]} body
* @returns {import('estree').BlockStatement}
* @param {ESTree.Statement[]} body
* @returns {ESTree.BlockStatement}
*/
export function block(body) {
return { type: 'BlockStatement', body };
@ -90,17 +91,17 @@ export function block(body) {
/**
* @param {string} name
* @param {import('estree').Statement} body
* @returns {import('estree').LabeledStatement}
* @param {ESTree.Statement} body
* @returns {ESTree.LabeledStatement}
*/
export function labeled(name, body) {
return { type: 'LabeledStatement', label: id(name), body };
}
/**
* @param {string | import('estree').Expression} callee
* @param {...(import('estree').Expression | import('estree').SpreadElement | false | undefined)} args
* @returns {import('estree').CallExpression}
* @param {string | ESTree.Expression} callee
* @param {...(ESTree.Expression | ESTree.SpreadElement | false | undefined)} args
* @returns {ESTree.CallExpression}
*/
export function call(callee, ...args) {
if (typeof callee === 'string') callee = id(callee);
@ -124,20 +125,18 @@ export function call(callee, ...args) {
return {
type: 'CallExpression',
callee,
arguments: /** @type {Array<import('estree').Expression | import('estree').SpreadElement>} */ (
args
),
arguments: /** @type {Array<ESTree.Expression | ESTree.SpreadElement>} */ (args),
optional: false
};
}
/**
* @param {string | import('estree').Expression} callee
* @param {...import('estree').Expression} args
* @returns {import('estree').ChainExpression}
* @param {string | ESTree.Expression} callee
* @param {...ESTree.Expression} args
* @returns {ESTree.ChainExpression}
*/
export function maybe_call(callee, ...args) {
const expression = /** @type {import('estree').SimpleCallExpression} */ (call(callee, ...args));
const expression = /** @type {ESTree.SimpleCallExpression} */ (call(callee, ...args));
expression.optional = true;
return {
@ -147,29 +146,29 @@ export function maybe_call(callee, ...args) {
}
/**
* @param {import('estree').UnaryOperator} operator
* @param {import('estree').Expression} argument
* @returns {import('estree').UnaryExpression}
* @param {ESTree.UnaryOperator} operator
* @param {ESTree.Expression} argument
* @returns {ESTree.UnaryExpression}
*/
export function unary(operator, argument) {
return { type: 'UnaryExpression', argument, operator, prefix: true };
}
/**
* @param {import('estree').Expression} test
* @param {import('estree').Expression} consequent
* @param {import('estree').Expression} alternate
* @returns {import('estree').ConditionalExpression}
* @param {ESTree.Expression} test
* @param {ESTree.Expression} consequent
* @param {ESTree.Expression} alternate
* @returns {ESTree.ConditionalExpression}
*/
export function conditional(test, consequent, alternate) {
return { type: 'ConditionalExpression', test, consequent, alternate };
}
/**
* @param {import('estree').LogicalOperator} operator
* @param {import('estree').Expression} left
* @param {import('estree').Expression} right
* @returns {import('estree').LogicalExpression}
* @param {ESTree.LogicalOperator} operator
* @param {ESTree.Expression} left
* @param {ESTree.Expression} right
* @returns {ESTree.LogicalExpression}
*/
export function logical(operator, left, right) {
return { type: 'LogicalExpression', operator, left, right };
@ -177,9 +176,9 @@ export function logical(operator, left, right) {
/**
* @param {'const' | 'let' | 'var'} kind
* @param {string | import('estree').Pattern} pattern
* @param {import('estree').Expression} [init]
* @returns {import('estree').VariableDeclaration}
* @param {string | ESTree.Pattern} pattern
* @param {ESTree.Expression} [init]
* @returns {ESTree.VariableDeclaration}
*/
export function declaration(kind, pattern, init) {
if (typeof pattern === 'string') pattern = id(pattern);
@ -192,32 +191,32 @@ export function declaration(kind, pattern, init) {
}
/**
* @param {import('estree').Pattern} id
* @param {import('estree').Expression} [init]
* @returns {import('estree').VariableDeclarator}
* @param {ESTree.Pattern} id
* @param {ESTree.Expression} [init]
* @returns {ESTree.VariableDeclarator}
*/
export function declarator(id, init) {
return { type: 'VariableDeclarator', id, init };
}
/** @type {import('estree').EmptyStatement} */
/** @type {ESTree.EmptyStatement} */
export const empty = {
type: 'EmptyStatement'
};
/**
* @param {import('estree').Expression | import('estree').MaybeNamedClassDeclaration | import('estree').MaybeNamedFunctionDeclaration} declaration
* @returns {import('estree').ExportDefaultDeclaration}
* @param {ESTree.Expression | ESTree.MaybeNamedClassDeclaration | ESTree.MaybeNamedFunctionDeclaration} declaration
* @returns {ESTree.ExportDefaultDeclaration}
*/
export function export_default(declaration) {
return { type: 'ExportDefaultDeclaration', declaration };
}
/**
* @param {import('estree').Identifier} id
* @param {import('estree').Pattern[]} params
* @param {import('estree').BlockStatement} body
* @returns {import('estree').FunctionDeclaration}
* @param {ESTree.Identifier} id
* @param {ESTree.Pattern[]} params
* @param {ESTree.BlockStatement} body
* @returns {ESTree.FunctionDeclaration}
*/
export function function_declaration(id, params, body) {
return {
@ -233,8 +232,8 @@ export function function_declaration(id, params, body) {
/**
* @param {string} name
* @param {import('estree').Statement[]} body
* @returns {import('estree').Property & { value: import('estree').FunctionExpression}}}
* @param {ESTree.Statement[]} body
* @returns {ESTree.Property & { value: ESTree.FunctionExpression}}}
*/
export function get(name, body) {
return prop('get', key(name), function_builder(null, [], block(body)));
@ -242,7 +241,7 @@ export function get(name, body) {
/**
* @param {string} name
* @returns {import('estree').Identifier}
* @returns {ESTree.Identifier}
*/
export function id(name) {
return { type: 'Identifier', name };
@ -250,7 +249,7 @@ export function id(name) {
/**
* @param {string} name
* @returns {import('estree').PrivateIdentifier}
* @returns {ESTree.PrivateIdentifier}
*/
export function private_id(name) {
return { type: 'PrivateIdentifier', name };
@ -258,7 +257,7 @@ export function private_id(name) {
/**
* @param {string} local
* @returns {import('estree').ImportNamespaceSpecifier}
* @returns {ESTree.ImportNamespaceSpecifier}
*/
function import_namespace(local) {
return {
@ -269,8 +268,8 @@ function import_namespace(local) {
/**
* @param {string} name
* @param {import('estree').Expression} value
* @returns {import('estree').Property}
* @param {ESTree.Expression} value
* @returns {ESTree.Property}
*/
export function init(name, value) {
return prop('init', key(name), value);
@ -278,7 +277,7 @@ export function init(name, value) {
/**
* @param {string | boolean | null | number | RegExp} value
* @returns {import('estree').Literal}
* @returns {ESTree.Literal}
*/
export function literal(value) {
// @ts-expect-error we don't want to muck around with bigint here
@ -286,11 +285,11 @@ export function literal(value) {
}
/**
* @param {import('estree').Expression | import('estree').Super} object
* @param {import('estree').Expression | import('estree').PrivateIdentifier} property
* @param {ESTree.Expression | ESTree.Super} object
* @param {ESTree.Expression | ESTree.PrivateIdentifier} property
* @param {boolean} computed
* @param {boolean} optional
* @returns {import('estree').MemberExpression}
* @returns {ESTree.MemberExpression}
*/
export function member(object, property, computed = false, optional = false) {
return { type: 'MemberExpression', object, property, computed, optional };
@ -298,12 +297,12 @@ export function member(object, property, computed = false, optional = false) {
/**
* @param {string} path
* @returns {import('estree').Identifier | import('estree').MemberExpression}
* @returns {ESTree.Identifier | ESTree.MemberExpression}
*/
export function member_id(path) {
const parts = path.split('.');
/** @type {import('estree').Identifier | import('estree').MemberExpression} */
/** @type {ESTree.Identifier | ESTree.MemberExpression} */
let expression = id(parts[0]);
for (let i = 1; i < parts.length; i += 1) {
@ -313,39 +312,39 @@ export function member_id(path) {
}
/**
* @param {Array<import('estree').Property | import('estree').SpreadElement>} properties
* @returns {import('estree').ObjectExpression}
* @param {Array<ESTree.Property | ESTree.SpreadElement>} properties
* @returns {ESTree.ObjectExpression}
*/
export function object(properties) {
return { type: 'ObjectExpression', properties };
}
/**
* @param {Array<import('estree').RestElement | import('estree').AssignmentProperty>} properties
* @returns {import('estree').ObjectPattern}
* @param {Array<ESTree.RestElement | ESTree.AssignmentProperty>} properties
* @returns {ESTree.ObjectPattern}
*/
export function object_pattern(properties) {
return { type: 'ObjectPattern', properties };
}
/**
* @template {import('estree').Expression} Value
* @template {ESTree.Expression} Value
* @param {'init' | 'get' | 'set'} kind
* @param {import('estree').Expression} key
* @param {ESTree.Expression} key
* @param {Value} value
* @param {boolean} computed
* @returns {import('estree').Property & { value: Value }}
* @returns {ESTree.Property & { value: Value }}
*/
export function prop(kind, key, value, computed = false) {
return { type: 'Property', kind, key, value, method: false, shorthand: false, computed };
}
/**
* @param {import('estree').Expression | import('estree').PrivateIdentifier} key
* @param {import('estree').Expression | null | undefined} value
* @param {ESTree.Expression | ESTree.PrivateIdentifier} key
* @param {ESTree.Expression | null | undefined} value
* @param {boolean} computed
* @param {boolean} is_static
* @returns {import('estree').PropertyDefinition}
* @returns {ESTree.PropertyDefinition}
*/
export function prop_def(key, value, computed = false, is_static = false) {
return { type: 'PropertyDefinition', key, value, computed, static: is_static };
@ -354,7 +353,7 @@ export function prop_def(key, value, computed = false, is_static = false) {
/**
* @param {string} cooked
* @param {boolean} tail
* @returns {import('estree').TemplateElement}
* @returns {ESTree.TemplateElement}
*/
export function quasi(cooked, tail = false) {
const raw = sanitize_template_string(cooked);
@ -362,16 +361,16 @@ export function quasi(cooked, tail = false) {
}
/**
* @param {import('estree').Pattern} argument
* @returns {import('estree').RestElement}
* @param {ESTree.Pattern} argument
* @returns {ESTree.RestElement}
*/
export function rest(argument) {
return { type: 'RestElement', argument };
}
/**
* @param {import('estree').Expression[]} expressions
* @returns {import('estree').SequenceExpression}
* @param {ESTree.Expression[]} expressions
* @returns {ESTree.SequenceExpression}
*/
export function sequence(expressions) {
return { type: 'SequenceExpression', expressions };
@ -379,42 +378,42 @@ export function sequence(expressions) {
/**
* @param {string} name
* @param {import('estree').Statement[]} body
* @returns {import('estree').Property & { value: import('estree').FunctionExpression}}
* @param {ESTree.Statement[]} body
* @returns {ESTree.Property & { value: ESTree.FunctionExpression}}
*/
export function set(name, body) {
return prop('set', key(name), function_builder(null, [id('$$value')], block(body)));
}
/**
* @param {import('estree').Expression} argument
* @returns {import('estree').SpreadElement}
* @param {ESTree.Expression} argument
* @returns {ESTree.SpreadElement}
*/
export function spread(argument) {
return { type: 'SpreadElement', argument };
}
/**
* @param {import('estree').Expression} expression
* @returns {import('estree').ExpressionStatement}
* @param {ESTree.Expression} expression
* @returns {ESTree.ExpressionStatement}
*/
export function stmt(expression) {
return { type: 'ExpressionStatement', expression };
}
/**
* @param {import('estree').TemplateElement[]} elements
* @param {import('estree').Expression[]} expressions
* @returns {import('estree').TemplateLiteral}
* @param {ESTree.TemplateElement[]} elements
* @param {ESTree.Expression[]} expressions
* @returns {ESTree.TemplateLiteral}
*/
export function template(elements, expressions) {
return { type: 'TemplateLiteral', quasis: elements, expressions };
}
/**
* @param {import('estree').Expression | import('estree').BlockStatement} expression
* @param {ESTree.Expression | ESTree.BlockStatement} expression
* @param {boolean} [async]
* @returns {import('estree').Expression}
* @returns {ESTree.Expression}
*/
export function thunk(expression, async = false) {
if (
@ -434,9 +433,9 @@ export function thunk(expression, async = false) {
/**
*
* @param {string | import('estree').Expression} expression
* @param {...import('estree').Expression} args
* @returns {import('estree').NewExpression}
* @param {string | ESTree.Expression} expression
* @param {...ESTree.Expression} args
* @returns {ESTree.NewExpression}
*/
function new_builder(expression, ...args) {
if (typeof expression === 'string') expression = id(expression);
@ -449,19 +448,19 @@ function new_builder(expression, ...args) {
}
/**
* @param {import('estree').UpdateOperator} operator
* @param {import('estree').Expression} argument
* @param {ESTree.UpdateOperator} operator
* @param {ESTree.Expression} argument
* @param {boolean} prefix
* @returns {import('estree').UpdateExpression}
* @returns {ESTree.UpdateExpression}
*/
export function update(operator, argument, prefix = false) {
return { type: 'UpdateExpression', operator, argument, prefix };
}
/**
* @param {import('estree').Expression} test
* @param {import('estree').Statement} body
* @returns {import('estree').DoWhileStatement}
* @param {ESTree.Expression} test
* @param {ESTree.Statement} body
* @returns {ESTree.DoWhileStatement}
*/
export function do_while(test, body) {
return { type: 'DoWhileStatement', test, body };
@ -471,38 +470,38 @@ const true_instance = literal(true);
const false_instance = literal(false);
const null_instane = literal(null);
/** @type {import('estree').DebuggerStatement} */
/** @type {ESTree.DebuggerStatement} */
const debugger_builder = {
type: 'DebuggerStatement'
};
/** @type {import('estree').ThisExpression} */
/** @type {ESTree.ThisExpression} */
const this_instance = {
type: 'ThisExpression'
};
/**
* @param {string | import('estree').Pattern} pattern
* @param { import('estree').Expression} [init]
* @returns {import('estree').VariableDeclaration}
* @param {string | ESTree.Pattern} pattern
* @param { ESTree.Expression} [init]
* @returns {ESTree.VariableDeclaration}
*/
function let_builder(pattern, init) {
return declaration('let', pattern, init);
}
/**
* @param {string | import('estree').Pattern} pattern
* @param { import('estree').Expression} init
* @returns {import('estree').VariableDeclaration}
* @param {string | ESTree.Pattern} pattern
* @param { ESTree.Expression} init
* @returns {ESTree.VariableDeclaration}
*/
function const_builder(pattern, init) {
return declaration('const', pattern, init);
}
/**
* @param {string | import('estree').Pattern} pattern
* @param { import('estree').Expression} [init]
* @returns {import('estree').VariableDeclaration}
* @param {string | ESTree.Pattern} pattern
* @param { ESTree.Expression} [init]
* @returns {ESTree.VariableDeclaration}
*/
function var_builder(pattern, init) {
return declaration('var', pattern, init);
@ -510,11 +509,11 @@ function var_builder(pattern, init) {
/**
*
* @param {import('estree').VariableDeclaration | import('estree').Expression | null} init
* @param {import('estree').Expression} test
* @param {import('estree').Expression} update
* @param {import('estree').Statement} body
* @returns {import('estree').ForStatement}
* @param {ESTree.VariableDeclaration | ESTree.Expression | null} init
* @param {ESTree.Expression} test
* @param {ESTree.Expression} update
* @param {ESTree.Statement} body
* @returns {ESTree.ForStatement}
*/
function for_builder(init, test, update, body) {
return { type: 'ForStatement', init, test, update, body };
@ -523,12 +522,12 @@ function for_builder(init, test, update, body) {
/**
*
* @param {'constructor' | 'method' | 'get' | 'set'} kind
* @param {import('estree').Expression | import('estree').PrivateIdentifier} key
* @param {import('estree').Pattern[]} params
* @param {import('estree').Statement[]} body
* @param {ESTree.Expression | ESTree.PrivateIdentifier} key
* @param {ESTree.Pattern[]} params
* @param {ESTree.Statement[]} body
* @param {boolean} computed
* @param {boolean} is_static
* @returns {import('estree').MethodDefinition}
* @returns {ESTree.MethodDefinition}
*/
export function method(kind, key, params, body, computed = false, is_static = false) {
return {
@ -543,10 +542,10 @@ export function method(kind, key, params, body, computed = false, is_static = fa
/**
*
* @param {import('estree').Identifier | null} id
* @param {import('estree').Pattern[]} params
* @param {import('estree').BlockStatement} body
* @returns {import('estree').FunctionExpression}
* @param {ESTree.Identifier | null} id
* @param {ESTree.Pattern[]} params
* @param {ESTree.BlockStatement} body
* @returns {ESTree.FunctionExpression}
*/
function function_builder(id, params, body) {
return {
@ -561,10 +560,10 @@ function function_builder(id, params, body) {
}
/**
* @param {import('estree').Expression} test
* @param {import('estree').Statement} consequent
* @param {import('estree').Statement} [alternate]
* @returns {import('estree').IfStatement}
* @param {ESTree.Expression} test
* @param {ESTree.Statement} consequent
* @param {ESTree.Statement} [alternate]
* @returns {ESTree.IfStatement}
*/
function if_builder(test, consequent, alternate) {
return { type: 'IfStatement', test, consequent, alternate };
@ -573,7 +572,7 @@ function if_builder(test, consequent, alternate) {
/**
* @param {string} as
* @param {string} source
* @returns {import('estree').ImportDeclaration}
* @returns {ESTree.ImportDeclaration}
*/
export function import_all(as, source) {
return {
@ -586,7 +585,7 @@ export function import_all(as, source) {
/**
* @param {Array<[string, string]>} parts
* @param {string} source
* @returns {import('estree').ImportDeclaration}
* @returns {ESTree.ImportDeclaration}
*/
export function imports(parts, source) {
return {
@ -601,8 +600,8 @@ export function imports(parts, source) {
}
/**
* @param {import('estree').Expression | null} argument
* @returns {import('estree').ReturnStatement}
* @param {ESTree.Expression | null} argument
* @returns {ESTree.ReturnStatement}
*/
function return_builder(argument = null) {
return { type: 'ReturnStatement', argument };
@ -610,7 +609,7 @@ function return_builder(argument = null) {
/**
* @param {string} str
* @returns {import('estree').ThrowStatement}
* @returns {ESTree.ThrowStatement}
*/
export function throw_error(str) {
return {
@ -637,7 +636,7 @@ export {
/**
* @param {string} name
* @returns {import('estree').Expression}
* @returns {ESTree.Expression}
*/
export function key(name) {
return regex_is_valid_identifier.test(name) ? id(name) : literal(name);

@ -1,3 +1,8 @@
/** @import { ValidatedCompileOptions } from '#compiler' */
/** @import { Processed } from '../preprocess/public.js' */
/** @import { SourceMap } from 'magic-string' */
/** @import { Source } from '../preprocess/private.js' */
/** @import { DecodedSourceMap, SourceMapSegment, RawSourceMap } from '@ampproject/remapping' */
import remapping from '@ampproject/remapping';
import { push_array } from './push_array.js';
@ -10,7 +15,7 @@ function last_line_length(s) {
// mutate map in-place
/**
* @param {import('@ampproject/remapping').DecodedSourceMap} map
* @param {DecodedSourceMap} map
* @param {{ line: number; column: number; }} offset
* @param {number} source_index
*/
@ -74,13 +79,13 @@ export class MappedCode {
string = /** @type {any} */ (undefined);
/**
* @type {import('@ampproject/remapping').DecodedSourceMap}
* @type {DecodedSourceMap}
*/
map = /** @type {any} */ (undefined);
/**
* @param {string} string
* @param {import('@ampproject/remapping').DecodedSourceMap | null} map
* @param {DecodedSourceMap | null} map
*/
constructor(string = '', map = null) {
this.string = string;
@ -171,7 +176,7 @@ export class MappedCode {
// combine last line + first line
push_array(
m1.mappings[m1.mappings.length - 1],
/** @type {import('@ampproject/remapping').SourceMapSegment[]} */ (m2.mappings.shift())
/** @type {SourceMapSegment[]} */ (m2.mappings.shift())
);
// append other lines
push_array(m1.mappings, m2.mappings);
@ -181,7 +186,7 @@ export class MappedCode {
/**
* @static
* @param {string} string
* @param {import('@ampproject/remapping').DecodedSourceMap} [map]
* @param {DecodedSourceMap} [map]
* @returns {MappedCode}
*/
static from_processed(string, map) {
@ -205,7 +210,7 @@ export class MappedCode {
/**
* @static
* @param {import('../preprocess/private.js').Source} opts
* @param {Source} opts
* @returns {MappedCode}
*/
static from_source({ source, file_basename, get_location }) {
@ -216,7 +221,7 @@ export class MappedCode {
if (!offset) offset = { line: 0, column: 0 };
/**
* @type {import('@ampproject/remapping').DecodedSourceMap}
* @type {DecodedSourceMap}
*/
const map = { version: 3, names: [], sources: [file_basename], mappings: [] };
if (source == '') return new MappedCode(source, map);
@ -255,7 +260,7 @@ const b64dec =
/**
* @param {string} filename Basename of the input file
* @param {Array<import('@ampproject/remapping').DecodedSourceMap | import('@ampproject/remapping').RawSourceMap>} sourcemap_list
* @param {Array<DecodedSourceMap | RawSourceMap>} sourcemap_list
*/
export function combine_sourcemaps(filename, sourcemap_list) {
if (sourcemap_list.length == 0) return null;
@ -296,9 +301,9 @@ export function combine_sourcemaps(filename, sourcemap_list) {
/**
* @param {string} filename
* @param {import('magic-string').SourceMap} svelte_map
* @param {string | import('@ampproject/remapping').DecodedSourceMap | import('@ampproject/remapping').RawSourceMap} preprocessor_map_input
* @returns {import('magic-string').SourceMap}
* @param {SourceMap} svelte_map
* @param {string | DecodedSourceMap | RawSourceMap} preprocessor_map_input
* @returns {SourceMap}
*/
function apply_preprocessor_sourcemap(filename, svelte_map, preprocessor_map_input) {
if (!svelte_map || !preprocessor_map_input) return svelte_map;
@ -323,13 +328,13 @@ function apply_preprocessor_sourcemap(filename, svelte_map, preprocessor_map_inp
}
}
});
return /** @type {import('magic-string').SourceMap} */ (result_map);
return /** @type {SourceMap} */ (result_map);
}
const regex_data_uri = /data:(?:application|text)\/json;(?:charset[:=]\S+?;)?base64,(\S*)/;
// parse attached sourcemap in processed.code
/**
* @param {import('../preprocess/public.js').Processed} processed
* @param {Processed} processed
* @param {'script' | 'style'} tag_name
* @returns {void}
*/
@ -382,8 +387,8 @@ export function parse_attached_sourcemap(processed, tag_name) {
}
/**
* @param {{ code: string, map: import('magic-string').SourceMap}} result
* @param {import('#compiler').ValidatedCompileOptions} options
* @param {{ code: string, map: SourceMap}} result
* @param {ValidatedCompileOptions} options
* @param {string} source_name
*/
export function merge_with_preprocessor_map(result, options, source_name) {

@ -1,3 +1,4 @@
/** @import { ModuleCompileOptions, ValidatedModuleCompileOptions, CompileOptions, ValidatedCompileOptions } from '#compiler' */
import * as e from './errors.js';
import * as w from './warnings.js';
@ -32,14 +33,14 @@ const common = {
};
export const validate_module_options =
/** @type {Validator<import('#compiler').ModuleCompileOptions, import('#compiler').ValidatedModuleCompileOptions>} */ (
/** @type {Validator<ModuleCompileOptions, ValidatedModuleCompileOptions>} */ (
object({
...common
})
);
export const validate_component_options =
/** @type {Validator<import('#compiler').CompileOptions, import('#compiler').ValidatedCompileOptions>} */ (
/** @type {Validator<CompileOptions, ValidatedCompileOptions>} */ (
object({
...common,

@ -1,10 +1,11 @@
/** @import { SourceLocation } from '../../../compiler/phases/3-transform/client/types.js' */
import { HYDRATION_END, HYDRATION_START } from '../../../constants.js';
import { hydrating } from '../dom/hydration.js';
/**
* @param {any} fn
* @param {string} filename
* @param {import('../../../compiler/phases/3-transform/client/types.js').SourceLocation[]} locations
* @param {SourceLocation[]} locations
* @returns {any}
*/
export function add_locations(fn, filename, locations) {
@ -21,7 +22,7 @@ export function add_locations(fn, filename, locations) {
/**
* @param {Element} element
* @param {string} filename
* @param {import('../../../compiler/phases/3-transform/client/types.js').SourceLocation} location
* @param {SourceLocation} location
*/
function assign_location(element, filename, location) {
// @ts-expect-error
@ -37,7 +38,7 @@ function assign_location(element, filename, location) {
/**
* @param {Node | null} node
* @param {string} filename
* @param {import('../../../compiler/phases/3-transform/client/types.js').SourceLocation[]} locations
* @param {SourceLocation[]} locations
*/
function assign_locations(node, filename, locations) {
var i = 0;

@ -1,3 +1,4 @@
/** @import { Source, Effect } from '#client' */
import { block, branch, destroy_effect } from '../reactivity/effects.js';
import { set_should_intro } from '../render.js';
import { get } from '../runtime.js';
@ -5,7 +6,7 @@ import { check_target } from './legacy.js';
/**
* @template {(anchor: Comment, props: any) => any} Component
* @param {import("#client").Source<Component>} source
* @param {Source<Component>} source
*/
export function hmr(source) {
/**
@ -15,7 +16,7 @@ export function hmr(source) {
return function (anchor, props) {
let instance = {};
/** @type {import("#client").Effect} */
/** @type {Effect} */
let effect;
block(anchor, 0, () => {

@ -1,3 +1,4 @@
/** @import { ProxyMetadata } from '#client' */
/** @typedef {{ file: string, line: number, column: number }} Location */
import { STATE_SYMBOL } from '../constants.js';
@ -134,8 +135,8 @@ export function add_owner_effect(get_object, Component) {
}
/**
* @param {import('#client').ProxyMetadata<any> | null} from
* @param {import('#client').ProxyMetadata<any>} to
* @param {ProxyMetadata<any> | null} from
* @param {ProxyMetadata<any>} to
*/
export function widen_ownership(from, to) {
if (to.owners === null) {
@ -162,7 +163,7 @@ export function widen_ownership(from, to) {
* @param {Set<any>} seen
*/
function add_owner_to_object(object, owner, seen) {
const metadata = /** @type {import('#client').ProxyMetadata} */ (object?.[STATE_SYMBOL]);
const metadata = /** @type {ProxyMetadata} */ (object?.[STATE_SYMBOL]);
if (metadata) {
// this is a state proxy, add owner directly, if not globally shared
@ -199,7 +200,7 @@ function add_owner_to_object(object, owner, seen) {
}
/**
* @param {import('#client').ProxyMetadata} metadata
* @param {ProxyMetadata} metadata
* @param {Function} component
* @returns {boolean}
*/
@ -215,18 +216,18 @@ function has_owner(metadata, component) {
}
/**
* @param {import('#client').ProxyMetadata} metadata
* @param {ProxyMetadata} metadata
* @returns {any}
*/
function get_owner(metadata) {
return (
metadata?.owners?.values().next().value ??
get_owner(/** @type {import('#client').ProxyMetadata} */ (metadata.parent))
get_owner(/** @type {ProxyMetadata} */ (metadata.parent))
);
}
/**
* @param {import('#client').ProxyMetadata} metadata
* @param {ProxyMetadata} metadata
*/
export function check_ownership(metadata) {
const component = get_component();

@ -1,3 +1,4 @@
/** @import { Dom, Effect } from '#client' */
import { UNINITIALIZED } from '../../../../constants.js';
import { block, branch, pause_effect } from '../../reactivity/effects.js';
import { safe_not_equal } from '../../reactivity/equality.js';
@ -6,14 +7,14 @@ import { safe_not_equal } from '../../reactivity/equality.js';
* @template V
* @param {Comment} anchor
* @param {() => V} get_key
* @param {(anchor: Node) => import('#client').Dom | void} render_fn
* @param {(anchor: Node) => Dom | void} render_fn
* @returns {void}
*/
export function key_block(anchor, get_key, render_fn) {
/** @type {V | typeof UNINITIALIZED} */
let key = UNINITIALIZED;
/** @type {import('#client').Effect} */
/** @type {Effect} */
let effect;
block(anchor, 0, () => {

@ -1,3 +1,4 @@
/** @import { TemplateNode, Dom, Effect } from '#client' */
import { DEV } from 'esm-env';
import { block, branch, pause_effect } from '../../reactivity/effects.js';
import { empty } from '../operations.js';
@ -5,16 +6,16 @@ import { empty } from '../operations.js';
/**
* @template P
* @template {(props: P) => void} C
* @param {import('#client').TemplateNode} anchor
* @param {TemplateNode} anchor
* @param {() => C} get_component
* @param {(anchor: import('#client').TemplateNode, component: C) => import('#client').Dom | void} render_fn
* @param {(anchor: TemplateNode, component: C) => Dom | void} render_fn
* @returns {void}
*/
export function component(anchor, get_component, render_fn) {
/** @type {C} */
let component;
/** @type {import('#client').Effect | null} */
/** @type {Effect | null} */
let effect;
var component_anchor = anchor;

@ -1,10 +1,11 @@
/** @import { ActionPayload } from '#client' */
import { effect, render_effect } from '../../reactivity/effects.js';
import { deep_read_state, untrack } from '../../runtime.js';
/**
* @template P
* @param {Element} dom
* @param {(dom: Element, value?: P) => import('#client').ActionPayload<P>} action
* @param {(dom: Element, value?: P) => ActionPayload<P>} action
* @param {() => P} [get_value]
* @returns {void}
*/

@ -1,3 +1,4 @@
/** @import { ComponentContextLegacy } from '#client' */
import { run, run_all } from '../../../shared/utils.js';
import { user_pre_effect, user_effect } from '../../reactivity/effects.js';
import { current_component_context, deep_read_state, get, untrack } from '../../runtime.js';
@ -6,9 +7,7 @@ import { current_component_context, deep_read_state, get, untrack } from '../../
* Legacy-mode only: Call `onMount` callbacks and set up `beforeUpdate`/`afterUpdate` effects
*/
export function init() {
const context = /** @type {import('#client').ComponentContextLegacy} */ (
current_component_context
);
const context = /** @type {ComponentContextLegacy} */ (current_component_context);
const callbacks = context.l.u;
if (!callbacks) return;
@ -45,7 +44,7 @@ export function init() {
/**
* Invoke the getter of all signals associated with a component
* so they can be registered to the effect this function is called in.
* @param {import('#client').ComponentContextLegacy} context
* @param {ComponentContextLegacy} context
*/
function observe_all(context) {
if (context.l.s) {

@ -1,3 +1,4 @@
/** @import { TaskCallback, Task, TaskEntry } from '#client' */
import { raf } from './timing.js';
// TODO move this into timing.js where it probably belongs
@ -22,11 +23,11 @@ function run_tasks(now) {
/**
* Creates a new task that runs on each raf frame
* until it returns a falsy value or is aborted
* @param {import('#client').TaskCallback} callback
* @returns {import('#client').Task}
* @param {TaskCallback} callback
* @returns {Task}
*/
export function loop(callback) {
/** @type {import('#client').TaskEntry} */
/** @type {TaskEntry} */
let task;
if (raf.tasks.size === 0) {

@ -1,4 +1,5 @@
/** @type {import('#client').Equals} */
/** @import { Equals } from '#client' */
/** @type {Equals} */
export function equals(value) {
return value === this.v;
}
@ -14,7 +15,7 @@ export function safe_not_equal(a, b) {
: a !== b || (a !== null && typeof a === 'object') || typeof a === 'function';
}
/** @type {import('#client').Equals} */
/** @type {Equals} */
export function safe_equals(value) {
return !safe_not_equal(value, this.v);
}

@ -1,3 +1,4 @@
/** @import { Source } from './types.js' */
import { DEV } from 'esm-env';
import {
PROPS_IS_IMMUTABLE,
@ -88,7 +89,7 @@ export function rest_props(props, exclude, name) {
/**
* The proxy handler for legacy $$restProps and $$props
* @type {ProxyHandler<{ props: Record<string | symbol, unknown>, exclude: Array<string | symbol>, special: Record<string | symbol, (v?: unknown) => unknown>, version: import('./types.js').Source<number> }>}}
* @type {ProxyHandler<{ props: Record<string | symbol, unknown>, exclude: Array<string | symbol>, special: Record<string | symbol, (v?: unknown) => unknown>, version: Source<number> }>}}
*/
const legacy_rest_props_handler = {
get(target, key) {

@ -1,3 +1,5 @@
/** @import { StoreReferencesContainer, Source } from '#client' */
/** @import { Store } from '#shared' */
import { subscribe_to_store } from '../../../store/utils.js';
import { noop } from '../../shared/utils.js';
import { UNINITIALIZED } from '../../../constants.js';
@ -10,13 +12,13 @@ import { mutable_source, set } from './sources.js';
* signal that will be updated when the store is. The store references container is needed to
* track reassignments to stores and to track the correct component context.
* @template V
* @param {import('#shared').Store<V> | null | undefined} store
* @param {Store<V> | null | undefined} store
* @param {string} store_name
* @param {import('#client').StoreReferencesContainer} stores
* @param {StoreReferencesContainer} stores
* @returns {V}
*/
export function store_get(store, store_name, stores) {
/** @type {import('#client').StoreReferencesContainer[''] | undefined} */
/** @type {StoreReferencesContainer[''] | undefined} */
let entry = stores[store_name];
const is_new = entry === undefined;
@ -46,12 +48,12 @@ export function store_get(store, store_name, stores) {
* Unsubscribe from a store if it's not the same as the one in the store references container.
* We need this in addition to `store_get` because someone could unsubscribe from a store but
* then never subscribe to the new one (if any), causing the subscription to stay open wrongfully.
* @param {import('#shared').Store<any> | null | undefined} store
* @param {Store<any> | null | undefined} store
* @param {string} store_name
* @param {import('#client').StoreReferencesContainer} stores
* @param {StoreReferencesContainer} stores
*/
export function store_unsub(store, store_name, stores) {
/** @type {import('#client').StoreReferencesContainer[''] | undefined} */
/** @type {StoreReferencesContainer[''] | undefined} */
let entry = stores[store_name];
if (entry && entry.store !== store) {
@ -65,8 +67,8 @@ export function store_unsub(store, store_name, stores) {
/**
* @template V
* @param {import('#shared').Store<V> | null | undefined} store
* @param {import('#client').Source<V>} source
* @param {Store<V> | null | undefined} store
* @param {Source<V>} source
*/
function connect_store_to_signal(store, source) {
if (store == null) {
@ -80,7 +82,7 @@ function connect_store_to_signal(store, source) {
/**
* Sets the new value of a store and returns that value.
* @template V
* @param {import('#shared').Store<V>} store
* @param {Store<V>} store
* @param {V} value
* @returns {V}
*/
@ -90,7 +92,7 @@ export function store_set(store, value) {
}
/**
* @param {import('#client').StoreReferencesContainer} stores
* @param {StoreReferencesContainer} stores
* @param {string} store_name
*/
export function invalidate_store(stores, store_name) {
@ -102,7 +104,7 @@ export function invalidate_store(stores, store_name) {
/**
* Unsubscribes from all auto-subscribed stores on destroy
* @param {import('#client').StoreReferencesContainer} stores
* @param {StoreReferencesContainer} stores
*/
export function unsubscribe_on_destroy(stores) {
on_destroy(() => {
@ -116,7 +118,7 @@ export function unsubscribe_on_destroy(stores) {
/**
* Updates a store with a new value.
* @param {import('#shared').Store<V>} store the store to update
* @param {Store<V>} store the store to update
* @param {any} expression the expression that mutates the store
* @param {V} new_value the new store value
* @template V
@ -127,7 +129,7 @@ export function mutate_store(store, expression, new_value) {
}
/**
* @param {import('#shared').Store<number>} store
* @param {Store<number>} store
* @param {number} store_value
* @param {1 | -1} [d]
* @returns {number}
@ -138,7 +140,7 @@ export function update_store(store, store_value, d = 1) {
}
/**
* @param {import('#shared').Store<number>} store
* @param {Store<number>} store
* @param {number} store_value
* @param {1 | -1} [d]
* @returns {number}

@ -1,3 +1,4 @@
/** @import { Raf } from '#client' */
import { noop } from '../shared/utils.js';
const is_client = typeof window !== 'undefined';
@ -6,7 +7,7 @@ const request_animation_frame = is_client ? requestAnimationFrame : noop;
const now = is_client ? () => performance.now() : () => Date.now();
/** @type {import('#client').Raf} */
/** @type {Raf} */
export const raf = {
tick: /** @param {any} _ */ (_) => request_animation_frame(_),
now: () => now(),

@ -1,8 +1,9 @@
/** @import { Component } from '#server' */
import { DEV } from 'esm-env';
import { on_destroy } from './index.js';
import * as e from '../shared/errors.js';
/** @type {import('#server').Component | null} */
/** @type {Component | null} */
export var current_component = null;
/**
@ -65,7 +66,7 @@ export function push(fn) {
}
export function pop() {
var component = /** @type {import('#server').Component} */ (current_component);
var component = /** @type {Component} */ (current_component);
var ondestroy = component.d;
@ -77,7 +78,7 @@ export function pop() {
}
/**
* @param {import('#server').Component} component_context
* @param {Component} component_context
* @returns {Map<unknown, unknown> | null}
*/
function get_parent_context(component_context) {

@ -1,3 +1,4 @@
/** @import { ComponentConstructorOptions, ComponentType, SvelteComponent, Component } from 'svelte' */
import { proxy } from '../internal/client/proxy.js';
import { user_pre_effect } from '../internal/client/reactivity/effects.js';
import { hydrate, mount, unmount } from '../internal/client/render.js';
@ -13,13 +14,13 @@ import { define_property } from '../internal/client/utils.js';
* @template {Record<string, any>} Events
* @template {Record<string, any>} Slots
*
* @param {import('svelte').ComponentConstructorOptions<Props> & {
* component: import('svelte').ComponentType<import('svelte').SvelteComponent<Props, Events, Slots>> | import('svelte').Component<Props>;
* @param {ComponentConstructorOptions<Props> & {
* component: ComponentType<SvelteComponent<Props, Events, Slots>> | Component<Props>;
* immutable?: boolean;
* hydrate?: boolean;
* recover?: boolean;
* }} options
* @returns {import('svelte').SvelteComponent<Props, Events, Slots> & Exports}
* @returns {SvelteComponent<Props, Events, Slots> & Exports}
*/
export function createClassComponent(options) {
// @ts-expect-error $$prop_def etc are not actually defined
@ -36,8 +37,8 @@ export function createClassComponent(options) {
* @template {Record<string, any>} Events
* @template {Record<string, any>} Slots
*
* @param {import('svelte').SvelteComponent<Props, Events, Slots> | import('svelte').Component<Props>} component
* @returns {import('svelte').ComponentType<import('svelte').SvelteComponent<Props, Events, Slots> & Exports>}
* @param {SvelteComponent<Props, Events, Slots> | Component<Props>} component
* @returns {ComponentType<SvelteComponent<Props, Events, Slots> & Exports>}
*/
export function asClassComponent(component) {
// @ts-expect-error $$prop_def etc are not actually defined
@ -60,7 +61,7 @@ class Svelte4Component {
#instance;
/**
* @param {import('svelte').ComponentConstructorOptions & {
* @param {ComponentConstructorOptions & {
* component: any;
* immutable?: boolean;
* hydrate?: boolean;

@ -1,3 +1,4 @@
/** @import { SvelteComponent } from '../index.js' */
import { asClassComponent as as_class_component, createClassComponent } from './legacy-client.js';
import { render } from '../internal/server/index.js';
@ -15,8 +16,8 @@ export { createClassComponent };
* @template {Record<string, any>} Events
* @template {Record<string, any>} Slots
*
* @param {import('../index.js').SvelteComponent<Props, Events, Slots>} component
* @returns {typeof import('../index.js').SvelteComponent<Props, Events, Slots> & Exports}
* @param {SvelteComponent<Props, Events, Slots>} component
* @returns {typeof SvelteComponent<Props, Events, Slots> & Exports}
*/
export function asClassComponent(component) {
const component_constructor = as_class_component(component);

@ -1,3 +1,6 @@
/** @import { Task } from '../internal/client/types' */
/** @import { Tweened } from './public' */
/** @import { TweenedOptions } from './private' */
import { writable } from '../store/index.js';
import { raf } from '../internal/client/timing.js';
import { loop } from '../internal/client/loop.js';
@ -76,17 +79,17 @@ function get_interpolator(a, b) {
* https://svelte.dev/docs/svelte-motion#tweened
* @template T
* @param {T} [value]
* @param {import('./private').TweenedOptions<T>} [defaults]
* @returns {import('./public').Tweened<T>}
* @param {TweenedOptions<T>} [defaults]
* @returns {Tweened<T>}
*/
export function tweened(value, defaults = {}) {
const store = writable(value);
/** @type {import('../internal/client/types').Task} */
/** @type {Task} */
let task;
let target_value = value;
/**
* @param {T} new_value
* @param {import('./private').TweenedOptions<T>} [opts]
* @param {TweenedOptions<T>} [opts]
*/
function set(new_value, opts) {
target_value = new_value;
@ -96,7 +99,7 @@ export function tweened(value, defaults = {}) {
return Promise.resolve();
}
/** @type {import('../internal/client/types').Task | null} */
/** @type {Task | null} */
let previous_task = task;
let started = false;

@ -1,9 +1,11 @@
/** @import { Readable, StartStopNotifier, Subscriber, Unsubscriber, Updater, Writable } from './public' */
/** @import { Invalidator, Stores, StoresValues, SubscribeInvalidateTuple } from './private' */
import { noop, run_all } from '../internal/shared/utils.js';
import { safe_not_equal } from '../internal/client/reactivity/equality.js';
import { subscribe_to_store } from './utils.js';
/**
* @type {Array<import('./private').SubscribeInvalidateTuple<any> | any>}
* @type {Array<SubscribeInvalidateTuple<any> | any>}
*/
const subscriber_queue = [];
@ -13,8 +15,8 @@ const subscriber_queue = [];
* https://svelte.dev/docs/svelte-store#readable
* @template T
* @param {T} [value] initial value
* @param {import('./public').StartStopNotifier<T>} [start]
* @returns {import('./public').Readable<T>}
* @param {StartStopNotifier<T>} [start]
* @returns {Readable<T>}
*/
export function readable(value, start) {
return {
@ -28,14 +30,14 @@ export function readable(value, start) {
* https://svelte.dev/docs/svelte-store#writable
* @template T
* @param {T} [value] initial value
* @param {import('./public').StartStopNotifier<T>} [start]
* @returns {import('./public').Writable<T>}
* @param {StartStopNotifier<T>} [start]
* @returns {Writable<T>}
*/
export function writable(value, start = noop) {
/** @type {import('./public').Unsubscriber | null} */
/** @type {Unsubscriber | null} */
let stop = null;
/** @type {Set<import('./private').SubscribeInvalidateTuple<T>>} */
/** @type {Set<SubscribeInvalidateTuple<T>>} */
const subscribers = new Set();
/**
@ -63,7 +65,7 @@ export function writable(value, start = noop) {
}
/**
* @param {import('./public').Updater<T>} fn
* @param {Updater<T>} fn
* @returns {void}
*/
function update(fn) {
@ -71,12 +73,12 @@ export function writable(value, start = noop) {
}
/**
* @param {import('./public').Subscriber<T>} run
* @param {import('./private').Invalidator<T>} [invalidate]
* @returns {import('./public').Unsubscriber}
* @param {Subscriber<T>} run
* @param {Invalidator<T>} [invalidate]
* @returns {Unsubscriber}
*/
function subscribe(run, invalidate = noop) {
/** @type {import('./private').SubscribeInvalidateTuple<T>} */
/** @type {SubscribeInvalidateTuple<T>} */
const subscriber = [run, invalidate];
subscribers.add(subscriber);
if (subscribers.size === 1) {
@ -99,38 +101,38 @@ export function writable(value, start = noop) {
* applying an aggregation function over its input values.
*
* https://svelte.dev/docs/svelte-store#derived
* @template {import('./private.js').Stores} S
* @template {Stores} S
* @template T
* @overload
* @param {S} stores
* @param {(values: import('./private.js').StoresValues<S>, set: (value: T) => void, update: (fn: import('./public.js').Updater<T>) => void) => import('./public.js').Unsubscriber | void} fn
* @param {(values: StoresValues<S>, set: (value: T) => void, update: (fn: Updater<T>) => void) => Unsubscriber | void} fn
* @param {T} [initial_value]
* @returns {import('./public.js').Readable<T>}
* @returns {Readable<T>}
*/
/**
* Derived value store by synchronizing one or more readable stores and
* applying an aggregation function over its input values.
*
* https://svelte.dev/docs/svelte-store#derived
* @template {import('./private.js').Stores} S
* @template {Stores} S
* @template T
* @overload
* @param {S} stores
* @param {(values: import('./private.js').StoresValues<S>) => T} fn
* @param {(values: StoresValues<S>) => T} fn
* @param {T} [initial_value]
* @returns {import('./public.js').Readable<T>}
* @returns {Readable<T>}
*/
/**
* @template {import('./private.js').Stores} S
* @template {Stores} S
* @template T
* @param {S} stores
* @param {Function} fn
* @param {T} [initial_value]
* @returns {import('./public.js').Readable<T>}
* @returns {Readable<T>}
*/
export function derived(stores, fn, initial_value) {
const single = !Array.isArray(stores);
/** @type {Array<import('./public').Readable<any>>} */
/** @type {Array<Readable<any>>} */
const stores_array = single ? [stores] : stores;
if (!stores_array.every(Boolean)) {
throw new Error('derived() expects stores as input, got a falsy value');
@ -187,8 +189,8 @@ export function derived(stores, fn, initial_value) {
*
* https://svelte.dev/docs/svelte-store#readonly
* @template T
* @param {import('./public').Readable<T>} store - store to make readonly
* @returns {import('./public').Readable<T>}
* @param {Readable<T>} store - store to make readonly
* @returns {Readable<T>}
*/
export function readonly(store) {
return {
@ -202,7 +204,7 @@ export function readonly(store) {
*
* https://svelte.dev/docs/svelte-store#get
* @template T
* @param {import('../store/public').Readable<T>} store
* @param {Readable<T>} store
* @returns {T}
*/
export function get(store) {

@ -1,17 +1,16 @@
import { Readable, Subscriber } from './public.js';
/** Cleanup logic callback. */
export type Invalidator<T> = (value?: T) => void;
type Invalidator<T> = (value?: T) => void;
/** Pair of subscriber and invalidator. */
export type SubscribeInvalidateTuple<T> = [Subscriber<T>, Invalidator<T>];
type SubscribeInvalidateTuple<T> = [Subscriber<T>, Invalidator<T>];
/** One or more `Readable`s. */
export type Stores =
| Readable<any>
| [Readable<any>, ...Array<Readable<any>>]
| Array<Readable<any>>;
type Stores = Readable<any> | [Readable<any>, ...Array<Readable<any>>] | Array<Readable<any>>;
/** One or more values from `Readable` stores. */
export type StoresValues<T> =
type StoresValues<T> =
T extends Readable<infer U> ? U : { [K in keyof T]: T[K] extends Readable<infer U> ? U : never };
export { Invalidator, SubscribeInvalidateTuple, Stores, StoresValues };

@ -1,13 +1,13 @@
import type { Invalidator } from './private.js';
/** Callback to inform of a value updates. */
export type Subscriber<T> = (value: T) => void;
type Subscriber<T> = (value: T) => void;
/** Unsubscribes from value updates. */
export type Unsubscriber = () => void;
type Unsubscriber = () => void;
/** Callback to update a value. */
export type Updater<T> = (value: T) => T;
type Updater<T> = (value: T) => T;
/**
* Start and stop notification callbacks.
@ -18,13 +18,13 @@ export type Updater<T> = (value: T) => T;
* @returns {void | (() => void)} Optionally, a cleanup function that is called when the last remaining
* subscriber unsubscribes.
*/
export type StartStopNotifier<T> = (
type StartStopNotifier<T> = (
set: (value: T) => void,
update: (fn: Updater<T>) => void
) => void | (() => void);
/** Readable interface for subscribing. */
export interface Readable<T> {
interface Readable<T> {
/**
* Subscribe on value changes.
* @param run subscription callback
@ -34,7 +34,7 @@ export interface Readable<T> {
}
/** Writable interface for both updating and subscribing. */
export interface Writable<T> extends Readable<T> {
interface Writable<T> extends Readable<T> {
/**
* Set value and inform subscribers.
* @param value to set
@ -48,4 +48,6 @@ export interface Writable<T> extends Readable<T> {
update(this: void, updater: Updater<T>): void;
}
export { Readable, StartStopNotifier, Subscriber, Unsubscriber, Updater, Writable };
export * from './index.js';

@ -1,8 +1,9 @@
/** @import { Readable } from './public' */
import { noop } from '../internal/shared/utils.js';
/**
* @template T
* @param {import('./public').Readable<T> | null | undefined} store
* @param {Readable<T> | null | undefined} store
* @param {(value: T) => void} run
* @param {(value: T) => void} [invalidate]
* @returns {() => void}

@ -1,3 +1,4 @@
/** @import { BlurParams, CrossfadeParams, DrawParams, FadeParams, FlyParams, ScaleParams, SlideParams, TransitionConfig } from './public' */
/** @param {number} x */
const linear = (x) => x;
@ -29,8 +30,8 @@ function split_css_unit(value) {
*
* https://svelte.dev/docs/svelte-transition#blur
* @param {Element} node
* @param {import('./public').BlurParams} [params]
* @returns {import('./public').TransitionConfig}
* @param {BlurParams} [params]
* @returns {TransitionConfig}
*/
export function blur(
node,
@ -54,8 +55,8 @@ export function blur(
*
* https://svelte.dev/docs/svelte-transition#fade
* @param {Element} node
* @param {import('./public').FadeParams} [params]
* @returns {import('./public').TransitionConfig}
* @param {FadeParams} [params]
* @returns {TransitionConfig}
*/
export function fade(node, { delay = 0, duration = 400, easing = linear } = {}) {
const o = +getComputedStyle(node).opacity;
@ -72,8 +73,8 @@ export function fade(node, { delay = 0, duration = 400, easing = linear } = {})
*
* https://svelte.dev/docs/svelte-transition#fly
* @param {Element} node
* @param {import('./public').FlyParams} [params]
* @returns {import('./public').TransitionConfig}
* @param {FlyParams} [params]
* @returns {TransitionConfig}
*/
export function fly(
node,
@ -100,8 +101,8 @@ export function fly(
*
* https://svelte.dev/docs/svelte-transition#slide
* @param {Element} node
* @param {import('./public').SlideParams} [params]
* @returns {import('./public').TransitionConfig}
* @param {SlideParams} [params]
* @returns {TransitionConfig}
*/
export function slide(node, { delay = 0, duration = 400, easing = cubic_out, axis = 'y' } = {}) {
const style = getComputedStyle(node);
@ -144,8 +145,8 @@ export function slide(node, { delay = 0, duration = 400, easing = cubic_out, axi
*
* https://svelte.dev/docs/svelte-transition#scale
* @param {Element} node
* @param {import('./public').ScaleParams} [params]
* @returns {import('./public').TransitionConfig}
* @param {ScaleParams} [params]
* @returns {TransitionConfig}
*/
export function scale(
node,
@ -172,8 +173,8 @@ export function scale(
*
* https://svelte.dev/docs/svelte-transition#draw
* @param {SVGElement & { getTotalLength(): number }} node
* @param {import('./public').DrawParams} [params]
* @returns {import('./public').TransitionConfig}
* @param {DrawParams} [params]
* @returns {TransitionConfig}
*/
export function draw(node, { delay = 0, speed, duration, easing = cubic_in_out } = {}) {
let len = node.getTotalLength();
@ -218,10 +219,10 @@ function assign(tar, src) {
* The `crossfade` function creates a pair of [transitions](https://svelte.dev/docs#template-syntax-element-directives-transition-fn) called `send` and `receive`. When an element is 'sent', it looks for a corresponding element being 'received', and generates a transition that transforms the element to its counterpart's position and fades it out. When an element is 'received', the reverse happens. If there is no counterpart, the `fallback` transition is used.
*
* https://svelte.dev/docs/svelte-transition#crossfade
* @param {import('./public').CrossfadeParams & {
* fallback?: (node: Element, params: import('./public').CrossfadeParams, intro: boolean) => import('./public').TransitionConfig;
* @param {CrossfadeParams & {
* fallback?: (node: Element, params: CrossfadeParams, intro: boolean) => TransitionConfig;
* }} params
* @returns {[(node: any, params: import('./public').CrossfadeParams & { key: any; }) => () => import('./public').TransitionConfig, (node: any, params: import('./public').CrossfadeParams & { key: any; }) => () => import('./public').TransitionConfig]}
* @returns {[(node: any, params: CrossfadeParams & { key: any; }) => () => TransitionConfig, (node: any, params: CrossfadeParams & { key: any; }) => () => TransitionConfig]}
*/
export function crossfade({ fallback, ...defaults }) {
/** @type {Map<any, Element>} */
@ -232,8 +233,8 @@ export function crossfade({ fallback, ...defaults }) {
/**
* @param {Element} from_node
* @param {Element} node
* @param {import('./public').CrossfadeParams} params
* @returns {import('./public').TransitionConfig}
* @param {CrossfadeParams} params
* @returns {TransitionConfig}
*/
function crossfade(from_node, node, params) {
const {
@ -269,7 +270,7 @@ export function crossfade({ fallback, ...defaults }) {
* @param {Map<any, Element>} items
* @param {Map<any, Element>} counterparts
* @param {boolean} intro
* @returns {(node: any, params: import('./public').CrossfadeParams & { key: any; }) => () => import('./public').TransitionConfig}
* @returns {(node: any, params: CrossfadeParams & { key: any; }) => () => TransitionConfig}
*/
function transition(items, counterparts, intro) {
// @ts-expect-error TODO improve typings (are the public types wrong?)

@ -1,6 +1,6 @@
export type EasingFunction = (t: number) => number;
type EasingFunction = (t: number) => number;
export interface TransitionConfig {
interface TransitionConfig {
delay?: number;
duration?: number;
easing?: EasingFunction;
@ -8,7 +8,7 @@ export interface TransitionConfig {
tick?: (t: number, u: number) => void;
}
export interface BlurParams {
interface BlurParams {
delay?: number;
duration?: number;
easing?: EasingFunction;
@ -16,13 +16,13 @@ export interface BlurParams {
opacity?: number;
}
export interface FadeParams {
interface FadeParams {
delay?: number;
duration?: number;
easing?: EasingFunction;
}
export interface FlyParams {
interface FlyParams {
delay?: number;
duration?: number;
easing?: EasingFunction;
@ -31,14 +31,14 @@ export interface FlyParams {
opacity?: number;
}
export interface SlideParams {
interface SlideParams {
delay?: number;
duration?: number;
easing?: EasingFunction;
axis?: 'x' | 'y';
}
export interface ScaleParams {
interface ScaleParams {
delay?: number;
duration?: number;
easing?: EasingFunction;
@ -46,17 +46,29 @@ export interface ScaleParams {
opacity?: number;
}
export interface DrawParams {
interface DrawParams {
delay?: number;
speed?: number;
duration?: number | ((len: number) => number);
easing?: EasingFunction;
}
export interface CrossfadeParams {
interface CrossfadeParams {
delay?: number;
duration?: number | ((len: number) => number);
easing?: EasingFunction;
}
export {
EasingFunction,
TransitionConfig,
BlurParams,
FadeParams,
FlyParams,
SlideParams,
ScaleParams,
DrawParams,
CrossfadeParams
};
export * from './index.js';

@ -1,3 +1,4 @@
/** @import { CompileOptions } from '#compiler' */
import * as fs from 'node:fs';
import * as path from 'node:path';
import glob from 'tiny-glob/sync.js';
@ -53,7 +54,7 @@ export function create_deferred() {
*
* @param {string} cwd
* @param {'client' | 'server'} generate
* @param {Partial<import('#compiler').CompileOptions>} compileOptions
* @param {Partial<CompileOptions>} compileOptions
* @param {boolean} [output_map]
* @param {any} [preprocessor]
*/

@ -1,3 +1,5 @@
/** @import { assert } from 'vitest' */
/** @import { CompileOptions, Warning } from '#compiler' */
/**
* @param {any} a
* @param {any} b
@ -118,9 +120,9 @@ function normalize_children(node) {
* html?: string;
* ssrHtml?: string;
* props?: Props;
* compileOptions?: Partial<import('#compiler').CompileOptions>;
* compileOptions?: Partial<CompileOptions>;
* test?: (args: {
* assert: typeof import('vitest').assert & {
* assert: typeof assert & {
* htmlEqual(a: string, b: string, description?: string): void;
* htmlEqualWithOptions(
* a: string,
@ -129,7 +131,7 @@ function normalize_children(node) {
* description?: string
* ): void;
* };
* compileOptions: import('#compiler').CompileOptions;
* compileOptions: CompileOptions;
* component: Props & {
* [key: string]: any;
* };
@ -150,7 +152,7 @@ function normalize_children(node) {
* accessors?: boolean;
* immutable?: boolean;
* dev?: boolean;
* warnings?: import('#compiler').Warning[];
* warnings?: Warning[];
*}} args
*/
export function test(args) {

@ -1,3 +1,4 @@
/** @import { Location } from 'locate-character' */
import * as assert from 'node:assert';
import * as path from 'node:path';
import { getLocator } from 'locate-character';
@ -15,7 +16,7 @@ export function assert_mapped({ code, filename, input, input_code, preprocessed
if (filename === undefined) filename = 'input.svelte';
if (input_code === undefined) input_code = code;
const source_loc = /** @type {import('locate-character').Location} */ (locate_input(input_code));
const source_loc = /** @type {Location} */ (locate_input(input_code));
assert.notEqual(source_loc, undefined, `failed to locate "${input_code}" in "${filename}"`);
const transformed_loc = preprocessed.locate_1(code);

@ -1,3 +1,4 @@
/** @import { PreprocessorGroup, Preprocessor } from '../../../../src/compiler/public' */
import * as path from 'node:path';
import MagicString from 'magic-string';
import { test } from '../../test';
@ -10,10 +11,10 @@ let comment_multi = true;
* @param {'script' | 'style'} tag_name
* @param {string} search
* @param {string} replace
* @returns {import('../../../../src/compiler/public').PreprocessorGroup}
* @returns {PreprocessorGroup}
*/
function get_processor(tag_name, search, replace) {
/** @type {import('../../../../src/compiler/public').Preprocessor} */
/** @type {Preprocessor} */
const preprocessor = ({ content, filename = '' }) => {
let code = content.slice();
const ms = new MagicString(code);

@ -1,3 +1,4 @@
/** @import { Location } from 'locate-character' */
import MagicString from 'magic-string';
import { TraceMap, originalPositionFor } from '@jridgewell/trace-mapping';
import { test } from '../../test';
@ -54,10 +55,7 @@ export default test({
['--done-replace-twice: green', '--replace-me-twice', 10, 2]
]).forEach(([content, name, line, column]) => {
assert.deepEqual(
originalPositionFor(
map,
/** @type {import('locate-character').Location_1} */ (locate(content))
),
originalPositionFor(map, /** @type {Location} */ (locate(content))),
{
source: sourcefile,
name,

@ -952,6 +952,29 @@ declare module 'svelte/compiler' {
inside_rest?: boolean;
} | null;
}
/**
* 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.
*
* https://svelte.dev/docs/svelte-compiler#svelte-preprocess
* */
function preprocess(source: string, preprocessor: PreprocessorGroup | PreprocessorGroup[], options?: {
filename?: string;
} | undefined): Promise<Processed>;
/**
* The current version, as set in package.json.
*
* https://svelte.dev/docs/svelte-compiler#svelte-version
* */
const VERSION: string;
/**
* Does a best-effort migration of Svelte code towards using runes, event attributes and render tags.
* May throw an error if the code is too complex to migrate automatically.
*
* */
function migrate(source: string): {
code: string;
};
interface BaseNode_1 {
type: string;
start: number;
@ -1191,29 +1214,6 @@ declare module 'svelte/compiler' {
| LegacyAttributeShorthand
| LegacyCssNode
| Text;
/**
* 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.
*
* https://svelte.dev/docs/svelte-compiler#svelte-preprocess
* */
function preprocess(source: string, preprocessor: PreprocessorGroup | PreprocessorGroup[], options?: {
filename?: string;
} | undefined): Promise<Processed>;
/**
* The current version, as set in package.json.
*
* https://svelte.dev/docs/svelte-compiler#svelte-version
* */
const VERSION: string;
/**
* Does a best-effort migration of Svelte code towards using runes, event attributes and render tags.
* May throw an error if the code is too complex to migrate automatically.
*
* */
function migrate(source: string): {
code: string;
};
class Scope {
constructor(root: ScopeRoot, parent: Scope | null, porous: boolean);
@ -2030,25 +2030,26 @@ declare module 'svelte/easing' {
}
declare module 'svelte/legacy' {
import type { ComponentConstructorOptions, SvelteComponent, ComponentType, Component } from 'svelte';
/**
* Takes the same options as a Svelte 4 component and the component function and returns a Svelte 4 compatible component.
*
* @deprecated Use this only as a temporary solution to migrate your imperative component code to Svelte 5.
*
* */
function createClassComponent<Props extends Record<string, any>, Exports extends Record<string, any>, Events extends Record<string, any>, Slots extends Record<string, any>>(options: import("svelte").ComponentConstructorOptions<Props> & {
component: import("svelte").ComponentType<import("svelte").SvelteComponent<Props, Events, Slots>> | import("svelte").Component<Props>;
function createClassComponent<Props extends Record<string, any>, Exports extends Record<string, any>, Events extends Record<string, any>, Slots extends Record<string, any>>(options: ComponentConstructorOptions<Props> & {
component: ComponentType<SvelteComponent<Props, Events, Slots>> | Component<Props>;
immutable?: boolean;
hydrate?: boolean;
recover?: boolean;
}): import("svelte").SvelteComponent<Props, Events, Slots> & Exports;
}): SvelteComponent<Props, Events, Slots> & Exports;
/**
* Takes the component function and returns a Svelte 4 compatible component constructor.
*
* @deprecated Use this only as a temporary solution to migrate your imperative component code to Svelte 5.
*
* */
function asClassComponent<Props extends Record<string, any>, Exports extends Record<string, any>, Events extends Record<string, any>, Slots extends Record<string, any>>(component: import("svelte").SvelteComponent<Props, Events, Slots> | import("svelte").Component<Props>): import("svelte").ComponentType<import("svelte").SvelteComponent<Props, Events, Slots> & Exports>;
function asClassComponent<Props extends Record<string, any>, Exports extends Record<string, any>, Events extends Record<string, any>, Slots extends Record<string, any>>(component: SvelteComponent<Props, Events, Slots> | Component<Props>): ComponentType<SvelteComponent<Props, Events, Slots> & Exports>;
/**
* Runs the given function once immediately on the server, and works like `$effect.pre` on the client.
*
@ -2252,10 +2253,7 @@ declare module 'svelte/store' {
type Invalidator<T> = (value?: T) => void;
/** One or more `Readable`s. */
type Stores =
| Readable<any>
| [Readable<any>, ...Array<Readable<any>>]
| Array<Readable<any>>;
type Stores = Readable<any> | [Readable<any>, ...Array<Readable<any>>] | Array<Readable<any>>;
/** One or more values from `Readable` stores. */
type StoresValues<T> =
@ -2302,7 +2300,7 @@ declare module 'svelte/store' {
* */
function get<T>(store: Readable<T>): T;
export { Subscriber, Unsubscriber, Updater, StartStopNotifier, Readable, Writable, readable, writable, derived, readonly, get };
export { Readable, StartStopNotifier, Subscriber, Unsubscriber, Updater, Writable, readable, writable, derived, readonly, get };
}
declare module 'svelte/transition' {

Loading…
Cancel
Save