diff --git a/src/lwc/signals/__tests__/computed.test.ts b/src/lwc/signals/__tests__/computed.test.ts index 4666178..8f6ec2c 100644 --- a/src/lwc/signals/__tests__/computed.test.ts +++ b/src/lwc/signals/__tests__/computed.test.ts @@ -1,4 +1,4 @@ -import { $computed, $signal } from "../core"; +import { $computed, $effect, $signal } from "../core"; describe("computed values", () => { test("can be created from a source signal", () => { @@ -46,4 +46,15 @@ describe("computed values", () => { expect(computed.value).toBe(2); expect(anotherComputed.value).toBe(4); }); + + test("computed objects that return the same value as a tracked signal recomputes", () => { + const signal = $signal({ a: 0, b: 0 }, { track: true }); + const computed = $computed(() => signal.value); + const spy = jest.fn(() => computed.value); + $effect(spy); + spy.mockReset(); + + signal.value.a = 1; + expect(spy).toHaveBeenCalled(); + }); }); diff --git a/src/lwc/signals/core.ts b/src/lwc/signals/core.ts index 73988dd..56f2f6a 100644 --- a/src/lwc/signals/core.ts +++ b/src/lwc/signals/core.ts @@ -53,7 +53,7 @@ function $effect(fn: VoidFunction): void { const effectNode: EffectNode = { error: null, state: UNSET - } + }; const execute = () => { if (effectNode.state === COMPUTING) { @@ -107,7 +107,7 @@ function computedGetter(node: ComputedNode) { */ function $computed(fn: ComputedFunction): ReadOnlySignal { const computedNode: ComputedNode = { - signal: $signal(undefined), + signal: $signal(undefined, { track: true }), error: null, state: UNSET }; @@ -143,6 +143,8 @@ interface TrackableState { get(): T; set(value: T): void; + + forceUpdate(): boolean; } class UntrackedState implements TrackableState { @@ -159,6 +161,10 @@ class UntrackedState implements TrackableState { set(value: T) { this._value = value; } + + forceUpdate() { + return false; + } } class TrackedState implements TrackableState { @@ -181,6 +187,10 @@ class TrackedState implements TrackableState { set(value: T) { this._value = this._membrane.getProxy(value); } + + forceUpdate(): boolean { + return true; + } } /** @@ -232,7 +242,10 @@ function $signal( } function setter(newValue: T) { - if (isEqual(newValue, _storageOption.get())) { + if ( + !trackableState.forceUpdate() && + isEqual(newValue, _storageOption.get()) + ) { return; } trackableState.set(newValue);