Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions packages/svelte/src/compiler/phases/1-parse/state/element.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ import { decode_character_references } from '../utils/html.js';
import * as e from '../../../errors.js';
import * as w from '../../../warnings.js';
import { create_fragment } from '../utils/create.js';
import { create_attribute, create_expression_metadata, is_element_node } from '../../nodes.js';
import { create_attribute, ExpressionMetadata, is_element_node } from '../../nodes.js';
import { get_attribute_expression, is_expression_attribute } from '../../../utils/ast.js';
import { closing_tag_omitted } from '../../../../html-tree-validation.js';
import { list } from '../../../utils/string.js';
import { regex_whitespace } from '../../patterns.js';

const regex_invalid_unquoted_attribute_value = /^(\/>|[\s"'=<>`])/;
const regex_closing_textarea_tag = /^<\/textarea(\s[^>]*)?>/i;
Expand Down Expand Up @@ -297,7 +296,7 @@ export default function element(parser) {
element.tag = get_attribute_expression(definition);
}

element.metadata.expression = create_expression_metadata();
element.metadata.expression = new ExpressionMetadata();
}

if (is_top_level_script_or_style) {
Expand Down Expand Up @@ -508,7 +507,7 @@ function read_attribute(parser) {
end: parser.index,
expression,
metadata: {
expression: create_expression_metadata()
expression: new ExpressionMetadata()
}
};

Expand All @@ -528,7 +527,7 @@ function read_attribute(parser) {
end: parser.index,
expression,
metadata: {
expression: create_expression_metadata()
expression: new ExpressionMetadata()
}
};

Expand Down Expand Up @@ -568,7 +567,7 @@ function read_attribute(parser) {
name
},
metadata: {
expression: create_expression_metadata()
expression: new ExpressionMetadata()
}
};

Expand Down Expand Up @@ -628,7 +627,7 @@ function read_attribute(parser) {
modifiers: /** @type {Array<'important'>} */ (modifiers),
value,
metadata: {
expression: create_expression_metadata()
expression: new ExpressionMetadata()
}
};
}
Expand Down Expand Up @@ -658,7 +657,7 @@ function read_attribute(parser) {
name: directive_name,
expression,
metadata: {
expression: create_expression_metadata()
expression: new ExpressionMetadata()
}
};

Expand Down Expand Up @@ -824,7 +823,7 @@ function read_sequence(parser, done, location) {
end: parser.index,
expression,
metadata: {
expression: create_expression_metadata()
expression: new ExpressionMetadata()
}
};

Expand Down
18 changes: 9 additions & 9 deletions packages/svelte/src/compiler/phases/1-parse/state/tag.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/** @import { Parser } from '../index.js' */
import { walk } from 'zimmerframe';
import * as e from '../../../errors.js';
import { create_expression_metadata } from '../../nodes.js';
import { ExpressionMetadata } from '../../nodes.js';
import { parse_expression_at } from '../acorn.js';
import read_pattern from '../read/context.js';
import read_expression, { get_loose_identifier } from '../read/expression.js';
Expand Down Expand Up @@ -42,7 +42,7 @@ export default function tag(parser) {
end: parser.index,
expression,
metadata: {
expression: create_expression_metadata()
expression: new ExpressionMetadata()
}
});
}
Expand All @@ -65,7 +65,7 @@ function open(parser) {
consequent: create_fragment(),
alternate: null,
metadata: {
expression: create_expression_metadata()
expression: new ExpressionMetadata()
}
});

Expand Down Expand Up @@ -249,7 +249,7 @@ function open(parser) {
then: null,
catch: null,
metadata: {
expression: create_expression_metadata()
expression: new ExpressionMetadata()
}
});

Expand Down Expand Up @@ -334,7 +334,7 @@ function open(parser) {
expression,
fragment: create_fragment(),
metadata: {
expression: create_expression_metadata()
expression: new ExpressionMetadata()
}
});

Expand Down Expand Up @@ -477,7 +477,7 @@ function next(parser) {
consequent: create_fragment(),
alternate: null,
metadata: {
expression: create_expression_metadata()
expression: new ExpressionMetadata()
}
});

Expand Down Expand Up @@ -643,7 +643,7 @@ function special(parser) {
end: parser.index,
expression,
metadata: {
expression: create_expression_metadata()
expression: new ExpressionMetadata()
}
});

