Skip to content

Commit 42f4f70

Browse files
pkozlowski-opensourcealxhub
authored andcommitted
fix(core): remove signal equality check short-circuit (#53446)
The PR #52465 introduced short-circuit for the signal equality invocation - with the reasoning that the equality function should never return false for arguments with the same references. In practice it turned out that it is rather surprising and the subsequent PR #52532 added a warning when the short-circuit was taking priority over the equality function. Still, the presence of the short-circuit prevents people from mutating objects in place and based on #52735 this is a common and desired scenario. This change removes the short-circuit altogether and thus fixes the mentioned issue. We do recognize that removing short-circuit exposes developers to the potentially surprising logic where mutated in-place change won't be propagated throug the reactivity graph (due to the deault equality function). But we assume that this might be less surprising / more desirable as compared to the short-circuit logic. Fixes #52735 PR Close #53446
1 parent 299eae4 commit 42f4f70

File tree

2 files changed

+6
-13
lines changed

2 files changed

+6
-13
lines changed

packages/core/primitives/signals/src/signal.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,7 @@ export function signalSetFn<T>(node: SignalNode<T>, newValue: T) {
6666
throwInvalidWriteToSignalError();
6767
}
6868

69-
const value = node.value;
70-
if (Object.is(value, newValue)) {
71-
if (typeof ngDevMode !== 'undefined' && ngDevMode && !node.equal(value, newValue)) {
72-
console.warn(
73-
'Signal value equality implementations should always return `true` for' +
74-
' values that are the same according to `Object.is` but returned `false` instead.');
75-
}
76-
} else if (!node.equal(value, newValue)) {
69+
if (!node.equal(node.value, newValue)) {
7770
node.value = newValue;
7871
signalValueChanged(node);
7972
}

packages/core/test/signals/signal_spec.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ describe('signals', () => {
8888
expect(derived()).toEqual('object:3');
8989
});
9090

91-
it('should consider referentially equal values as always equal', () => {
91+
it('should invoke custom equality function even if old / new references are the same', () => {
9292
const state = {value: 0};
9393
const stateSignal = signal(state, {equal: (a, b) => false});
9494

@@ -98,13 +98,13 @@ describe('signals', () => {
9898
// derived is re-computed initially
9999
expect(derived()).toBe('0:1');
100100

101-
// setting signal with the same reference should not propagate change
101+
// setting signal with the same reference should propagate change due to the custom equality
102102
stateSignal.set(state);
103-
expect(derived()).toBe('0:1');
103+
expect(derived()).toBe('0:2');
104104

105-
// updating signal with the same reference should not propagate change
105+
// updating signal with the same reference should propagate change as well
106106
stateSignal.update(state => state);
107-
expect(derived()).toBe('0:1');
107+
expect(derived()).toBe('0:3');
108108
});
109109

110110
it('should allow converting writable signals to their readonly counterpart', () => {

0 commit comments

Comments
 (0)