File tree Expand file tree Collapse file tree 4 files changed +89
-2
lines changed
src/internal/client/proxy
tests/runtime-runes/samples/each-mutation-2 Expand file tree Collapse file tree 4 files changed +89
-2
lines changed Original file line number Diff line number Diff line change 1+ ---
2+ ' svelte ' : patch
3+ ---
4+
5+ fix: better handle array property deletion reactivity
Original file line number Diff line number Diff line change @@ -140,13 +140,28 @@ const handler = {
140140
141141 deleteProperty ( target , prop ) {
142142 const metadata = target [ STATE_SYMBOL ] ;
143-
144143 const s = metadata . s . get ( prop ) ;
144+ const is_array = metadata . a ;
145+ const boolean = delete target [ prop ] ;
146+
147+ // If we have mutated an array directly, and the deletion
148+ // was successful we will also need to update the length
149+ // before updating the field or the version. This is to
150+ // ensure any effects observing length can execute before
151+ // effects that listen to the fields – otherwise they will
152+ // operate an an index that no longer exists.
153+ if ( is_array && boolean ) {
154+ const ls = metadata . s . get ( 'length' ) ;
155+ const length = target . length - 1 ;
156+ if ( ls !== undefined && ls . v !== length ) {
157+ set ( ls , length ) ;
158+ }
159+ }
145160 if ( s !== undefined ) set ( s , UNINITIALIZED ) ;
146161
147162 if ( prop in target ) update ( metadata . v ) ;
148163
149- return delete target [ prop ] ;
164+ return boolean ;
150165 } ,
151166
152167 get ( target , prop , receiver ) {
Original file line number Diff line number Diff line change 1+ import { flushSync } from 'svelte' ;
2+ import { test } from '../../test' ;
3+
4+ export default test ( {
5+ html : `<button>push</button><button>pop</button><p>1</p><p>2</p><p>3</p>` ,
6+
7+ async test ( { assert, target } ) {
8+ const [ btn1 , btn2 ] = target . querySelectorAll ( 'button' ) ;
9+
10+ flushSync ( ( ) => {
11+ btn1 . click ( ) ;
12+ } ) ;
13+
14+ assert . htmlEqual (
15+ target . innerHTML ,
16+ `<button>push</button><button>pop</button><p>1</p><p>2</p><p>3</p><p>4</p>`
17+ ) ;
18+
19+ flushSync ( ( ) => {
20+ btn1 . click ( ) ;
21+ } ) ;
22+
23+ assert . htmlEqual (
24+ target . innerHTML ,
25+ `<button>push</button><button>pop</button><p>1</p><p>2</p><p>3</p><p>4</p><p>5</p>`
26+ ) ;
27+
28+ flushSync ( ( ) => {
29+ btn2 . click ( ) ;
30+ } ) ;
31+
32+ assert . htmlEqual (
33+ target . innerHTML ,
34+ `<button>push</button><button>pop</button><p>1</p><p>2</p><p>3</p><p>4</p>`
35+ ) ;
36+
37+ flushSync ( ( ) => {
38+ btn2 . click ( ) ;
39+ } ) ;
40+
41+ assert . htmlEqual (
42+ target . innerHTML ,
43+ `<button>push</button><button>pop</button><p>1</p><p>2</p><p>3</p>`
44+ ) ;
45+
46+ flushSync ( ( ) => {
47+ btn2 . click ( ) ;
48+ } ) ;
49+
50+ assert . htmlEqual ( target . innerHTML , `<button>push</button><button>pop</button><p>1</p><p>2</p>` ) ;
51+ }
52+ } ) ;
Original file line number Diff line number Diff line change 1+ <script >
2+ let numbers = $state ([{id: 1 }, {id: 2 }, {id: 3 }]);
3+ </script >
4+
5+ <button onclick ={() => numbers .push ({id: numbers .length + 1 })}>
6+ push
7+ </button >
8+
9+ <button onclick ={() => numbers .pop ()}>
10+ pop
11+ </button >
12+
13+ {#each numbers as number }
14+ <p >{number .id }</p >
15+ {/each }
You can’t perform that action at this time.
0 commit comments