Expand Down Expand Up @@ -721,7 +721,7 @@ function special(parser) {
end: parser.index - 1
},
metadata: {
expression: create_expression_metadata()
expression: new ExpressionMetadata()
}
});
}
Expand All @@ -748,7 +748,7 @@ function special(parser) {
end: parser.index,
expression: /** @type {AST.RenderTag['expression']} */ (expression),
metadata: {
expression: create_expression_metadata(),
expression: new ExpressionMetadata(),
dynamic: false,
arguments: [],
path: [],
Expand Down
3 changes: 2 additions & 1 deletion packages/svelte/src/compiler/phases/2-analyze/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Scope } from '../scope.js';
import type { ComponentAnalysis, ReactiveStatement } from '../types.js';
import type { AST, ExpressionMetadata, StateField, ValidatedCompileOptions } from '#compiler';
import type { AST, StateField, ValidatedCompileOptions } from '#compiler';
import type { ExpressionMetadata } from '../nodes.js';

export interface AnalysisState {
scope: Scope;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { get_parent } from '../../../utils/ast.js';
import { is_pure, is_safe_identifier } from './shared/utils.js';
import { dev, locate_node, source } from '../../../state.js';
import * as b from '#compiler/builders';
import { create_expression_metadata } from '../../nodes.js';
import { ExpressionMetadata } from '../../nodes.js';

/**
* @param {CallExpression} node
Expand Down Expand Up @@ -243,7 +243,7 @@ export function CallExpression(node, context) {

// `$inspect(foo)` or `$derived(foo) should not trigger the `static-state-reference` warning
if (rune === '$derived') {
const expression = create_expression_metadata();
const expression = new ExpressionMetadata();

context.next({
...context.state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as e from '../../../errors.js';
import { validate_opening_tag } from './shared/utils.js';
import { mark_subtree_dynamic } from './shared/fragment.js';
import { is_resolved_snippet } from './shared/snippets.js';
import { create_expression_metadata } from '../../nodes.js';
import { ExpressionMetadata } from '../../nodes.js';

/**
* @param {AST.RenderTag} node
Expand Down Expand Up @@ -57,7 +57,7 @@ export function RenderTag(node, context) {
context.visit(callee, { ...context.state, expression: node.metadata.expression });

for (const arg of expression.arguments) {
const metadata = create_expression_metadata();
const metadata = new ExpressionMetadata();
node.metadata.arguments.push(metadata);

context.visit(arg, {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** @import { Expression, Identifier, ObjectExpression } from 'estree' */
/** @import { AST, ExpressionMetadata } from '#compiler' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../../types' */
import { escape_html } from '../../../../../../escaping.js';
import { normalize_attribute } from '../../../../../../utils.js';
Expand All @@ -8,6 +8,7 @@ import { is_event_attribute } from '../../../../../utils/ast.js';
import * as b from '#compiler/builders';
import { build_class_directives_object, build_style_directives_object } from '../RegularElement.js';
import { build_expression, build_template_chunk, Memoizer } from './utils.js';
import { ExpressionMetadata } from '../../../../nodes.js';

/**
* @param {Array<AST.Attribute | AST.SpreadAttribute>} attributes
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/** @import { Expression } from 'estree' */
/** @import { AST, ExpressionMetadata } from '#compiler' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../../types' */
import { is_capture_event, is_passive_event } from '../../../../../../utils.js';
import { dev, locator } from '../../../../../state.js';
import * as b from '#compiler/builders';
import { ExpressionMetadata } from '../../../../nodes.js';

/**
* @param {AST.Attribute} node
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** @import { AssignmentExpression, Expression, Identifier, MemberExpression, SequenceExpression, Literal, Super, UpdateExpression, ExpressionStatement } from 'estree' */
/** @import { AST, ExpressionMetadata } from '#compiler' */
/** @import { AST } from '#compiler' */
/** @import { ComponentClientTransformState, ComponentContext, Context } from '../../types' */
import { walk } from 'zimmerframe';
import { object } from '../../../../../utils/ast.js';
Expand All @@ -9,6 +9,7 @@ import { regex_is_valid_identifier } from '../../../../patterns.js';
import is_reference from 'is-reference';
import { dev, is_ignored, locator, component_name } from '../../../../../state.js';
import { build_getter } from '../../utils.js';
import { ExpressionMetadata } from '../../../../nodes.js';

/**
* A utility for extracting complex expressions (such as call expressions)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
/** @import { ArrayExpression, Expression, Literal, ObjectExpression } from 'estree' */
/** @import { AST, ExpressionMetadata } from '#compiler' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext, ComponentServerTransformState } from '../../types.js' */
import { is_event_attribute, is_text_attribute } from '../../../../../utils/ast.js';
import { binding_properties } from '../../../../bindings.js';
import {
create_attribute,
create_expression_metadata,
is_custom_element_node
} from '../../../../nodes.js';
import { create_attribute, ExpressionMetadata, is_custom_element_node } from '../../../../nodes.js';
import { regex_starts_with_newline } from '../../../../patterns.js';
import * as b from '#compiler/builders';
import {
Expand Down Expand Up @@ -160,7 +156,7 @@ export function build_element_attributes(node, context, transform) {
build_attribute_value(value_attribute.value, context, transform)
),
metadata: {
expression: create_expression_metadata()
expression: new ExpressionMetadata()
}
}
])
Expand All @@ -174,7 +170,7 @@ export function build_element_attributes(node, context, transform) {
end: -1,
expression,
metadata: {
expression: create_expression_metadata()
expression: new ExpressionMetadata()
}
}
])
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** @import { AssignmentOperator, Expression, Identifier, Node, Statement, BlockStatement } from 'estree' */
/** @import { AST, ExpressionMetadata } from '#compiler' */
/** @import { Expression, Identifier, Node, Statement, BlockStatement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext, ServerTransformState } from '../../types.js' */

