Skip to content

Commit 61e3724

Browse files
Merge pull request #127 from preactjs/lazy-branch
Fix stale value when conditionally accessing stale signal
2 parents 20a5867 + aa2df65 commit 61e3724

File tree

6 files changed

+26
-17
lines changed

6 files changed

+26
-17
lines changed

.changeset/selfish-cameras-play.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@preact/signals-core": patch
3+
---
4+
5+
Fix conditionally signals (lazy branches) not being re-computed upon activation

mangle.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
"$_pending": "_p",
3131
"$_updater": "_u",
3232
"$_setCurrent": "_",
33-
"$_canActivate": "_c",
33+
"$_activate": "_a",
34+
"$_isComputing": "_c",
3435
"$_readonly": "_r",
3536
"$_requiresUpdate": "_q",
3637
"$_props": "__"

packages/core/src/index.ts

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export class Signal<T = any> {
3030
/** @internal Marks the signal as requiring an update */
3131
_requiresUpdate = false;
3232
/** @internal Determine if reads should eagerly activate value */
33-
_canActivate = false;
33+
_active = false;
3434
/** @internal Used to detect if there is a cycle in the graph */
3535
_isComputing = false;
3636

@@ -43,16 +43,14 @@ export class Signal<T = any> {
4343
}
4444

4545
peek() {
46-
const shouldActivate = !currentSignal || currentSignal._canActivate;
47-
if (shouldActivate && this._deps.size === 0) {
46+
if (!this._active) {
4847
activate(this);
4948
}
5049
return this._value;
5150
}
5251

5352
get value() {
54-
const shouldActivate = !currentSignal || currentSignal._canActivate;
55-
if (shouldActivate && this._deps.size === 0) {
53+
if (!this._active) {
5654
activate(this);
5755
}
5856

@@ -69,15 +67,6 @@ export class Signal<T = any> {
6967
currentSignal._deps.add(this);
7068
oldDeps.delete(this);
7169

72-
// refresh stale value when this signal is read from withing
73-
// batching and when it has been marked already
74-
if (
75-
(batchPending > 0 && this._pending > 0) ||
76-
// Set up subscriptions during activation phase
77-
(activating && this._deps.size === 0)
78-
) {
79-
refreshStale(this);
80-
}
8170
return this._value;
8271
}
8372

@@ -192,6 +181,7 @@ function sweep(subs: Set<Signal<any>>) {
192181
}
193182

194183
function subscribe(signal: Signal<any>, to: Signal<any>) {
184+
signal._active = true;
195185
signal._deps.add(to);
196186
to._subs.add(signal);
197187
}
@@ -204,6 +194,7 @@ function unsubscribe(signal: Signal<any>, from: Signal<any>) {
204194
// upwards and destroy all subscriptions until we encounter a writable
205195
// signal or a signal that others listen to as well.
206196
if (from._subs.size === 0) {
197+
from._active = false;
207198
from._deps.forEach(dep => unsubscribe(from, dep));
208199
}
209200
}
@@ -239,6 +230,7 @@ function refreshStale(signal: Signal) {
239230

240231
function activate(signal: Signal) {
241232
activating = true;
233+
signal._active = true;
242234
try {
243235
refreshStale(signal);
244236
} finally {

packages/core/test/signal.test.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,19 @@ describe("computed()", () => {
572572
expect(compute).to.have.been.called;
573573
expect(d.value).to.equal(4);
574574
});
575+
576+
it("should support lazy branches", () => {
577+
const a = signal(0);
578+
const b = computed(() => a.value);
579+
const c = computed(() => (a.value > 0 ? a.value : b.value));
580+
581+
expect(c.value).to.equal(0);
582+
a.value = 1;
583+
expect(c.value).to.equal(1);
584+
585+
a.value = 0;
586+
expect(c.value).to.equal(0);
587+
});
575588
});
576589
});
577590

packages/preact/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ function setCurrentUpdater(updater?: Updater) {
4949

5050
function createUpdater(updater: () => void) {
5151
const s = signal(undefined) as Updater;
52-
s._canActivate = true;
5352
s._updater = updater;
5453
return s;
5554
}

packages/react/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ function setCurrentUpdater(updater?: Updater) {
6565

6666
function createUpdater(updater: () => void) {
6767
const s = signal(undefined) as Updater;
68-
s._canActivate = true;
6968
s._updater = updater;
7069
return s;
7170
}

0 commit comments

Comments
 (0)