File tree Expand file tree Collapse file tree 6 files changed +112
-10
lines changed
compiler/phases/3-transform/client/visitors
tests/runtime-runes/samples/snippet-reactive-args Expand file tree Collapse file tree 6 files changed +112
-10
lines changed Original file line number Diff line number Diff line change 1+ ---
2+ ' svelte ' : patch
3+ ---
4+
5+ fix: prevent reactive snippet from reinitializing unnecessarily
Original file line number Diff line number Diff line change @@ -1734,18 +1734,20 @@ export const template_visitors = {
17341734 if ( node . argument ) {
17351735 args . push ( b . thunk ( /** @type {import('estree').Expression } */ ( context . visit ( node . argument ) ) ) ) ;
17361736 }
1737- const snippet_function = /** @type {import('estree').Expression } */ (
1737+
1738+ let snippet_function = /** @type {import('estree').Expression } */ (
17381739 context . visit ( node . expression )
17391740 ) ;
1740- const init = b . call (
1741- context . state . options . dev ? b . call ( '$.validate_snippet' , snippet_function ) : snippet_function ,
1742- ...args
1743- ) ;
1741+ if ( context . state . options . dev ) {
1742+ snippet_function = b . call ( '$.validate_snippet' , snippet_function ) ;
1743+ }
17441744
17451745 if ( is_reactive ) {
1746- context . state . init . push ( b . stmt ( b . call ( '$.snippet_effect' , b . thunk ( init ) ) ) ) ;
1746+ context . state . init . push (
1747+ b . stmt ( b . call ( '$.snippet_effect' , b . thunk ( snippet_function ) , ...args ) )
1748+ ) ;
17471749 } else {
1748- context . state . init . push ( b . stmt ( init ) ) ;
1750+ context . state . init . push ( b . stmt ( b . call ( snippet_function , ... args ) ) ) ;
17491751 }
17501752 } ,
17511753 AnimateDirective ( node , { state, visit } ) {
Original file line number Diff line number Diff line change @@ -3170,13 +3170,18 @@ export function sanitize_slots(props) {
31703170}
31713171
31723172/**
3173- * @param {() => void } create_snippet
3173+ * @param {() => Function } get_snippet
3174+ * @param {Node } node
3175+ * @param {() => any } args
31743176 * @returns {void }
31753177 */
3176- export function snippet_effect ( create_snippet ) {
3178+ export function snippet_effect ( get_snippet , node , args ) {
31773179 const block = create_snippet_block ( ) ;
31783180 render_effect ( ( ) => {
3179- create_snippet ( ) ;
3181+ // Only rerender when the snippet function itself changes,
3182+ // not when an eagerly-read prop inside the snippet function changes
3183+ const snippet = get_snippet ( ) ;
3184+ untrack ( ( ) => snippet ( node , args ) ) ;
31803185 return ( ) => {
31813186 if ( block . d !== null ) {
31823187 remove ( block . d ) ;
Original file line number Diff line number Diff line change 1+ import { test } from '../../test' ;
2+
3+ export default test ( {
4+ html : `
5+ <p>snippet: 0</p>
6+ <button>toggle</button>
7+ <button>increase count</button>
8+ ` ,
9+ props : {
10+ get log ( ) {
11+ return [ ] ;
12+ }
13+ } ,
14+
15+ async test ( { assert, target, component } ) {
16+ const [ toggle , increment ] = target . querySelectorAll ( 'button' ) ;
17+
18+ await increment ?. click ( ) ;
19+ assert . htmlEqual (
20+ target . innerHTML ,
21+ `
22+ <p>snippet: 1</p>
23+ <button>toggle</button>
24+ <button>increase count</button>
25+ `
26+ ) ;
27+ assert . deepEqual ( component . log , [ ] ) ;
28+
29+ await toggle ?. click ( ) ;
30+ assert . htmlEqual (
31+ target . innerHTML ,
32+ `
33+ <p>component: 1</p>
34+ <button>toggle</button>
35+ <button>increase count</button>
36+ `
37+ ) ;
38+ assert . deepEqual ( component . log , [ 1 ] ) ;
39+
40+ await increment ?. click ( ) ;
41+ assert . htmlEqual (
42+ target . innerHTML ,
43+ `
44+ <p>component: 2</p>
45+ <button>toggle</button>
46+ <button>increase count</button>
47+ `
48+ ) ;
49+ assert . deepEqual ( component . log , [ 1 ] ) ;
50+
51+ await toggle ?. click ( ) ;
52+ assert . htmlEqual (
53+ target . innerHTML ,
54+ `
55+ <p>snippet: 2</p>
56+ <button>toggle</button>
57+ <button>increase count</button>
58+ `
59+ ) ;
60+ assert . deepEqual ( component . log , [ 1 ] ) ;
61+ }
62+ } ) ;
Original file line number Diff line number Diff line change 1+ <script >
2+ let { count, log } = $props ();
3+ log .push (count);
4+ </script >
5+
6+ <p >component: {count }</p >
Original file line number Diff line number Diff line change 1+ <script >
2+ import Inner from " ./inner.svelte" ;
3+
4+ let { log } = $props ();
5+
6+ let count = $state (0 );
7+ let show_foo = $state (true );
8+ let snippet = $derived (show_foo ? foo : bar);
9+ </script >
10+
11+ {#snippet foo ({count })}
12+ <p >snippet: {count }</p >
13+ {/ snippet }
14+
15+ {#snippet bar (props )}
16+ <Inner {...props }></Inner >
17+ {/ snippet }
18+
19+ {@render snippet ({ count , log })}
20+
21+ <button onclick ={() => show_foo = ! show_foo }>toggle</button >
22+ <button onclick ={() => count ++ }>increase count</button >
You can’t perform that action at this time.
0 commit comments