pull/12215/head
Rich Harris 3 months ago
parent 3a2a9699e1
commit fdf3d84885

@ -594,7 +594,10 @@ function special(parser) {
type: 'RenderTag', type: 'RenderTag',
start, start,
end: parser.index, end: parser.index,
expression: expression expression: expression,
metadata: {
dynamic: false
}
}); });
} }
} }

@ -1511,6 +1511,13 @@ const common_visitors = {
return; return;
} }
} }
},
Component(node, context) {
const binding = context.state.scope.get(
node.name.includes('.') ? node.name.slice(0, node.name.indexOf('.')) : node.name
);
node.metadata.dynamic = binding !== null && binding.kind !== 'normal';
} }
}; };

@ -625,6 +625,11 @@ const validation = {
}); });
}, },
RenderTag(node, context) { RenderTag(node, context) {
const callee = unwrap_optional(node.expression).callee;
node.metadata.dynamic =
callee.type !== 'Identifier' || context.state.scope.get(callee.name)?.kind !== 'normal';
context.state.analysis.uses_render_tags = true; context.state.analysis.uses_render_tags = true;
const raw_args = unwrap_optional(node.expression).arguments; const raw_args = unwrap_optional(node.expression).arguments;
@ -634,7 +639,6 @@ const validation = {
} }
} }
const callee = unwrap_optional(node.expression).callee;
if ( if (
callee.type === 'MemberExpression' && callee.type === 'MemberExpression' &&
callee.property.type === 'Identifier' && callee.property.type === 'Identifier' &&

@ -1682,6 +1682,8 @@ export const template_visitors = {
process_children(trimmed, expression, false, { ...context, state }); process_children(trimmed, expression, false, { ...context, state });
var first = trimmed[0];
/** /**
* If the first item in an effect is a static slot or render tag, it will clone * If the first item in an effect is a static slot or render tag, it will clone
* a template but without creating a child effect. In these cases, we need to keep * a template but without creating a child effect. In these cases, we need to keep
@ -1689,32 +1691,9 @@ export const template_visitors = {
* the item in question * the item in question
* TODO come up with a better name than `unset` * TODO come up with a better name than `unset`
*/ */
var unset = false; var unset =
var first = trimmed[0]; first.type === 'SlotElement' ||
((first.type === 'Component' || first.type === 'RenderTag') && !first.metadata.dynamic);
if (first.type === 'SlotElement') {
unset = true;
}
if (first.type === 'Component') {
// if it's not a `$.component`, mark as unset
const binding = context.state.scope.get(
first.name.includes('.') ? first.name.slice(0, first.name.indexOf('.')) : first.name
);
if (binding === null || binding.kind === 'normal') {
unset = true;
}
}
if (first.type === 'RenderTag') {
const callee = unwrap_optional(first.expression).callee;
const is_reactive =
callee.type !== 'Identifier' || context.state.scope.get(callee.name)?.kind !== 'normal';
if (!is_reactive) {
unset = true;
}
}
const use_comment_template = state.template.length === 1 && state.template[0] === '<!>'; const use_comment_template = state.template.length === 1 && state.template[0] === '<!>';
@ -1872,8 +1851,6 @@ export const template_visitors = {
context.state.template.push('<!>'); context.state.template.push('<!>');
const callee = unwrap_optional(node.expression).callee; const callee = unwrap_optional(node.expression).callee;
const raw_args = unwrap_optional(node.expression).arguments; const raw_args = unwrap_optional(node.expression).arguments;
const is_reactive =
callee.type !== 'Identifier' || context.state.scope.get(callee.name)?.kind !== 'normal';
const args = raw_args.map((arg) => const args = raw_args.map((arg) =>
b.thunk(/** @type {import('estree').Expression} */ (context.visit(arg))) b.thunk(/** @type {import('estree').Expression} */ (context.visit(arg)))
@ -1884,7 +1861,7 @@ export const template_visitors = {
snippet_function = b.call('$.validate_snippet', snippet_function); snippet_function = b.call('$.validate_snippet', snippet_function);
} }
if (is_reactive) { if (node.metadata.dynamic) {
context.state.init.push( context.state.init.push(
b.stmt(b.call('$.snippet', context.state.node, b.thunk(snippet_function), ...args)) b.stmt(b.call('$.snippet', context.state.node, b.thunk(snippet_function), ...args))
); );
@ -3014,10 +2991,7 @@ export const template_visitors = {
} }
}, },
Component(node, context) { Component(node, context) {
const binding = context.state.scope.get( if (node.metadata.dynamic) {
node.name.includes('.') ? node.name.slice(0, node.name.indexOf('.')) : node.name
);
if (binding !== null && binding.kind !== 'normal') {
// Handle dynamic references to what seems like static inline components // Handle dynamic references to what seems like static inline components
const component = serialize_inline_component(node, '$$component', context); const component = serialize_inline_component(node, '$$component', context);
context.state.init.push( context.state.init.push(
@ -3036,6 +3010,7 @@ export const template_visitors = {
); );
return; return;
} }
const component = serialize_inline_component(node, node.name, context); const component = serialize_inline_component(node, node.name, context);
context.state.init.push(component); context.state.init.push(component);
}, },

@ -152,6 +152,9 @@ export interface DebugTag extends BaseNode {
export interface RenderTag extends BaseNode { export interface RenderTag extends BaseNode {
type: 'RenderTag'; type: 'RenderTag';
expression: SimpleCallExpression | (ChainExpression & { expression: SimpleCallExpression }); expression: SimpleCallExpression | (ChainExpression & { expression: SimpleCallExpression });
metadata: {
dynamic: boolean;
};
} }
type Tag = ExpressionTag | HtmlTag | ConstTag | DebugTag | RenderTag; type Tag = ExpressionTag | HtmlTag | ConstTag | DebugTag | RenderTag;
@ -271,6 +274,9 @@ interface BaseElement extends BaseNode {
export interface Component extends BaseElement { export interface Component extends BaseElement {
type: 'Component'; type: 'Component';
metadata: {
dynamic: boolean;
};
} }
interface TitleElement extends BaseElement { interface TitleElement extends BaseElement {

Loading…
Cancel
Save