Skip to content

Commit b1cbfc3

Browse files
authored
fix: populate this.#sources when constructing reactive map (#11915)
* fix: populate `this.#sources` when constructing reactive map * populate sources in first #read_all * use increment helper * use numbers instead of symbols * make forEach work
1 parent 862949d commit b1cbfc3

File tree

5 files changed

+41
-37
lines changed

5 files changed

+41
-37
lines changed

.changeset/cold-beans-tease.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
'svelte': patch
33
---
44

5-
fix: increment version when creating new source in Map.get or Map.has
5+
fix: populate `this.#sources` when constructing reactive map

packages/svelte/src/reactivity/map.js

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import { DEV } from 'esm-env';
22
import { source, set } from '../internal/client/reactivity/sources.js';
33
import { get } from '../internal/client/runtime.js';
4-
import { UNINITIALIZED } from '../constants.js';
4+
import { increment } from './utils.js';
55

66
/**
77
* @template K
88
* @template V
99
* @extends {Map<K, V>}
1010
*/
1111
export class ReactiveMap extends Map {
12-
/** @type {Map<K, import('#client').Source<symbol>>} */
12+
/** @type {Map<K, import('#client').Source<number>>} */
1313
#sources = new Map();
1414
#version = source(0);
1515
#size = source(0);
@@ -31,10 +31,6 @@ export class ReactiveMap extends Map {
3131
}
3232
}
3333