import { escape_html } from '../../../../../../escaping.js';
Expand All @@ -13,6 +13,7 @@ import * as b from '#compiler/builders';
import { sanitize_template_string } from '../../../../../utils/sanitize_template_string.js';
import { regex_whitespaces_strict } from '../../../../patterns.js';
import { has_await_expression } from '../../../../../utils/ast.js';
import { ExpressionMetadata } from '../../../../nodes.js';

/** Opens an if/each block, so that we can remove nodes in the case of a mismatch */
export const block_open = b.literal(BLOCK_OPEN);
Expand Down
41 changes: 27 additions & 14 deletions packages/svelte/src/compiler/phases/nodes.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** @import { Expression, PrivateIdentifier } from 'estree' */
/** @import { AST, ExpressionMetadata } from '#compiler' */
/** @import { AST, Binding } from '#compiler' */

/**
* All nodes that can appear elsewhere than the top level, have attributes and can contain children
Expand Down Expand Up @@ -64,20 +64,33 @@ export function create_attribute(name, start, end, value) {
}
};
}
export class ExpressionMetadata {
/** True if the expression references state directly, or _might_ (via member/call expressions) */
has_state = false;

/**
* @returns {ExpressionMetadata}
*/
export function create_expression_metadata() {
return {
dependencies: new Set(),
references: new Set(),
has_state: false,
has_call: false,
has_member_expression: false,
has_assignment: false,
has_await: false
};
/** True if the expression involves a call expression (often, it will need to be wrapped in a derived) */
has_call = false;

/** True if the expression contains `await` */
has_await = false;

/** True if the expression includes a member expression */
has_member_expression = false;

/** True if the expression includes an assignment or an update */
has_assignment = false;

/**
* All the bindings that are referenced eagerly (not inside functions) in this expression
* @type {Set<Binding>}
*/
dependencies = new Set();

/**
* True if the expression references state directly, or _might_ (via member/call expressions)
* @type {Set<Binding>}
*/
references = new Set();
}

/**
Expand Down
4 changes: 2 additions & 2 deletions packages/svelte/src/compiler/phases/scope.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/** @import { AST, BindingKind, DeclarationKind } from '#compiler' */
import is_reference from 'is-reference';
import { walk } from 'zimmerframe';
import { create_expression_metadata } from './nodes.js';
import { ExpressionMetadata } from './nodes.js';
import * as b from '#compiler/builders';
import * as e from '../errors.js';
import {
Expand Down Expand Up @@ -1201,7 +1201,7 @@ export function create_scopes(ast, root, allow_reactive_declarations, parent) {
if (node.fallback) visit(node.fallback, { scope });

node.metadata = {
expression: create_expression_metadata(),
expression: new ExpressionMetadata(),
keyed: false,
contains_group_binding: false,
index: scope.root.unique('$$index'),
Expand Down
17 changes: 0 additions & 17 deletions packages/svelte/src/compiler/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,23 +294,6 @@ export type DeclarationKind =
| 'using'
| 'await using';

export interface ExpressionMetadata {
/** All the bindings that are referenced eagerly (not inside functions) in this expression */
dependencies: Set<Binding>;
/** All the bindings that are referenced inside this expression, including inside functions */
references: Set<Binding>;
/** True if the expression references state directly, or _might_ (via member/call expressions) */
has_state: boolean;
/** True if the expression involves a call expression (often, it will need to be wrapped in a derived) */
has_call: boolean;
/** True if the expression contains `await` */
has_await: boolean;
/** True if the expression includes a member expression */
has_member_expression: boolean;
/** True if the expression includes an assignment or an update */
has_assignment: boolean;
}

export interface StateField {
type: StateCreationRuneName;
node: PropertyDefinition | AssignmentExpression;
Expand Down
Loading
Loading