Skip to content

Commit ec386e7

Browse files
AleksanderBodurriAndrewKushnir
authored andcommitted
feat(core): introduce debugName optional arg to framework signal functions (#57073)
Angular DevTools is working on developing signal debugging support. This commit is a step in the direction of making available debug information to the framework that will allow Angular DevTools to provide users with more accurate information regarding the usage of signals in their applications. Follow up PRs that will use this arg will: - Develop a typescript transform that will detect usages of signal functions and attempt to add a debugName without the user needing to specify one directly - Develop debug APIs for discovering signal graphs within Angular applications (using debugName as a way to label nodes on the graph) PR Close #57073
1 parent 1e9328e commit ec386e7

File tree

17 files changed

+372
-38
lines changed

17 files changed

+372
-38
lines changed

goldens/public-api/core/index.api.md

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -382,20 +382,24 @@ export interface ContentChildFunction {
382382
<LocatorT>(locator: ProviderToken<LocatorT> | string, opts?: {
383383
descendants?: boolean;
384384
read?: undefined;
385+
debugName?: string;
385386
}): Signal<LocatorT | undefined>;
386387
// (undocumented)
387388
<LocatorT, ReadT>(locator: ProviderToken<LocatorT> | string, opts: {
388389
descendants?: boolean;
389390
read: ProviderToken<ReadT>;
391+
debugName?: string;
390392
}): Signal<ReadT | undefined>;
391393
required: {
392394
<LocatorT>(locator: ProviderToken<LocatorT> | string, opts?: {
393395
descendants?: boolean;
394396
read?: undefined;
397+
debugName?: string;
395398
}): Signal<LocatorT>;
396399
<LocatorT, ReadT>(locator: ProviderToken<LocatorT> | string, opts: {
397400
descendants?: boolean;
398401
read: ProviderToken<ReadT>;
402+
debugName?: string;
399403
}): Signal<ReadT>;
400404
};
401405
}
@@ -410,12 +414,14 @@ export const ContentChildren: ContentChildrenDecorator;
410414
export function contentChildren<LocatorT>(locator: ProviderToken<LocatorT> | string, opts?: {
411415
descendants?: boolean;
412416
read?: undefined;
417+
debugName?: string;
413418
}): Signal<ReadonlyArray<LocatorT>>;
414419

415420
// @public (undocumented)
416421
export function contentChildren<LocatorT, ReadT>(locator: ProviderToken<LocatorT> | string, opts: {
417422
descendants?: boolean;
418423
read: ProviderToken<ReadT>;
424+
debugName?: string;
419425
}): Signal<ReadonlyArray<ReadT>>;
420426

421427
// @public
@@ -443,13 +449,15 @@ export function createComponent<C>(component: Type<C>, options: {
443449

444450
// @public
445451
export interface CreateComputedOptions<T> {
452+
debugName?: string;
446453
equal?: ValueEqualityFn<T>;
447454
}
448455

449456
// @public
450457
export interface CreateEffectOptions {
451458
// @deprecated (undocumented)
452459
allowSignalWrites?: boolean;
460+
debugName?: string;
453461
forceRoot?: true;
454462
injector?: Injector;
455463
manualCleanup?: boolean;
@@ -472,6 +480,7 @@ export function createPlatformFactory(parentPlatformFactory: ((extraProviders?:
472480

473481
// @public
474482
export interface CreateSignalOptions<T> {
483+
debugName?: string;
475484
equal?: ValueEqualityFn<T>;
476485
}
477486

@@ -993,6 +1002,7 @@ export interface InputFunction {
9931002
// @public
9941003
export interface InputOptions<T, TransformT> {
9951004
alias?: string;
1005+
debugName?: string;
9961006
transform?: (v: TransformT) => T;
9971007
}
9981008

@@ -1166,6 +1176,7 @@ export interface ModelFunction {
11661176
// @public
11671177
export interface ModelOptions {
11681178
alias?: string;
1179+
debugName?: string;
11691180
}
11701181

11711182
// @public
@@ -1855,15 +1866,21 @@ export interface ViewChildDecorator {
18551866

18561867
// @public
18571868
export interface ViewChildFunction {
1858-
<LocatorT>(locator: ProviderToken<LocatorT> | string): Signal<LocatorT | undefined>;
1859-
// (undocumented)
18601869
<LocatorT, ReadT>(locator: ProviderToken<LocatorT> | string, opts: {
18611870
read: ProviderToken<ReadT>;
1871+
debugName?: string;
18621872
}): Signal<ReadT | undefined>;
1873+
// (undocumented)
1874+
<LocatorT>(locator: ProviderToken<LocatorT> | string, opts?: {
1875+
debugName?: string;
1876+
}): Signal<LocatorT | undefined>;
18631877
required: {
1864-
<LocatorT>(locator: ProviderToken<LocatorT> | string): Signal<LocatorT>;
1878+
<LocatorT>(locator: ProviderToken<LocatorT> | string, opts?: {
1879+
debugName?: string;
1880+
}): Signal<LocatorT>;
18651881
<LocatorT, ReadT>(locator: ProviderToken<LocatorT> | string, opts: {
18661882
read: ProviderToken<ReadT>;
1883+
debugName?: string;
18671884
}): Signal<ReadT>;
18681885
};
18691886
}
@@ -1875,11 +1892,14 @@ export type ViewChildren = Query;
18751892
export const ViewChildren: ViewChildrenDecorator;
18761893

18771894
// @public (undocumented)
1878-
export function viewChildren<LocatorT>(locator: ProviderToken<LocatorT> | string): Signal<ReadonlyArray<LocatorT>>;
1895+
export function viewChildren<LocatorT>(locator: ProviderToken<LocatorT> | string, opts?: {
1896+
debugName?: string;
1897+
}): Signal<ReadonlyArray<LocatorT>>;
18791898

18801899
// @public (undocumented)
18811900
export function viewChildren<LocatorT, ReadT>(locator: ProviderToken<LocatorT> | string, opts: {
18821901
read: ProviderToken<ReadT>;
1902+
debugName?: string;
18831903
}): Signal<ReadonlyArray<ReadT>>;
18841904

18851905
// @public

packages/core/src/authoring/input/input_signal.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ export interface InputOptions<T, TransformT> {
3232
* handle such string values and convert them to `boolean`. See: {@link booleanAttribute}.
3333
*/
3434
transform?: (v: TransformT) => T;
35+
36+
/**
37+
* A debug name for the input signal. Used in Angular DevTools to identify the signal.
38+
*/
39+
debugName?: string;
3540
}
3641

3742
/**
@@ -135,6 +140,7 @@ export function createInputSignal<T, TransformT>(
135140

136141
if (ngDevMode) {
137142
inputValueFn.toString = () => `[Input Signal: ${inputValueFn()}]`;
143+
node.debugName = options?.debugName;
138144
}
139145

140146
return inputValueFn as InputSignalWithTransform<T, TransformT>;

packages/core/src/authoring/input/input_signal_node.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ export interface InputSignalNode<T, TransformT> extends SignalNode<T> {
3030
* purposes we assume it's a valid `T` value. Type-checking will enforce that.
3131
*/
3232
applyValueToInputSignal<T, TransformT>(node: InputSignalNode<T, TransformT>, value: T): void;
33+
34+
/**
35+
* A debug name for the input signal. Used in Angular DevTools to identify the signal.
36+
*/
37+
debugName?: string;
3338
}
3439

3540
// Note: Using an IIFE here to ensure that the spread assignment is not considered

packages/core/src/authoring/model/model.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,19 @@ import {REQUIRED_UNSET_VALUE} from '../input/input_signal_node';
1111

1212
import {createModelSignal, ModelOptions, ModelSignal} from './model_signal';
1313

14-
export function modelFunction<T>(initialValue?: T): ModelSignal<T | undefined> {
14+
export function modelFunction<T>(
15+
initialValue?: T,
16+
opts?: ModelOptions,
17+
): ModelSignal<T | undefined> {
1518
ngDevMode && assertInInjectionContext(model);
1619

17-
return createModelSignal(initialValue);
20+
return createModelSignal(initialValue, opts);
1821
}
1922

20-
export function modelRequiredFunction<T>(): ModelSignal<T> {
23+
export function modelRequiredFunction<T>(opts?: ModelOptions): ModelSignal<T> {
2124
ngDevMode && assertInInjectionContext(model);
2225

23-
return createModelSignal(REQUIRED_UNSET_VALUE as T);
26+
return createModelSignal(REQUIRED_UNSET_VALUE as T, opts);
2427
}
2528

2629
/**

packages/core/src/authoring/model/model_signal.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ export interface ModelOptions {
3535
* name as the input, but suffixed with `Change`. By default, the class field name is used.
3636
*/
3737
alias?: string;
38+
39+
/**
40+
* A debug name for the model signal. Used in Angular DevTools to identify the signal.
41+
*/
42+
debugName?: string;
3843
}
3944

4045
/**
@@ -56,7 +61,7 @@ export interface ModelSignal<T> extends WritableSignal<T>, InputSignal<T>, Outpu
5661
* Can be set to {@link REQUIRED_UNSET_VALUE} for required model signals.
5762
* @param options Additional options for the model.
5863
*/
59-
export function createModelSignal<T>(initialValue: T): ModelSignal<T> {
64+
export function createModelSignal<T>(initialValue: T, opts?: ModelOptions): ModelSignal<T> {
6065
const node: InputSignalNode<T, T> = Object.create(INPUT_SIGNAL_NODE);
6166
const emitterRef = new OutputEmitterRef<T>();
6267

@@ -89,6 +94,7 @@ export function createModelSignal<T>(initialValue: T): ModelSignal<T> {
8994

9095
if (ngDevMode) {
9196
getter.toString = () => `[Model Signal: ${getter()}]`;
97+
node.debugName = opts?.debugName;
9298
}
9399

94100
return getter as typeof getter &

0 commit comments

Comments
 (0)