pull/17825/merge
Mathias Picker 1 day ago committed by GitHub
commit 76d9120ad4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
"svelte": patch
---
perf: use walk_readonly for analysis-phase AST walks

@ -1,10 +1,10 @@
/** @import { VariableDeclarator, Node, Identifier, AssignmentExpression, LabeledStatement, ExpressionStatement } from 'estree' */
/** @import { Visitors } from 'zimmerframe' */
/** @import { ReadonlyVisitors } from 'zimmerframe' */
/** @import { ComponentAnalysis } from '../phases/types.js' */
/** @import { Scope } from '../phases/scope.js' */
/** @import { AST, Binding, ValidatedCompileOptions } from '#compiler' */
import MagicString from 'magic-string';
import { walk } from 'zimmerframe';
import { walk_readonly } from 'zimmerframe';
import { parse } from '../phases/1-parse/index.js';
import { regex_valid_component_name } from '../phases/1-parse/state/element.js';
import { analyze_component } from '../phases/2-analyze/index.js';
@ -215,11 +215,11 @@ export function migrate(source, { filename, use_ts } = {}) {
}
if (parsed.instance) {
walk(parsed.instance.content, state, instance_script);
walk_readonly(parsed.instance.content, state, instance_script);
}
state = { ...state, scope: analysis.template.scope };
walk(parsed.fragment, state, template);
walk_readonly(parsed.fragment, state, template);
let insertion_point = parsed.instance
? /** @type {number} */ (parsed.instance.content.start)
@ -483,7 +483,7 @@ export function migrate(source, { filename, use_ts } = {}) {
* }} State
*/
/** @type {Visitors<AST.SvelteNode, State>} */
/** @type {ReadonlyVisitors<AST.SvelteNode, State>} */
const instance_script = {
_(node, { state, next }) {
// @ts-expect-error
@ -1054,7 +1054,7 @@ function trim_block(state, start, end) {
}
}
/** @type {Visitors<AST.SvelteNode, State>} */
/** @type {ReadonlyVisitors<AST.SvelteNode, State>} */
const template = {
Identifier(node, { state, path }) {
handle_identifier(node, state, path);

@ -1,7 +1,7 @@
/** @import { ComponentAnalysis } from '../../types.js' */
/** @import { AST } from '#compiler' */
/** @import { Visitors } from 'zimmerframe' */
import { walk } from 'zimmerframe';
/** @import { ReadonlyVisitors } from 'zimmerframe' */
import { walk_readonly } from 'zimmerframe';
import * as e from '../../../errors.js';
import { is_keyframes_node } from '../../css.js';
import { is_global, is_unscoped_pseudo_class } from './utils.js';
@ -15,7 +15,7 @@ import { is_global, is_unscoped_pseudo_class } from './utils.js';
*/
/**
* @typedef {Visitors<AST.CSS.Node, CssState>} CssVisitors
* @typedef {ReadonlyVisitors<AST.CSS.Node, CssState>} CssVisitors
*/
/**
@ -183,7 +183,7 @@ const css_visitors = {
if (node.metadata.is_global_like || node.metadata.is_global) {
// So that nested selectors like `:root:not(.x)` are not marked as unused
for (const child of node.selectors) {
walk(/** @type {AST.CSS.Node} */ (child), null, {
walk_readonly(/** @type {AST.CSS.Node} */ (child), null, {
ComplexSelector(node, context) {
node.metadata.used = true;
context.next();
@ -222,7 +222,7 @@ const css_visitors = {
node.metadata.is_global_block = is_global_block = true;
for (let i = 1; i < child.selectors.length; i++) {
walk(/** @type {AST.CSS.Node} */ (child.selectors[i]), null, {
walk_readonly(/** @type {AST.CSS.Node} */ (child.selectors[i]), null, {
ComplexSelector(node) {
node.metadata.used = true;
}
@ -327,5 +327,5 @@ export function analyze_css(stylesheet, analysis) {
analysis
};
walk(stylesheet, css_state, css_visitors);
walk_readonly(stylesheet, css_state, css_visitors);
}

@ -1,5 +1,5 @@
/** @import * as Compiler from '#compiler' */
import { walk } from 'zimmerframe';
import { walk_readonly } from 'zimmerframe';
import {
get_parent_rules,
get_possible_values,
@ -128,7 +128,7 @@ const seen = new Set();
* @param {Iterable<Compiler.AST.RegularElement | Compiler.AST.SvelteElement>} elements
*/
export function prune(stylesheet, elements) {
walk(/** @type {Compiler.AST.CSS.Node} */ (stylesheet), null, {
walk_readonly(/** @type {Compiler.AST.CSS.Node} */ (stylesheet), null, {
Rule(node, context) {
if (node.metadata.is_global_block) {
context.visit(node.prelude);
@ -176,7 +176,7 @@ function get_relative_selectors(node) {
// nesting could be inside pseudo classes like :is, :has or :where
for (let selector of selectors) {
walk(selector, null, {
walk_readonly(selector, null, {
// @ts-ignore
NestingSelector() {
has_explicit_nesting_selector = true;
@ -534,7 +534,7 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
// with descendants, in which case we scope them all.
if (name === 'not' && selector.args) {
for (const complex_selector of selector.args.children) {
walk(complex_selector, null, {
walk_readonly(complex_selector, null, {
ComplexSelector(node, context) {
node.metadata.used = true;
context.next();
@ -869,7 +869,7 @@ function get_ancestor_elements(node, adjacent_only, seen = new Set()) {
if (select_element && (!adjacent_only || is_direct_child)) {
/** @type {Compiler.AST.RegularElement | null} */
let selectedcontent_element = null;
walk(select_element, null, {
walk_readonly(select_element, null, {
RegularElement(child, context) {
if (child.name === 'selectedcontent') {
selectedcontent_element = child;
@ -912,7 +912,7 @@ function get_descendant_elements(node, adjacent_only, seen = new Set()) {
* @param {Compiler.AST.SvelteNode} node
*/
function walk_children(node) {
walk(node, null, {
walk_readonly(node, null, {
_(node, context) {
if (node.type === 'RegularElement' || node.type === 'SvelteElement') {
descendants.push(node);
@ -946,7 +946,7 @@ function get_descendant_elements(node, adjacent_only, seen = new Set()) {
);
if (select_element) {
walk(
walk_readonly(
select_element,
{ inside_option: false },
{

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

@ -2,7 +2,7 @@
/** @import { Binding, AST, ValidatedCompileOptions, ValidatedModuleCompileOptions } from '#compiler' */
/** @import { AnalysisState, Visitors } from './types' */
/** @import { Analysis, ComponentAnalysis, Js, ReactiveStatement, Template } from '../types' */
import { walk } from 'zimmerframe';
import { walk_readonly } from 'zimmerframe';
import { parse } from '../1-parse/acorn.js';
import * as e from '../../errors.js';
import * as w from '../../warnings.js';
@ -295,7 +295,7 @@ export function analyze_module(source, options) {
runes: true
});
walk(
walk_readonly(
/** @type {ESTree.Node} */ (ast),
{
scope,
@ -642,7 +642,7 @@ export function analyze_component(root, source, options) {
// more legacy nonsense: if an `each` binding is reassigned/mutated,
// treat the expression as being mutated as well
walk(/** @type {AST.SvelteNode} */ (template.ast), null, {
walk_readonly(/** @type {AST.SvelteNode} */ (template.ast), null, {
EachBlock(node) {
const scope = /** @type {Scope} */ (template.scopes.get(node));
@ -650,7 +650,7 @@ export function analyze_component(root, source, options) {
if (binding.updated) {
const state = { scope: /** @type {Scope} */ (scope.parent), scopes: template.scopes };
walk(node.expression, state, {
walk_readonly(node.expression, state, {
// @ts-expect-error
_: set_scope,
Identifier(node, context) {
@ -727,7 +727,7 @@ export function analyze_component(root, source, options) {
derived_function_depth: -1
};
walk(/** @type {AST.SvelteNode} */ (ast), state, visitors);
walk_readonly(/** @type {AST.SvelteNode} */ (ast), state, visitors);
}
// warn on any nonstate declarations that are a) reassigned and b) referenced in the template
@ -795,7 +795,7 @@ export function analyze_component(root, source, options) {
derived_function_depth: -1
};
walk(/** @type {AST.SvelteNode} */ (ast), state, visitors);
walk_readonly(/** @type {AST.SvelteNode} */ (ast), state, visitors);
}
for (const [name, binding] of instance.scope.declarations) {
@ -957,7 +957,7 @@ function calculate_blockers(instance, analysis) {
if (seen.has(expression)) return;
seen.add(expression);
walk(
walk_readonly(
expression,
{ scope },
{
@ -1010,7 +1010,7 @@ function calculate_blockers(instance, analysis) {
}
}
walk(
walk_readonly(
node,
{ scope },
{

@ -35,12 +35,8 @@ export interface AnalysisState {
derived_function_depth: number;
}
export type Context<State extends AnalysisState = AnalysisState> = import('zimmerframe').Context<
AST.SvelteNode,
State
>;
export type Context<State extends AnalysisState = AnalysisState> =
import('zimmerframe').ReadonlyContext<AST.SvelteNode, State>;
export type Visitors<State extends AnalysisState = AnalysisState> = import('zimmerframe').Visitors<
AST.SvelteNode,
State
>;
export type Visitors<State extends AnalysisState = AnalysisState> =
import('zimmerframe').ReadonlyVisitors<AST.SvelteNode, State>;

@ -44,7 +44,7 @@ import {
} from '../../../../patterns.js';
import { is_event_attribute, is_text_attribute } from '../../../../../utils/ast.js';
import { list } from '../../../../../utils/string.js';
import { walk } from 'zimmerframe';
import { walk_readonly } from 'zimmerframe';
import fuzzymatch from '../../../../1-parse/utils/fuzzymatch.js';
import { is_content_editable_binding } from '../../../../../../utils.js';
import * as w from '../../../../../warnings.js';
@ -456,7 +456,7 @@ export function check_element(node, context) {
/** @param {AST.TemplateNode} node */
const has_input_child = (node) => {
let has = false;
walk(
walk_readonly(
node,
{},
{

@ -1,8 +1,8 @@
/** @import { BinaryOperator, ClassDeclaration, Expression, FunctionDeclaration, Identifier, ImportDeclaration, MemberExpression, LogicalOperator, Node, Pattern, UnaryOperator, VariableDeclarator, Super, SimpleLiteral, FunctionExpression, ArrowFunctionExpression } from 'estree' */
/** @import { Context, Visitor } from 'zimmerframe' */
/** @import { ReadonlyContext, ReadonlyVisitor } from 'zimmerframe' */
/** @import { AST, BindingKind, DeclarationKind } from '#compiler' */
import is_reference from 'is-reference';
import { walk } from 'zimmerframe';
import { walk_readonly } from 'zimmerframe';
import { ExpressionMetadata } from './nodes.js';
import * as b from '#compiler/builders';
import * as e from '../errors.js';
@ -957,7 +957,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
}
/**
* @type {Visitor<Node, State, AST.SvelteNode>}
* @type {ReadonlyVisitor<Node, State, AST.SvelteNode>}
*/
const create_block_scope = (node, { state, next }) => {
const scope = state.scope.child(true);
@ -967,7 +967,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
};
/**
* @type {Visitor<AST.ElementLike, State, AST.SvelteNode>}
* @type {ReadonlyVisitor<AST.ElementLike, State, AST.SvelteNode>}
*/
const SvelteFragment = (node, { state, next }) => {
const scope = state.scope.child();
@ -976,7 +976,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
};
/**
* @type {Visitor<AST.Component | AST.SvelteComponent | AST.SvelteSelf, State, AST.SvelteNode>}
* @type {ReadonlyVisitor<AST.Component | AST.SvelteComponent | AST.SvelteSelf, State, AST.SvelteNode>}
*/
const Component = (node, context) => {
node.metadata.scopes = {
@ -1017,7 +1017,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
};
/**
* @type {Visitor<AST.AnimateDirective | AST.TransitionDirective | AST.UseDirective, State, AST.SvelteNode>}
* @type {ReadonlyVisitor<AST.AnimateDirective | AST.TransitionDirective | AST.UseDirective, State, AST.SvelteNode>}
*/
const SvelteDirective = (node, { state, path, visit }) => {
state.scope.reference(b.id(node.name.split('.')[0]), path);
@ -1029,7 +1029,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
let has_await = false;
walk(ast, state, {
walk_readonly(ast, state, {
AwaitExpression(node, context) {
// this doesn't _really_ belong here, but it allows us to
// automatically opt into runes mode on encountering
@ -1245,7 +1245,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
let inside_rest = false;
let is_rest_id = false;
walk(node.context, null, {
walk_readonly(node.context, null, {
Identifier(node) {
if (inside_rest && node === id) {
is_rest_id = true;
@ -1418,7 +1418,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
/**
* @template {{ scope: Scope, scopes: Map<AST.SvelteNode, Scope> }} State
* @param {AST.SvelteNode} node
* @param {Context<AST.SvelteNode, State>} context
* @param {ReadonlyContext<AST.SvelteNode, State>} context
*/
export function set_scope(node, { next, state }) {
const scope = state.scopes.get(node);

@ -1,6 +1,6 @@
/** @import { AST, Scope } from '#compiler' */
/** @import * as ESTree from 'estree' */
import { walk } from 'zimmerframe';
import { walk_readonly } from 'zimmerframe';
import * as b from '#compiler/builders';
/**
@ -149,7 +149,7 @@ export function extract_all_identifiers_from_expression(expr) {
/** @type {string[]} */
let keypath = [];
walk(
walk_readonly(
expr,
{},
{
@ -616,7 +616,7 @@ export function build_assignment_value(operator, left, right) {
export function has_await_expression(node) {
let has_await = false;
walk(node, null, {
walk_readonly(node, null, {
AwaitExpression(_node, context) {
has_await = true;
context.stop();

Loading…
Cancel
Save