Skip to content

Commit d2063ca

Browse files
committed
breaking: finer lazy reactivity for set
1 parent b91a67b commit d2063ca

File tree

2 files changed

+42
-32
lines changed

2 files changed

+42
-32
lines changed

packages/svelte/src/reactivity/set.js

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { DEV } from 'esm-env';
22
import { source, set } from '../internal/client/reactivity/sources.js';
3+
import { effect } from '../internal/client/reactivity/effects.js';
34
import { get } from '../internal/client/runtime.js';
45
import { map } from './utils.js';
56

@@ -13,7 +14,7 @@ var inited = false;
1314
*/
1415
export class ReactiveSet extends Set {
1516
/** @type {Map<T, import('#client').Source<boolean>>} */
16-
#sources = new Map();
17+
#tracked = new Map();
1718
#version = source(0);
1819
#size = source(0);
1920

@@ -27,13 +28,11 @@ export class ReactiveSet extends Set {
2728
if (DEV) new Set(value);
2829

2930
if (value) {
30-
var sources = this.#sources;
31-
3231
for (var element of value) {
33-
sources.set(element, source(true));
32+
super.add(element);
3433
}
3534

36-
this.#size.v = sources.size;
35+
this.#size.v = super.size;
3736
}
3837

3938
if (!inited) this.#init();
@@ -73,65 +72,72 @@ export class ReactiveSet extends Set {
7372

7473
/** @param {T} value */
7574
has(value) {
76-
var s = this.#sources.get(value);
75+
var exists = super.has(value);
76+
var s = this.#tracked.get(value);
7777

7878
if (s === undefined) {
79-
// We should always track the version in case
80-
// the Set ever gets this value in the future.
81-
get(this.#version);
82-
83-
return false;
79+
s = source(exists);
80+
this.#tracked.set(value, s);
8481
}
8582

83+
effect(() => () => {
84+
queueMicrotask(() => {
85+
if (s && !s.reactions) {
86+
this.#tracked.delete(value);
87+
}
88+
});
89+
});
90+
8691
return get(s);
8792
}
8893

8994
/** @param {T} value */
9095
add(value) {
91-
var sources = this.#sources;
92-
93-
if (!sources.has(value)) {
94-
sources.set(value, source(true));
95-
set(this.#size, sources.size);
96+
if (!super.has(value)) {
97+
super.add(value);
98+
set(this.#size, super.size);
9699
this.#increment_version();
100+
101+
var s = this.#tracked.get(value);
102+
if (s !== undefined) {
103+
set(s, true);
104+
}
97105
}
98106

99107
return this;
100108
}
101109

102110
/** @param {T} value */
103111
delete(value) {
104-
var sources = this.#sources;
105-
var s = sources.get(value);
106-
107-
if (s !== undefined) {
108-
var removed = sources.delete(value);
109-
set(this.#size, sources.size);
110-
set(s, false);
112+
var removed = super.delete(value);
113+
if (removed) {
114+
set(this.#size, super.size);
111115
this.#increment_version();
112-
return removed;
116+
117+
var s = this.#tracked.get(value);
118+
if (s !== undefined) {
119+
set(s, false);
120+
}
113121
}
114122

115-
return false;
123+
return removed;
116124
}
117125

118126
clear() {
119-
var sources = this.#sources;
120-
121-
if (sources.size !== 0) {
127+
if (super.size !== 0) {
122128
set(this.#size, 0);
123-
for (var s of sources.values()) {
129+
for (var s of this.#tracked.values()) {
124130
set(s, false);
125131
}
126132
this.#increment_version();
127133
}
128134

129-
sources.clear();
135+
super.clear();
130136
}
131137

132138
keys() {
133139
get(this.#version);
134-
return map(this.#sources.keys(), (key) => key, 'Set Iterator');
140+
return map(super.keys(), (key) => key, 'Set Iterator');
135141
}
136142

137143
values() {

packages/svelte/src/reactivity/set.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ test('set.values()', () => {
3030
set.clear();
3131
});
3232

33-
assert.deepEqual(log, [5, true, [1, 2, 3, 4, 5], 4, false, [1, 2, 4, 5], 0, false, []]);
33+
assert.deepEqual(log, [5, true, [1, 2, 3, 4, 5], 4, false, [1, 2, 4, 5], 0, []]);
3434

3535
cleanup();
3636
});
@@ -58,6 +58,10 @@ test('set.has(...)', () => {
5858
set.delete(2);
5959
});
6060

61+
flushSync(() => {
62+
set.add(4);
63+
});
64+
6165
flushSync(() => {
6266
set.add(2);
6367
});

0 commit comments

Comments
 (0)