Skip to content

Commit

Permalink
Add missing forEach methods
Browse files Browse the repository at this point in the history
  • Loading branch information
mbeckem committed Oct 4, 2024
1 parent 2f65787 commit 8c1d4d1
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 2 deletions.
1 change: 1 addition & 0 deletions packages/reactivity-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## v0.4.3 (Unreleased)

- Introduce `subtleWatchDirty`, a function that allows one to watch for signal changes without triggering the re-evaluation of the signal.
- Add missing `forEach()` method to `ReactiveSet` and `ReactiveMap`.
- Deprecate `syncEffectOnce` (use `subtleWatchDirty` instead).

## v0.4.2
Expand Down
30 changes: 29 additions & 1 deletion packages/reactivity-core/collections/map.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { it, expect, describe } from "vitest";
import { it, expect, describe, vi } from "vitest";
import { ReactiveMap, reactiveMap } from "./map";
import { batch, computed } from "../ReactiveImpl";
import { syncEffect } from "../sync";
Expand Down Expand Up @@ -45,6 +45,34 @@ describe("basic API", () => {
expect(removed).toBe(false);
});

it("supports iteration via forEach", () => {
const map = reactiveMap<string, number>([
["foo", 1],
["bar", 2]
]);
map.set("baz", 3);

const cb = vi.fn();
map.forEach(cb);

expect(cb.mock.calls).toMatchInlineSnapshot(`
[
[
1,
"foo",
],
[
2,
"bar",
],
[
3,
"baz",
],
]
`);
});

it("supports iteration", () => {
const map = reactiveMap<string, number>([
["foo", 1],
Expand Down
15 changes: 15 additions & 0 deletions packages/reactivity-core/collections/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ export interface ReactiveMap<K, V> extends Iterable<[key: K, value: V]> {
*/
delete(key: K): boolean;

/**
* Executes the given callback for every entry of the map.
*
* See also [Map.forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/forEach).
*/
forEach(callback: (value: V, key: K) => void): void;

/**
* Returns an iterator over the `[key, value]` entries in this map.
*/
Expand Down Expand Up @@ -108,6 +115,14 @@ class ReactiveMapImpl<K, V> implements ReactiveMap<K, V> {
return this.#map.size;
}

forEach(callback: (value: V, key: K) => void): void {
this.#subscribeToStructureChange();
const entries = this.#map.entries();
for (const [key, cell] of entries) {
callback(cell.value, key);
}
}

entries(): IterableIterator<[K, V]> {
this.#subscribeToStructureChange();
return this.#iterateEntries();
Expand Down
27 changes: 26 additions & 1 deletion packages/reactivity-core/collections/set.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { it, expect, describe } from "vitest";
import { it, expect, describe, vi } from "vitest";
import { reactiveSet } from "./set";

describe("basic API", () => {
Expand Down Expand Up @@ -31,6 +31,31 @@ describe("basic API", () => {
expect(removed).toBe(false);
});

it("supports iteration via forEach", () => {
const set = reactiveSet<string>(["foo", "bar"]);
set.add("baz");

const cb = vi.fn();
set.forEach(cb);

expect(cb.mock.calls).toMatchInlineSnapshot(`
[
[
"foo",
"foo",
],
[
"bar",
"bar",
],
[
"baz",
"baz",
],
]
`);
});

it("supports iteration", () => {
const set = reactiveSet<string>(["foo", "bar"]);
set.add("baz");
Expand Down
11 changes: 11 additions & 0 deletions packages/reactivity-core/collections/set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ export interface ReactiveSet<V> extends Iterable<V> {
*/
delete(value: V): boolean;

/**
* Executes the given callback for every entry of the set.
*
* See also [Set.forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/forEach).
*/
forEach(callback: (value: V, key: V) => void): void;

/**
* Returns an iterator over the `[value, value]` entries in this set.
*
Expand Down Expand Up @@ -110,6 +117,10 @@ export class ReactiveSetImpl<V> implements ReactiveSet<V> {
return this.#impl.delete(value);
}

forEach(callback: (value: V, key: V) => void): void {
this.#impl.forEach((_value, key) => callback(key, key));
}

entries(): IterableIterator<[value: V, value: V]> {
return mapToDuplicateEntries(this.values());
}
Expand Down

0 comments on commit 8c1d4d1

Please sign in to comment.