From fdf3d8488591922ee2407d6b9b5cda83dc0a9326 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 27 Jun 2024 17:39:46 -0400 Subject: [PATCH] simplify --- .../src/compiler/phases/1-parse/state/tag.js | 5 ++- .../src/compiler/phases/2-analyze/index.js | 7 ++++ .../compiler/phases/2-analyze/validation.js | 6 ++- .../3-transform/client/visitors/template.js | 41 ++++--------------- .../svelte/src/compiler/types/template.d.ts | 6 +++ 5 files changed, 30 insertions(+), 35 deletions(-) diff --git a/packages/svelte/src/compiler/phases/1-parse/state/tag.js b/packages/svelte/src/compiler/phases/1-parse/state/tag.js index 0dc7b9709e..baa86783b0 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/tag.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/tag.js @@ -594,7 +594,10 @@ function special(parser) { type: 'RenderTag', start, end: parser.index, - expression: expression + expression: expression, + metadata: { + dynamic: false + } }); } } diff --git a/packages/svelte/src/compiler/phases/2-analyze/index.js b/packages/svelte/src/compiler/phases/2-analyze/index.js index 2e46d18c6f..6986408f04 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/index.js +++ b/packages/svelte/src/compiler/phases/2-analyze/index.js @@ -1511,6 +1511,13 @@ const common_visitors = { 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'; } }; diff --git a/packages/svelte/src/compiler/phases/2-analyze/validation.js b/packages/svelte/src/compiler/phases/2-analyze/validation.js index f4778e4322..d0258a52dc 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/validation.js +++ b/packages/svelte/src/compiler/phases/2-analyze/validation.js @@ -625,6 +625,11 @@ const validation = { }); }, 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; const raw_args = unwrap_optional(node.expression).arguments; @@ -634,7 +639,6 @@ const validation = { } } - const callee = unwrap_optional(node.expression).callee; if ( callee.type === 'MemberExpression' && callee.property.type === 'Identifier' && diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js index 682c7add46..a4087fb9b3 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js @@ -1682,6 +1682,8 @@ export const template_visitors = { 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 * 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 * TODO come up with a better name than `unset` */ - var unset = false; - var first = trimmed[0]; - - 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; - } - } + var unset = + first.type === 'SlotElement' || + ((first.type === 'Component' || first.type === 'RenderTag') && !first.metadata.dynamic); const use_comment_template = state.template.length === 1 && state.template[0] === ''; @@ -1872,8 +1851,6 @@ export const template_visitors = { context.state.template.push(''); const callee = unwrap_optional(node.expression).callee; 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) => 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); } - if (is_reactive) { + if (node.metadata.dynamic) { context.state.init.push( b.stmt(b.call('$.snippet', context.state.node, b.thunk(snippet_function), ...args)) ); @@ -3014,10 +2991,7 @@ export const template_visitors = { } }, Component(node, context) { - const binding = context.state.scope.get( - node.name.includes('.') ? node.name.slice(0, node.name.indexOf('.')) : node.name - ); - if (binding !== null && binding.kind !== 'normal') { + if (node.metadata.dynamic) { // Handle dynamic references to what seems like static inline components const component = serialize_inline_component(node, '$$component', context); context.state.init.push( @@ -3036,6 +3010,7 @@ export const template_visitors = { ); return; } + const component = serialize_inline_component(node, node.name, context); context.state.init.push(component); }, diff --git a/packages/svelte/src/compiler/types/template.d.ts b/packages/svelte/src/compiler/types/template.d.ts index 05ac91bda2..25947dcf2b 100644 --- a/packages/svelte/src/compiler/types/template.d.ts +++ b/packages/svelte/src/compiler/types/template.d.ts @@ -152,6 +152,9 @@ export interface DebugTag extends BaseNode { export interface RenderTag extends BaseNode { type: 'RenderTag'; expression: SimpleCallExpression | (ChainExpression & { expression: SimpleCallExpression }); + metadata: { + dynamic: boolean; + }; } type Tag = ExpressionTag | HtmlTag | ConstTag | DebugTag | RenderTag; @@ -271,6 +274,9 @@ interface BaseElement extends BaseNode { export interface Component extends BaseElement { type: 'Component'; + metadata: { + dynamic: boolean; + }; } interface TitleElement extends BaseElement {