Skip to content

Commit

Permalink
Fix stale invalidated signals inside batch
Browse files Browse the repository at this point in the history
  • Loading branch information
marvinhagemeister committed Sep 15, 2022
1 parent dfb3a71 commit 00a59c6
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/tiny-numbers-argue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@preact/signals-core": patch
---

Fix invalidated signals inside `batch()` not being refreshed when read inside a batching operation. This fixes a regression.
6 changes: 2 additions & 4 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ export class Signal<T = any> {
}

peek() {
if (!this._active) {
if (!this._active || this._pending > 0) {
activate(this);
}
return this._value;
}

get value() {
if (!this._active) {
if (!this._active || this._pending > 0) {
activate(this);
}

Expand Down Expand Up @@ -266,15 +266,13 @@ export function effect(callback: () => void) {
export function batch<T>(cb: () => T): T {
if (batchPending !== null) {
return cb();

} else {
const pending: Set<Signal> = new Set();

batchPending = pending;

try {
return cb();

} finally {
// Since stale signals are refreshed upwards, we need to
// add pending signals in reverse
Expand Down
40 changes: 40 additions & 0 deletions packages/core/test/signal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -747,4 +747,44 @@ describe("batch/transaction", () => {
c.value = "cc";
expect(result).to.equal("aa bb cc");
});

it("should not lead to stale signals with .value in batch", () => {
const invokes: number[][] = [];
const counter = signal(0);
const double = computed(() => counter.value * 2);
const tripple = computed(() => counter.value * 3);

effect(() => {
invokes.push([double.value, tripple.value]);
});

expect(invokes).to.deep.equal([[0, 0]]);

batch(() => {
counter.value = 1;
expect(double.value).to.equal(2);
});

expect(invokes[1]).to.deep.equal([2, 3]);
});

it("should not lead to stale signals with peek() in batch", () => {
const invokes: number[][] = [];
const counter = signal(0);
const double = computed(() => counter.value * 2);
const tripple = computed(() => counter.value * 3);

effect(() => {
invokes.push([double.value, tripple.value]);
});

expect(invokes).to.deep.equal([[0, 0]]);

batch(() => {
counter.value = 1;
expect(double.peek()).to.equal(2);
});

expect(invokes[1]).to.deep.equal([2, 3]);
});
});

0 comments on commit 00a59c6

Please sign in to comment.