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 = {
140
140
141
141
deleteProperty ( target , prop ) {
142
142
const metadata = target [ STATE_SYMBOL ] ;
143
-
144
143
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
+ }
145
160
if ( s !== undefined ) set ( s , UNINITIALIZED ) ;
146
161
147
162
if ( prop in target ) update ( metadata . v ) ;
148
163
149
- return delete target [ prop ] ;
164
+ return boolean ;
150
165
} ,
151
166
152
167
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