pull/16100/head
Rich Harris 4 months ago
parent efb3b6acc5
commit 1d188f595c

@ -63,7 +63,10 @@ function open(parser) {
end: -1,
test: read_expression(parser),
consequent: create_fragment(),
alternate: null
alternate: null,
metadata: {
expression: create_expression_metadata()
}
});
parser.allow_whitespace();
@ -244,7 +247,10 @@ function open(parser) {
error: null,
pending: null,
then: null,
catch: null
catch: null,
metadata: {
expression: create_expression_metadata()
}
});
if (parser.eat('then')) {
@ -326,7 +332,10 @@ function open(parser) {
start,
end: -1,
expression,
fragment: create_fragment()
fragment: create_fragment(),
metadata: {
expression: create_expression_metadata()
}
});
parser.stack.push(block);
@ -461,7 +470,10 @@ function next(parser) {
elseif: true,
test: expression,
consequent: create_fragment(),
alternate: null
alternate: null,
metadata: {
expression: create_expression_metadata()
}
});
parser.stack.push(child);
@ -624,7 +636,10 @@ function special(parser) {
type: 'HtmlTag',
start,
end: parser.index,
expression
expression,
metadata: {
expression: create_expression_metadata()
}
});
return;
@ -699,6 +714,9 @@ function special(parser) {
declarations: [{ type: 'VariableDeclarator', id, init, start: id.start, end: init.end }],
start: start + 2, // start at const, not at @const
end: parser.index - 1
},
metadata: {
expression: create_expression_metadata()
}
});
}
@ -725,6 +743,7 @@ function special(parser) {
end: parser.index,
expression: /** @type {AST.RenderTag['expression']} */ (expression),
metadata: {
expression: create_expression_metadata(),
dynamic: false,
arguments: [],
path: [],

@ -41,5 +41,8 @@ export function AwaitBlock(node, context) {
mark_subtree_dynamic(context.path);
context.next();
context.visit(node.expression, { ...context.state, expression: node.metadata.expression });
if (node.pending) context.visit(node.pending);
if (node.then) context.visit(node.then);
if (node.catch) context.visit(node.catch);
}

@ -32,5 +32,8 @@ export function ConstTag(node, context) {
e.const_tag_invalid_placement(node);
}
context.next();
const declaration = node.declaration.declarations[0];
context.visit(declaration.id);
context.visit(declaration.init, { ...context.state, expression: node.metadata.expression });
}

@ -15,5 +15,5 @@ export function HtmlTag(node, context) {
// unfortunately this is necessary in order to fix invalid HTML
mark_subtree_dynamic(context.path);
context.next();
context.next({ ...context.state, expression: node.metadata.expression });
}

@ -17,5 +17,11 @@ export function IfBlock(node, context) {
mark_subtree_dynamic(context.path);
context.next();
context.visit(node.test, {
...context.state,
expression: node.metadata.expression
});
context.visit(node.consequent);
if (node.alternate) context.visit(node.alternate);
}

@ -16,5 +16,6 @@ export function KeyBlock(node, context) {
mark_subtree_dynamic(context.path);
context.next();
context.visit(node.expression, { ...context.state, expression: node.metadata.expression });
context.visit(node.fragment);
}

@ -54,7 +54,7 @@ export function RenderTag(node, context) {
mark_subtree_dynamic(context.path);
context.visit(callee);
context.visit(callee, { ...context.state, expression: node.metadata.expression });
for (const arg of expression.arguments) {
const metadata = create_expression_metadata();

@ -2,7 +2,7 @@
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */
import * as b from '../../../../utils/builders.js';
import { build_legacy_expression } from './shared/utils.js';
import { build_legacy_expression_2 } from './shared/utils.js';
/**
* @param {AST.AttachTag} node
@ -11,7 +11,7 @@ import { build_legacy_expression } from './shared/utils.js';
export function AttachTag(node, context) {
const expression = context.state.analysis.runes
? /** @type {Expression} */ (context.visit(node.expression))
: build_legacy_expression(node.expression, context);
: build_legacy_expression_2(context, node.expression, node.metadata.expression);
context.state.init.push(b.stmt(b.call('$.attach', context.state.node, b.thunk(expression))));
context.next();
}

@ -5,7 +5,7 @@ import { extract_identifiers } from '../../../../utils/ast.js';
import * as b from '#compiler/builders';
import { create_derived } from '../utils.js';
import { get_value } from './shared/declarations.js';
import { build_legacy_expression } from './shared/utils.js';
import { build_legacy_expression_2 } from './shared/utils.js';
/**
* @param {AST.AwaitBlock} node
@ -18,7 +18,7 @@ export function AwaitBlock(node, context) {
const expression = b.thunk(
context.state.analysis.runes
? /** @type {Expression} */ (context.visit(node.expression))
: build_legacy_expression(node.expression, context)
: build_legacy_expression_2(context, node.expression, node.metadata.expression)
);
let then_block;

@ -14,7 +14,7 @@ import { extract_paths, object } from '../../../../utils/ast.js';
import * as b from '#compiler/builders';
import { build_getter } from '../utils.js';
import { get_value } from './shared/declarations.js';
import { build_legacy_expression } from './shared/utils.js';
import { build_legacy_expression_2 } from './shared/utils.js';
/**
* @param {AST.EachBlock} node
@ -31,10 +31,14 @@ export function EachBlock(node, context) {
};
const collection = context.state.analysis.runes
? /** @type {Expression} */ (context.visit(node.expression, parent_scope_state))
: build_legacy_expression(node.expression, {
: build_legacy_expression_2(
{
...context,
state: parent_scope_state
});
},
node.expression,
node.metadata.expression
);
if (!each_node_meta.is_controlled) {
context.state.template.push_comment();

@ -3,7 +3,7 @@
/** @import { ComponentContext } from '../types' */
import { is_ignored } from '../../../../state.js';
import * as b from '#compiler/builders';
import { build_legacy_expression } from './shared/utils.js';
import { build_legacy_expression_2 } from './shared/utils.js';
/**
* @param {AST.HtmlTag} node
@ -14,7 +14,7 @@ export function HtmlTag(node, context) {
const expression = context.state.analysis.runes
? /** @type {Expression} */ (context.visit(node.expression))
: build_legacy_expression(node.expression, context);
: build_legacy_expression_2(context, node.expression, node.metadata.expression);
const is_svg = context.state.metadata.namespace === 'svg';
const is_mathml = context.state.metadata.namespace === 'mathml';

@ -2,7 +2,7 @@
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */
import * as b from '#compiler/builders';
import { build_legacy_expression } from './shared/utils.js';
import { build_legacy_expression_2 } from './shared/utils.js';
/**
* @param {AST.IfBlock} node
@ -34,7 +34,7 @@ export function IfBlock(node, context) {
const test = context.state.analysis.runes
? /** @type {Expression} */ (context.visit(node.test))
: build_legacy_expression(node.test, context);
: build_legacy_expression_2(context, node.test, node.metadata.expression);
/** @type {Expression[]} */
const args = [

@ -2,7 +2,7 @@
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */
import * as b from '#compiler/builders';
import { build_legacy_expression } from './shared/utils.js';
import { build_legacy_expression_2 } from './shared/utils.js';
/**
* @param {AST.KeyBlock} node
@ -13,7 +13,7 @@ export function KeyBlock(node, context) {
const key = context.state.analysis.runes
? /** @type {Expression} */ (context.visit(node.expression))
: build_legacy_expression(node.expression, context);
: build_legacy_expression_2(context, node.expression, node.metadata.expression);
const body = /** @type {Expression} */ (context.visit(node.fragment));
context.state.init.push(

@ -3,7 +3,7 @@
/** @import { ComponentContext } from '../types' */
import { unwrap_optional } from '../../../../utils/ast.js';
import * as b from '#compiler/builders';
import { build_legacy_expression } from './shared/utils.js';
import { build_legacy_expression_2 } from './shared/utils.js';
/**
* @param {AST.RenderTag} node
@ -34,7 +34,11 @@ export function RenderTag(node, context) {
let snippet_function = context.state.analysis.runes
? /** @type {Expression} */ (context.visit(callee))
: build_legacy_expression(/** @type {Expression} */ (callee), context);
: build_legacy_expression_2(
context,
/** @type {Expression} */ (callee),
node.metadata.expression
);
if (node.metadata.dynamic) {
// If we have a chain expression then ensure a nullish snippet function gets turned into an empty one

@ -435,6 +435,37 @@ function is_pure_expression(expression) {
}
}
/**
*
* @param {ComponentContext} context
* @param {Expression} expression
* @param {ExpressionMetadata} metadata
*/
export function build_legacy_expression_2(context, expression, metadata) {
const sequence = b.sequence([]);
for (const binding of metadata.dependencies) {
if (binding.kind === 'normal') {
continue;
}
var getter = build_getter({ ...binding.node }, context.state);
if (binding.kind === 'rest_prop') {
getter = b.call('Object.keys', getter);
} else if (binding.kind === 'bindable_prop') {
getter = b.call('$.deep_read_state', getter);
}
sequence.expressions.push(getter);
}
const value = /** @type {Expression} */ (context.visit(expression));
sequence.expressions.push(b.call('$.untrack', b.thunk(value)));
return sequence;
}
/**
* Serializes an expression with reactivity like in Svelte 4
* @param {Expression} expression

@ -135,6 +135,10 @@ export namespace AST {
export interface HtmlTag extends BaseNode {
type: 'HtmlTag';
expression: Expression;
/** @internal */
metadata: {
expression: ExpressionMetadata;
};
}
/** An HTML comment */
@ -151,6 +155,10 @@ export namespace AST {
declaration: VariableDeclaration & {
declarations: [VariableDeclarator & { id: Pattern; init: Expression }];
};
/** @internal */
metadata: {
expression: ExpressionMetadata;
};
}
/** A `{@debug ...}` tag */
@ -165,6 +173,7 @@ export namespace AST {
expression: SimpleCallExpression | (ChainExpression & { expression: SimpleCallExpression });
/** @internal */
metadata: {
expression: ExpressionMetadata;
dynamic: boolean;
arguments: ExpressionMetadata[];
path: SvelteNode[];
@ -447,6 +456,10 @@ export namespace AST {
test: Expression;
consequent: Fragment;
alternate: Fragment | null;
/** @internal */
metadata: {
expression: ExpressionMetadata;
};
}
/** An `{#await ...}` block */
@ -461,12 +474,20 @@ export namespace AST {
pending: Fragment | null;
then: Fragment | null;
catch: Fragment | null;
/** @internal */
metadata: {
expression: ExpressionMetadata;
};
}
export interface KeyBlock extends BaseNode {
type: 'KeyBlock';
expression: Expression;
fragment: Fragment;
/** @internal */
metadata: {
expression: ExpressionMetadata;
};
}
export interface SnippetBlock extends BaseNode {

Loading…
Cancel
Save