From 00a59c6475bd4542fb934474d82d1e242b2ac870 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Wed, 14 Sep 2022 18:44:35 +0200 Subject: [PATCH] Fix stale invalidated signals inside batch --- .changeset/tiny-numbers-argue.md | 5 ++++ packages/core/src/index.ts | 6 ++--- packages/core/test/signal.test.tsx | 40 ++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 .changeset/tiny-numbers-argue.md diff --git a/.changeset/tiny-numbers-argue.md b/.changeset/tiny-numbers-argue.md new file mode 100644 index 000000000..63d52eeaa --- /dev/null +++ b/.changeset/tiny-numbers-argue.md @@ -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. diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 670af65b9..9d41b915c 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -35,14 +35,14 @@ export class Signal { } 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); } @@ -266,7 +266,6 @@ export function effect(callback: () => void) { export function batch(cb: () => T): T { if (batchPending !== null) { return cb(); - } else { const pending: Set = new Set(); @@ -274,7 +273,6 @@ export function batch(cb: () => T): T { try { return cb(); - } finally { // Since stale signals are refreshed upwards, we need to // add pending signals in reverse diff --git a/packages/core/test/signal.test.tsx b/packages/core/test/signal.test.tsx index 81b2ee176..e64f8aa9e 100644 --- a/packages/core/test/signal.test.tsx +++ b/packages/core/test/signal.test.tsx @@ -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]); + }); });