diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/Identifier.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/Identifier.js index abf70769c0..cced326f9b 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/Identifier.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/Identifier.js @@ -90,6 +90,7 @@ export function Identifier(node, context) { if (binding) { if (context.state.expression) { context.state.expression.dependencies.add(binding); + context.state.expression.references.add(binding); context.state.expression.has_state ||= binding.kind !== 'static' && !binding.is_function() && diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/function.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/function.js index c892efd421..1f399f2b43 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/function.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/function.js @@ -13,6 +13,16 @@ export function visit_function(node, context) { scope: context.state.scope }; + if (context.state.expression) { + for (const [name] of context.state.scope.references) { + const binding = context.state.scope.get(name); + + if (binding) { + context.state.expression.references.add(binding); + } + } + } + context.next({ ...context.state, function_depth: context.state.function_depth + 1, diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/ConstTag.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/ConstTag.js index c61df71222..0a97a98156 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/ConstTag.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/ConstTag.js @@ -6,7 +6,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, build_legacy_expression_2 } from './shared/utils.js'; /** * @param {AST.ConstTag} node @@ -18,7 +18,7 @@ export function ConstTag(node, context) { if (declaration.id.type === 'Identifier') { const init = context.state.analysis.runes ? /** @type {Expression} */ (context.visit(declaration.init)) - : build_legacy_expression(declaration.init, context); + : build_legacy_expression_2(context, declaration.init, node.metadata.expression); context.state.init.push(b.const(declaration.id, create_derived(context.state, b.thunk(init)))); context.state.transform[declaration.id.name] = { read: get_value }; @@ -46,7 +46,11 @@ export function ConstTag(node, context) { // instead of destructuring it only to return a new object const init = context.state.analysis.runes ? /** @type {Expression} */ (context.visit(declaration.init, child_state)) - : build_legacy_expression(declaration.init, { ...context, state: child_state }); + : build_legacy_expression_2( + { ...context, state: child_state }, + declaration.init, + node.metadata.expression + ); const fn = b.arrow( [], b.block([ diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js index ad5f734ff0..4b591c48e6 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js @@ -450,7 +450,7 @@ export function build_legacy_expression_2(context, expression, metadata) { const sequence = b.sequence([]); - for (const binding of metadata.dependencies) { + for (const binding of metadata.references) { if (binding.kind === 'normal') { continue; } diff --git a/packages/svelte/src/compiler/phases/nodes.js b/packages/svelte/src/compiler/phases/nodes.js index 954f232424..c35f194b75 100644 --- a/packages/svelte/src/compiler/phases/nodes.js +++ b/packages/svelte/src/compiler/phases/nodes.js @@ -62,6 +62,7 @@ export function create_attribute(name, start, end, value) { export function create_expression_metadata() { return { dependencies: new Set(), + references: new Set(), has_state: false, has_call: false, has_member_expression: false, diff --git a/packages/svelte/src/compiler/types/index.d.ts b/packages/svelte/src/compiler/types/index.d.ts index 5bcc99e147..558ee558f7 100644 --- a/packages/svelte/src/compiler/types/index.d.ts +++ b/packages/svelte/src/compiler/types/index.d.ts @@ -279,8 +279,10 @@ export type DeclarationKind = | 'synthetic'; export interface ExpressionMetadata { - /** All the bindings that are referenced inside this expression */ + /** All the bindings that are referenced eagerly (not inside functions) in this expression */ dependencies: Set; + /** All the bindings that are referenced inside this expression, including inside functions */ + references: Set; /** 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) */