Skip to content

Commit b401c18

Browse files
JoostKatscott
authored andcommitted
fix(core): include signal debug names in their toString() representation
The `toString()` implementations in the primitives package intended to include the debug name, yet the debug name was evaluated during construction before it could ever have been assigned. This commit fixes that. The Angular wrappers override the `toString()` representation to evaluate signals ad-hoc instead of showing their internal state, and this commit aligns their behavior to include the debug name in `toString` as well.
1 parent 0837d25 commit b401c18

File tree

9 files changed

+29
-16
lines changed

9 files changed

+29
-16
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ import {
1414
producerUpdateValueVersion,
1515
REACTIVE_NODE,
1616
ReactiveNode,
17+
runPostProducerCreatedFn,
1718
setActiveConsumer,
1819
SIGNAL,
19-
runPostProducerCreatedFn,
2020
} from './graph';
2121

2222
// Required as the signals library is in a separate package, so we need to explicitly ensure the
@@ -83,8 +83,8 @@ export function createComputed<T>(
8383

8484
(computed as ComputedGetter<T>)[SIGNAL] = node;
8585
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
86-
const debugName = node.debugName ? ' (' + node.debugName + ')' : '';
87-
computed.toString = () => `[Computed${debugName}: ${String(node.value)}]`;
86+
computed.toString = () =>
87+
`[Computed${node.debugName ? ' (' + node.debugName + ')' : ''}: ${String(node.value)}]`;
8888
}
8989

9090
runPostProducerCreatedFn(node);

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ export function createLinkedSignal<S, D>(
9393
const getter = linkedSignalGetter as LinkedSignalGetter<S, D>;
9494
getter[SIGNAL] = node;
9595
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
96-
const debugName = node.debugName ? ' (' + node.debugName + ')' : '';
97-
getter.toString = () => `[LinkedSignal${debugName}: ${String(node.value)}]`;
96+
getter.toString = () =>
97+
`[LinkedSignal${node.debugName ? ' (' + node.debugName + ')' : ''}: ${String(node.value)}]`;
9898
}
9999

100100
runPostProducerCreatedFn(node);

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ export function createSignal<T>(
6262
const getter = (() => signalGetFn(node)) as SignalGetter<T>;
6363
(getter as any)[SIGNAL] = node;
6464
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
65-
const debugName = node.debugName ? ' (' + node.debugName + ')' : '';
66-
getter.toString = () => `[Signal${debugName}: ${String(node.value)}]`;
65+
getter.toString = () =>
66+
`[Signal${node.debugName ? ' (' + node.debugName + ')' : ''}: ${String(node.value)}]`;
6767
}
6868

6969
runPostProducerCreatedFn(node);

packages/core/src/render3/reactivity/computed.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,10 @@ export interface CreateComputedOptions<T> {
3232
export function computed<T>(computation: () => T, options?: CreateComputedOptions<T>): Signal<T> {
3333
const getter = createComputed(computation, options?.equal);
3434

35-
if (ngDevMode) {
36-
getter.toString = () => `[Computed: ${getter()}]`;
37-
getter[SIGNAL].debugName = options?.debugName;
35+
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
36+
const debugName = options?.debugName;
37+
getter[SIGNAL].debugName = debugName;
38+
getter.toString = () => `[Computed${debugName ? ' (' + debugName + ')' : ''}: ${getter()}]`;
3839
}
3940

4041
return getter;

packages/core/src/render3/reactivity/linked_signal.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@ function upgradeLinkedSignalGetter<S, D>(
7878
getter: LinkedSignalGetter<S, D>,
7979
debugName?: string,
8080
): WritableSignal<D> {
81-
if (ngDevMode) {
82-
getter.toString = () => `[LinkedSignal: ${getter()}]`;
81+
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
8382
getter[SIGNAL].debugName = debugName;
83+
getter.toString = () => `[LinkedSignal${debugName ? ' (' + debugName + ')' : ''}: ${getter()}]`;
8484
}
8585

8686
const node = getter[SIGNAL] as LinkedSignalNode<S, D>;

packages/core/src/render3/reactivity/signal.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,10 @@ export function signal<T>(initialValue: T, options?: CreateSignalOptions<T>): Wr
7979
signalFn.update = update;
8080
signalFn.asReadonly = signalAsReadonlyFn.bind(signalFn as any) as () => Signal<T>;
8181

82-
if (ngDevMode) {
83-
signalFn.toString = () => `[Signal: ${signalFn()}]`;
84-
node.debugName = options?.debugName;
82+
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
83+
const debugName = options?.debugName;
84+
node.debugName = debugName;
85+
signalFn.toString = () => `[Signal${debugName ? ' (' + debugName + ')' : ''}: ${signalFn()}]`;
8586
}
8687

8788
return signalFn as WritableSignal<T>;

packages/core/test/signals/computed_spec.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,12 @@ describe('computed', () => {
200200
expect(double + '').toBe('[Computed: 2]');
201201
});
202202

203+
it('should have a toString implementation with debugName', () => {
204+
const counter = signal(1);
205+
const double = computed(() => counter() * 2, {debugName: 'double'});
206+
expect(double + '').toBe('[Computed (double): 2]');
207+
});
208+
203209
it('should set debugName when a debugName is provided', () => {
204210
const primitiveSignal = signal(0);
205211
const node = computed(() => primitiveSignal(), {debugName: 'computedSignal'})[

packages/core/test/signals/linked_signal_spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ describe('linkedSignal', () => {
5555
});
5656

5757
expect(choice()).toBe('apple');
58-
expect(choice.toString()).toBe('[LinkedSignal: apple]');
58+
expect(choice.toString()).toBe('[LinkedSignal (TestChoice): apple]');
5959
});
6060

6161
it('should update when the source changes', () => {

packages/core/test/signals/signal_spec.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ describe('signals', () => {
133133
expect(state + '').toBe('[Signal: false]');
134134
});
135135

136+
it('should have a toString implementation with debugName', () => {
137+
const state = signal(false, {debugName: 'state'});
138+
expect(state + '').toBe('[Signal (state): false]');
139+
});
140+
136141
it('should set debugName when a debugName is provided', () => {
137142
const node = signal(false, {debugName: 'falseSignal'})[SIGNAL] as ReactiveNode;
138143
expect(node.debugName).toBe('falseSignal');

0 commit comments

Comments
 (0)