Skip to content

Commit 8500819

Browse files
committed
fix: Don't assume iterators will always break on specific iteration
1 parent cea0f93 commit 8500819

File tree

2 files changed

+34
-24
lines changed

2 files changed

+34
-24
lines changed

packages/set/src/index.ts

+18-14
Original file line numberDiff line numberDiff line change
@@ -28,35 +28,39 @@ export class ReactiveSet<T> extends Set<T> {
2828
this.#triggers.track($KEYS);
2929
return super.size;
3030
}
31+
3132
has(v: T): boolean {
3233
this.#triggers.track(v);
3334
return super.has(v);
3435
}
3536

36-
*keys(): IterableIterator<T> {
37-
for (const key of super.keys()) {
38-
this.#triggers.track(key);
39-
yield key;
40-
}
41-
this.#triggers.track($KEYS);
37+
keys(): IterableIterator<T> {
38+
return this.values();
4239
}
43-
values(): IterableIterator<T> {
44-
return this.keys();
40+
41+
*values(): IterableIterator<T> {
42+
this.#triggers.track($KEYS);
43+
44+
for (const value of super.values()) {
45+
yield value;
46+
}
4547
}
48+
4649
*entries(): IterableIterator<[T, T]> {
47-
for (const key of super.keys()) {
48-
this.#triggers.track(key);
49-
yield [key, key];
50-
}
5150
this.#triggers.track($KEYS);
51+
52+
for (const entry of super.entries()) {
53+
yield entry;
54+
}
5255
}
5356

5457
[Symbol.iterator](): IterableIterator<T> {
5558
return this.values();
5659
}
57-
forEach(callbackfn: (value: T, value2: T, set: this) => void) {
60+
61+
forEach(callbackfn: (value1: T, value2: T, set: Set<T>) => void, thisArg?: any): void {
5862
this.#triggers.track($KEYS);
59-
super.forEach(callbackfn as any);
63+
super.forEach(callbackfn, thisArg);
6064
}
6165

6266
// writes

packages/set/test/index.test.ts

+16-10
Original file line numberDiff line numberDiff line change
@@ -100,33 +100,39 @@ describe("ReactiveSet", () => {
100100
const dispose = createRoot(dispose => {
101101
createEffect(() => {
102102
const run: number[] = [];
103-
let i = 0;
104103
for (const key of fn(set)) {
105104
run.push(key);
106-
if (i === 2) break; // don't iterate over all keys
107-
i += 1;
108105
}
109106
captured.push(run);
110107
});
111108
return dispose;
112109
});
113110

114111
expect(captured).toHaveLength(1);
115-
expect(captured[0]).toEqual([1, 2, 3]);
112+
expect(captured[0]).toEqual([1, 2, 3, 4]);
116113

117114
set.delete(4);
118-
expect(captured, "deleted unseen key").toHaveLength(1);
115+
expect(captured).toHaveLength(2);
116+
expect(captured[1]).toEqual([1, 2, 3]);
119117

120118
set.delete(1);
121-
expect(captured, "deleted seen").toHaveLength(2);
122-
expect(captured[1]).toEqual([2, 3]);
119+
expect(captured).toHaveLength(3);
120+
expect(captured[2]).toEqual([2, 3]);
123121

124122
set.add(4);
125-
expect(captured, "added key in reach").toHaveLength(3);
126-
expect(captured[2]).toEqual([2, 3, 4]);
123+
expect(captured).toHaveLength(4);
124+
expect(captured[3]).toEqual([2, 3, 4]);
127125

128126
set.add(5);
129-
expect(captured, "added key out of reach").toHaveLength(3);
127+
expect(captured).toHaveLength(5);
128+
expect(captured[4]).toEqual([2, 3, 4, 5]);
129+
130+
set.add(5);
131+
expect(captured).toHaveLength(5);
132+
133+
set.clear();
134+
expect(captured).toHaveLength(6);
135+
expect(captured[5]).toEqual([]);
130136

131137
dispose();
132138
});

0 commit comments

Comments
 (0)