Skip to content

Commit 5d75b1d

Browse files
atscottpkozlowski-opensource
authored andcommitted
fix(core): toSignal equal option should be passed to inner computed (angular#56903)
The user-defined equality function needs to be passed to the inner computed it will still use `Object.is` and prevent notifications. PR Close angular#56903
1 parent 5179ce3 commit 5d75b1d

File tree

2 files changed

+43
-16
lines changed

2 files changed

+43
-16
lines changed

packages/core/rxjs-interop/src/to_signal.ts

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -195,22 +195,25 @@ export function toSignal<T, U = undefined>(
195195

196196
// The actual returned signal is a `computed` of the `State` signal, which maps the various states
197197
// to either values or errors.
198-
return computed(() => {
199-
const current = state();
200-
switch (current.kind) {
201-
case StateKind.Value:
202-
return current.value;
203-
case StateKind.Error:
204-
throw current.error;
205-
case StateKind.NoValue:
206-
// This shouldn't really happen because the error is thrown on creation.
207-
// TODO(alxhub): use a RuntimeError when we finalize the error semantics
208-
throw new ɵRuntimeError(
209-
ɵRuntimeErrorCode.REQUIRE_SYNC_WITHOUT_SYNC_EMIT,
210-
'`toSignal()` called with `requireSync` but `Observable` did not emit synchronously.',
211-
);
212-
}
213-
});
198+
return computed(
199+
() => {
200+
const current = state();
201+
switch (current.kind) {
202+
case StateKind.Value:
203+
return current.value;
204+
case StateKind.Error:
205+
throw current.error;
206+
case StateKind.NoValue:
207+
// This shouldn't really happen because the error is thrown on creation.
208+
// TODO(alxhub): use a RuntimeError when we finalize the error semantics
209+
throw new ɵRuntimeError(
210+
ɵRuntimeErrorCode.REQUIRE_SYNC_WITHOUT_SYNC_EMIT,
211+
'`toSignal()` called with `requireSync` but `Observable` did not emit synchronously.',
212+
);
213+
}
214+
},
215+
{equal: options?.equal},
216+
);
214217
}
215218

216219
function makeToSignalEqual<T>(

packages/core/rxjs-interop/test/to_signal_spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,30 @@ describe('toSignal()', () => {
274274
expect(updates).toBe(3);
275275
}),
276276
);
277+
278+
it(
279+
'should update when values are reference equal but equality function says otherwise',
280+
test(() => {
281+
const numsSet = new Set<number>();
282+
const nums$ = new BehaviorSubject<Set<number>>(numsSet);
283+
const nums = toSignal(nums$, {
284+
requireSync: true,
285+
equal: () => false,
286+
});
287+
288+
let updates = 0;
289+
const tracker = computed(() => {
290+
updates++;
291+
return Array.from(nums()!.values());
292+
});
293+
294+
expect(tracker()).toEqual([]);
295+
numsSet.add(1);
296+
nums$.next(numsSet); // same value as before
297+
expect(tracker()).toEqual([1]);
298+
expect(updates).toBe(2);
299+
}),
300+
);
277301
});
278302

279303
describe('in a @Component', () => {

0 commit comments

Comments
 (0)