34-
#increment_version() {
35-
set(this.#version, this.#version.v + 1);
36-
}
37-
3834
/** @param {K} key */
3935
has(key) {
4036
var sources = this.#sources;
@@ -43,9 +39,8 @@ export class ReactiveMap extends Map {
4339
if (s === undefined) {
4440
var ret = super.get(key);
4541
if (ret !== undefined) {
46-
s = source(Symbol());
42+
s = source(0);
4743
sources.set(key, s);
48-
this.#increment_version();
4944
} else {
5045
// We should always track the version in case
5146
// the Set ever gets this value in the future.
@@ -63,9 +58,8 @@ export class ReactiveMap extends Map {
6358
* @param {any} [this_arg]
6459
*/
6560
forEach(callbackfn, this_arg) {
66-
get(this.#version);
67-
68-
return super.forEach(callbackfn, this_arg);
61+
this.#read_all();
62+
super.forEach(callbackfn, this_arg);
6963
}
7064

7165
/** @param {K} key */
@@ -76,9 +70,8 @@ export class ReactiveMap extends Map {
7670
if (s === undefined) {
7771
var ret = super.get(key);
7872
if (ret !== undefined) {
79-
s = source(Symbol());
73+
s = source(0);
8074
sources.set(key, s);
81-
this.#increment_version();
8275
} else {
8376
// We should always track the version in case
8477
// the Set ever gets this value in the future.
@@ -102,11 +95,11 @@ export class ReactiveMap extends Map {
10295
var res = super.set(key, value);
10396

10497
if (s === undefined) {
105-
sources.set(key, source(Symbol()));
98+
sources.set(key, source(0));
10699
set(this.#size, super.size);
107-
this.#increment_version();
100+
increment(this.#version);
108101
} else if (prev_res !== value) {
109-
set(s, Symbol());
102+
increment(s);
110103
}
111104

112105
return res;
@@ -121,8 +114,8 @@ export class ReactiveMap extends Map {
121114
if (s !== undefined) {
122115
sources.delete(key);
123116
set(this.#size, super.size);
124-
set(s, UNINITIALIZED);
125-
this.#increment_version();
117+
set(s, -1);
118+
increment(this.#version);
126119
}
127120

128121
return res;
@@ -134,16 +127,26 @@ export class ReactiveMap extends Map {
134127
if (super.size !== 0) {
135128
set(this.#size, 0);
136129
for (var s of sources.values()) {
137-
set(s, UNINITIALIZED);
130+
set(s, -1);
138131
}
139-
this.#increment_version();
132+
increment(this.#version);
140133
sources.clear();
141134
}
142135
super.clear();
143136
}
144137

145138
#read_all() {
146139
get(this.#version);
140+
141+
var sources = this.#sources;
142+
if (this.#size.v !== sources.size) {
143+
for (var key of super.keys()) {
144+
if (!sources.has(key)) {
145+
sources.set(key, source(0));
146+
}
147+
}
148+
}
149+
147150
for (var [, s] of this.#sources) {
148151
get(s);
149152
}

packages/svelte/src/reactivity/set.js

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { DEV } from 'esm-env';
22
import { source, set } from '../internal/client/reactivity/sources.js';
33
import { get } from '../internal/client/runtime.js';
4+
import { increment } from './utils.js';
45

56
var read_methods = ['forEach', 'isDisjointFrom', 'isSubsetOf', 'isSupersetOf'];
67
var set_like_methods = ['difference', 'intersection', 'symmetricDifference', 'union'];
@@ -63,10 +64,6 @@ export class ReactiveSet extends Set {
6364
}
6465
}
6566

66-
#increment_version() {
67-
set(this.#version, this.#version.v + 1);
68-
}
69-
7067
/** @param {T} value */
7168
has(value) {
7269
var sources = this.#sources;
@@ -98,7 +95,7 @@ export class ReactiveSet extends Set {
9895
if (s === undefined) {
9996
sources.set(value, source(true));
10097
set(this.#size, super.size);
101-
this.#increment_version();
98+
increment(this.#version);
10299
} else {
103100
set(s, true);
104101
}
@@ -116,7 +113,7 @@ export class ReactiveSet extends Set {
116113
sources.delete(value);
117114
set(this.#size, super.size);
118115
set(s, false);
119-
this.#increment_version();
116+
increment(this.#version);
120117
}
121118

122119
return res;
@@ -130,7 +127,7 @@ export class ReactiveSet extends Set {
130127
for (var s of sources.values()) {
131128
set(s, false);
132129
}
133-
this.#increment_version();
130+
increment(this.#version);
134131
sources.clear();
135132
}
136133
super.clear();

packages/svelte/src/reactivity/url.js

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { source, set } from '../internal/client/reactivity/sources.js';
22
import { get } from '../internal/client/runtime.js';
3+
import { increment } from './utils.js';
34

45
const REPLACE = Symbol();
56

@@ -155,10 +156,6 @@ export class ReactiveURL extends URL {
155156
export class ReactiveURLSearchParams extends URLSearchParams {
156157
#version = source(0);
157158

158-
#increment_version() {
159-
set(this.#version, this.#version.v + 1);
160-
}
161-
162159
/**
163160
* @param {URLSearchParams} params
164161
*/
@@ -171,7 +168,7 @@ export class ReactiveURLSearchParams extends URLSearchParams {
171168
super.append(key, value);
172169
}
173170

174-
this.#increment_version();
171+
increment(this.#version);
175172
}
176173

177174
/**
@@ -180,7 +177,7 @@ export class ReactiveURLSearchParams extends URLSearchParams {
180177
* @returns {void}
181178
*/
182179
append(name, value) {
183-
this.#increment_version();
180+
increment(this.#version);
184181
return super.append(name, value);
185182
}
186183

@@ -190,7 +187,7 @@ export class ReactiveURLSearchParams extends URLSearchParams {
190187
* @returns {void}
191188
*/
192189
delete(name, value) {
193-
this.#increment_version();
190+
increment(this.#version);
194191
return super.delete(name, value);
195192
}
196193

@@ -233,12 +230,12 @@ export class ReactiveURLSearchParams extends URLSearchParams {
233230
* @returns {void}
234231
*/
235232
set(name, value) {
236-
this.#increment_version();
233+
increment(this.#version);
237234
return super.set(name, value);
238235
}
239236

240237
sort() {
241-
this.#increment_version();
238+
increment(this.#version);
242239
return super.sort();
243240
}
244241

packages/svelte/src/reactivity/utils.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { set } from '../internal/client/reactivity/sources.js';
2+
13
/**
24
* @template T
35
* @template U
@@ -27,3 +29,8 @@ export function map(iterable, fn, name) {
2729
function get_this() {
2830
return this;
2931
}
32+
33+
/** @param {import('#client').Source<number>} source */
34+
export function increment(source) {
35+
set(source, source.v + 1);
36+
}

0 commit comments

Comments
 (0)