Skip to content

Commit b224c3f

Browse files
Rich-Harris7nikdummdidumm
authored
fix: coarse reactivity, alternative approach (#16100)
Make sure we track statically visible dependencies and untrack indirect dependencies Fixes #14351 --------- Co-authored-by: 7nik <[email protected]> Co-authored-by: Simon H <[email protected]>
1 parent d99d872 commit b224c3f

File tree

38 files changed

+392
-87
lines changed

38 files changed

+392
-87
lines changed

.changeset/popular-dancers-switch.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: use compiler-driven reactivity in legacy mode template expressions

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

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ function open(parser) {
6363
end: -1,
6464
test: read_expression(parser),
6565
consequent: create_fragment(),
66-
alternate: null
66+
alternate: null,
67+
metadata: {
68+
expression: create_expression_metadata()
69+
}
6770
});
6871

6972
parser.allow_whitespace();
@@ -244,7 +247,10 @@ function open(parser) {
244247
error: null,
245248
pending: null,
246249
then: null,
247-
catch: null
250+
catch: null,
251+
metadata: {
252+
expression: create_expression_metadata()
253+
}
248254
});
249255

250256
if (parser.eat('then')) {
@@ -326,7 +332,10 @@ function open(parser) {
326332
start,
327333
end: -1,
328334
expression,
329-
fragment: create_fragment()
335+
fragment: create_fragment(),
336+
metadata: {
337+
expression: create_expression_metadata()
338+
}
330339
});
331340

332341
parser.stack.push(block);
@@ -461,7 +470,10 @@ function next(parser) {
461470
elseif: true,
462471
test: expression,
463472
consequent: create_fragment(),
464-
alternate: null
473+
alternate: null,
474+
metadata: {
475+
expression: create_expression_metadata()
476+
}
465477
});
466478

467479
parser.stack.push(child);
@@ -624,7 +636,10 @@ function special(parser) {
624636
type: 'HtmlTag',
625637
start,
626638
end: parser.index,
627-
expression
639+
expression,
640+
metadata: {
641+
expression: create_expression_metadata()
642+
}
628643
});
629644

630645
return;
@@ -699,6 +714,9 @@ function special(parser) {
699714
declarations: [{ type: 'VariableDeclarator', id, init, start: id.start, end: init.end }],
700715
start: start + 2, // start at const, not at @const
701716
end: parser.index - 1
717+
},
718+
metadata: {
719+
expression: create_expression_metadata()
702720
}
703721
});
704722
}
@@ -725,6 +743,7 @@ function special(parser) {
725743
end: parser.index,
726744
expression: /** @type {AST.RenderTag['expression']} */ (expression),
727745
metadata: {
746+
expression: create_expression_metadata(),
728747
dynamic: false,
729748
arguments: [],
730749
path: [],

packages/svelte/src/compiler/phases/2-analyze/visitors/AssignmentExpression.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,9 @@ export function AssignmentExpression(node, context) {
2323
}
2424
}
2525

26+
if (context.state.expression) {
27+
context.state.expression.has_assignment = true;
28+
}
29+
2630
context.next();
2731
}

packages/svelte/src/compiler/phases/2-analyze/visitors/AwaitBlock.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,8 @@ export function AwaitBlock(node, context) {
4141

4242
mark_subtree_dynamic(context.path);
4343

44-
context.next();
44+
context.visit(node.expression, { ...context.state, expression: node.metadata.expression });
45+
if (node.pending) context.visit(node.pending);
46+
if (node.then) context.visit(node.then);
47+
if (node.catch) context.visit(node.catch);
4548
}

packages/svelte/src/compiler/phases/2-analyze/visitors/ConstTag.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,8 @@ export function ConstTag(node, context) {
3232
e.const_tag_invalid_placement(node);
3333
}
3434

35-
context.next();
35+
const declaration = node.declaration.declarations[0];
36+
37+
context.visit(declaration.id);
38+
context.visit(declaration.init, { ...context.state, expression: node.metadata.expression });
3639
}

packages/svelte/src/compiler/phases/2-analyze/visitors/HtmlTag.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ export function HtmlTag(node, context) {
1515
// unfortunately this is necessary in order to fix invalid HTML
1616
mark_subtree_dynamic(context.path);
1717

18-
context.next();
18+
context.next({ ...context.state, expression: node.metadata.expression });
1919
}

packages/svelte/src/compiler/phases/2-analyze/visitors/Identifier.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ export function Identifier(node, context) {
9090
if (binding) {
9191
if (context.state.expression) {
9292
context.state.expression.dependencies.add(binding);
93+
context.state.expression.references.add(binding);
9394
context.state.expression.has_state ||=
9495
binding.kind !== 'static' &&
9596
!binding.is_function() &&

packages/svelte/src/compiler/phases/2-analyze/visitors/IfBlock.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,11 @@ export function IfBlock(node, context) {
1717

1818
mark_subtree_dynamic(context.path);
1919

20-
context.next();
20+
context.visit(node.test, {
21+
...context.state,
22+
expression: node.metadata.expression
23+
});
24+
25+
context.visit(node.consequent);
26+
if (node.alternate) context.visit(node.alternate);
2127
}

packages/svelte/src/compiler/phases/2-analyze/visitors/KeyBlock.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@ export function KeyBlock(node, context) {
1616

1717
mark_subtree_dynamic(context.path);
1818

19-
context.next();
19+
context.visit(node.expression, { ...context.state, expression: node.metadata.expression });
20+
context.visit(node.fragment);
2021
}

packages/svelte/src/compiler/phases/2-analyze/visitors/MemberExpression.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ export function MemberExpression(node, context) {
1515
}
1616
}
1717

18-
if (context.state.expression && !is_pure(node, context)) {
19-
context.state.expression.has_state = true;
18+
if (context.state.expression) {
19+
context.state.expression.has_member_expression = true;
20+
context.state.expression.has_state ||= !is_pure(node, context);
2021
}
2122

2223
if (!is_safe_identifier(node, context.state.scope)) {

0 commit comments

Comments
 (0)