Skip to content

Commit 70cec4e

Browse files
authored
fix: cache call expressions in render tag arguments (#12418)
* fix: cache call expressions in render tag arguments Ensure that they're called at most once per change, not once per access within the snippet fixes #12187 * leverage state * types * fix
1 parent d967780 commit 70cec4e

File tree

9 files changed

+212
-195
lines changed

9 files changed

+212
-195
lines changed

.changeset/tricky-avocados-play.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: cache call expressions in render tag arguments

packages/svelte/src/compiler/phases/1-parse/state/tag.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,8 @@ function special(parser) {
600600
end: parser.index,
601601
expression: expression,
602602
metadata: {
603-
dynamic: false
603+
dynamic: false,
604+
args_with_call_expression: new Set()
604605
}
605606
});
606607
}

packages/svelte/src/compiler/phases/2-analyze/index.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import {
88
extract_paths,
99
is_event_attribute,
1010
is_text_attribute,
11-
object
11+
object,
12+
unwrap_optional
1213
} from '../../utils/ast.js';
1314
import * as b from '../../utils/builders.js';
1415
import { MathMLElements, ReservedKeywords, Runes, SVGElements } from '../constants.js';
@@ -441,6 +442,7 @@ export function analyze_component(root, source, options) {
441442
has_props_rune: false,
442443
component_slots: new Set(),
443444
expression: null,
445+
render_tag: null,
444446
private_derived_state: [],
445447
function_depth: scope.function_depth
446448
};
@@ -512,6 +514,7 @@ export function analyze_component(root, source, options) {
512514
reactive_statements: analysis.reactive_statements,
513515
component_slots: new Set(),
514516
expression: null,
517+
render_tag: null,
515518
private_derived_state: [],
516519
function_depth: scope.function_depth
517520
};
@@ -1289,14 +1292,26 @@ const common_visitors = {
12891292
}
12901293
},
12911294
CallExpression(node, context) {
1292-
const { expression } = context.state;
1295+
const { expression, render_tag } = context.state;
12931296
if (
12941297
(expression?.type === 'ExpressionTag' || expression?.type === 'SpreadAttribute') &&
12951298
!is_known_safe_call(node, context)
12961299
) {
12971300
expression.metadata.contains_call_expression = true;
12981301
}
12991302

1303+
if (render_tag) {
1304+
// Find out which of the render tag arguments contains this call expression
1305+
const arg_idx = unwrap_optional(render_tag.expression).arguments.findIndex(
1306+
(arg) => arg === node || context.path.includes(arg)
1307+
);
1308+
1309+
// -1 if this is the call expression of the render tag itself
1310+
if (arg_idx !== -1) {
1311+
render_tag.metadata.args_with_call_expression.add(arg_idx);
1312+
}
1313+
}
1314+
13001315
const callee = node.callee;
13011316
const rune = get_rune(node, context.state.scope);
13021317

@@ -1523,6 +1538,9 @@ const common_visitors = {
15231538
);
15241539

15251540
node.metadata.dynamic = binding !== null && binding.kind !== 'normal';
1541+
},
1542+
RenderTag(node, context) {
1543+
context.next({ ...context.state, render_tag: node });
15261544
}
15271545
};
15281546

packages/svelte/src/compiler/phases/2-analyze/types.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { ComponentAnalysis, ReactiveStatement } from '../types.js';
33
import type {
44
ClassDirective,
55
ExpressionTag,
6+
RenderTag,
67
SpreadAttribute,
78
SvelteNode,
89
ValidatedCompileOptions
@@ -20,6 +21,8 @@ export interface AnalysisState {
2021
component_slots: Set<string>;
2122
/** The current {expression}, if any */
2223
expression: ExpressionTag | ClassDirective | SpreadAttribute | null;
24+
/** The current {@render ...} tag, if any */
25+
render_tag: null | RenderTag;
2326
private_derived_state: string[];
2427
function_depth: number;
2528
}

0 commit comments

Comments
 (0)