Skip to content

Commit eee0af0

Browse files
committed
refactor(core): add internal signal input support for @Input decorator (#53808)
We are adding internal support for declaring signal inputs via the `@Input` decorator. This is needed for JIT unit testing, or JIT applications. In JIT, Angular is not able to recognize signal inputs due to the lack of static reflection metadata. Decorators attach their information on the class- without it needing to be instantiated. This allows Angular to know inputs when preparing/generating the directive definition. With signal inputs this is not possible- so we need a way to tell Angular about inputs for JIT applications. We've decided that this is not something users should have to deal with, so a transform will be added in a follow-up that will automatically derive/and add the decorators for signal inputs when requested in JIT environments. PR Close #53808
1 parent 6fcfe2b commit eee0af0

File tree

3 files changed

+21
-2
lines changed

3 files changed

+21
-2
lines changed

packages/compiler/src/core.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ export interface Input {
3434
alias?: string;
3535
required?: boolean;
3636
transform?: (value: any) => any;
37+
// Note: This field is marked as `internal` in `@angular/core`, but in the compiler
38+
// we rely on it for JIT processing at runtime.
39+
isSignal: boolean;
3740
}
3841

3942
/** Flags describing an input for a directive. */

packages/compiler/src/jit_compiler_facade.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,10 @@ function convertDirectiveFacadeToMetadata(facade: R3DirectiveMetadataFacade): R3
335335
bindingPropertyName: ann.alias || field,
336336
classPropertyName: field,
337337
required: ann.required || false,
338-
// TODO(signals): Support JIT signal inputs via decorator transform.
339-
isSignal: false,
338+
// For JIT, decorators are used to declare signal inputs. That is because of
339+
// a technical limitation where it's not possible to statically reflect class
340+
// members of a directive/component at runtime before instantiating the class.
341+
isSignal: !!ann.isSignal,
340342
transformFunction: ann.transform != null ? new WrappedNodeExpr(ann.transform) : null,
341343
};
342344
} else if (isOutput(ann)) {

packages/core/src/metadata/directives.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,20 @@ export interface Input {
832832
* Function with which to transform the input value before assigning it to the directive instance.
833833
*/
834834
transform?: (value: any) => any;
835+
836+
/**
837+
* @internal
838+
*
839+
* Whether the input is a signal input.
840+
*
841+
* This option exists for JIT compatibility. Users are not expected to use this.
842+
* Angular needs a way to capture inputs from classes so that the internal data
843+
* structures can be set up. This needs to happen before the component is instantiated.
844+
* Due to this, for JIT compilation, signal inputs need an additional decorator
845+
* declaring the input. Angular provides a TS transformer to automatically handle this
846+
* for JIT usage (e.g. in tests).
847+
*/
848+
isSignal?: boolean;
835849
}
836850

837851
/**

0 commit comments

Comments
 (0)