From de4fad1f9c8a21be458f3b798bc629d94ff499cf Mon Sep 17 00:00:00 2001 From: Jessica Janiuk Date: Fri, 19 Sep 2025 11:07:08 -0700 Subject: [PATCH 1/3] Revert "fix(compiler-cli): capture metadata for undecorated fields (#63904)" This reverts commit 4c091abba617f07f9308baca98078c289de718d2. --- .../ngtsc/annotations/common/src/metadata.ts | 18 +-- .../annotations/common/test/metadata_spec.ts | 2 +- .../annotations/component/src/handler.ts | 9 -- .../annotations/directive/src/handler.ts | 25 +--- .../ngtsc/annotations/directive/src/shared.ts | 140 ------------------ .../test_cases/model_inputs/GOLDEN_PARTIAL.js | 6 +- .../output_function/GOLDEN_PARTIAL.js | 6 +- .../host_bindings/GOLDEN_PARTIAL.js | 6 +- .../GOLDEN_PARTIAL.js | 4 +- .../signal_inputs/GOLDEN_PARTIAL.js | 10 +- .../signal_queries/GOLDEN_PARTIAL.js | 8 +- .../inline_templates/GOLDEN_PARTIAL.js | 8 +- .../test/ngtsc/authoring_inputs_spec.ts | 20 --- .../test/ngtsc/authoring_models_spec.ts | 25 ---- .../test/ngtsc/authoring_outputs_spec.ts | 21 --- .../test/ngtsc/authoring_queries_spec.ts | 140 ------------------ 16 files changed, 29 insertions(+), 419 deletions(-) diff --git a/packages/compiler-cli/src/ngtsc/annotations/common/src/metadata.ts b/packages/compiler-cli/src/ngtsc/annotations/common/src/metadata.ts index 98903c398ef6..6299337a7456 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/common/src/metadata.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/common/src/metadata.ts @@ -30,9 +30,6 @@ import { import {valueReferenceToExpression, wrapFunctionExpressionsInParens} from './util'; -/** Function that extracts metadata from an undercorated class member. */ -export type UndecoratedMetadataExtractor = (member: ClassMember) => LiteralArrayExpr | null; - /** * Given a class declaration, generate a call to `setClassMetadata` with the Angular metadata * present on the class or its member fields. An ngDevMode guard is used to allow the call to be @@ -47,7 +44,6 @@ export function extractClassMetadata( isCore: boolean, annotateForClosureCompiler?: boolean, angularDecoratorTransform: (dec: Decorator) => Decorator = (dec) => dec, - undecoratedMetadataExtractor: UndecoratedMetadataExtractor = () => null, ): R3ClassMetadata | null { if (!reflection.isClass(clazz)) { return null; @@ -102,12 +98,10 @@ export function extractClassMetadata( let duplicateDecoratedMembers: ClassMember[] | null = null; for (const member of classMembers) { - const shouldQuoteName = member.nameNode !== null && ts.isStringLiteralLike(member.nameNode); - if (member.decorators !== null && member.decorators.length > 0) { decoratedMembers.push({ key: member.name, - quoted: shouldQuoteName, + quoted: false, value: decoratedClassMemberToMetadata(member.decorators!, isCore), }); @@ -117,16 +111,6 @@ export function extractClassMetadata( } else { seenMemberNames.add(member.name); } - } else { - const undecoratedMetadata = undecoratedMetadataExtractor(member); - - if (undecoratedMetadata !== null) { - decoratedMembers.push({ - key: member.name, - quoted: shouldQuoteName, - value: undecoratedMetadata, - }); - } } } diff --git a/packages/compiler-cli/src/ngtsc/annotations/common/test/metadata_spec.ts b/packages/compiler-cli/src/ngtsc/annotations/common/test/metadata_spec.ts index e117844ca449..5814cf434d80 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/common/test/metadata_spec.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/common/test/metadata_spec.ts @@ -108,7 +108,7 @@ runInEachFileSystem(() => { } `); expect(res).toContain( - `{ "has-dashes-in-name": [{ type: Input }], noDashesInName: [{ type: Input }] })`, + `{ 'has-dashes-in-name': [{ type: Input }], noDashesInName: [{ type: Input }] })`, ); }); diff --git a/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts b/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts index b8c0953c8277..70720ccf1c47 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts @@ -155,14 +155,12 @@ import { ResourceLoader, toFactoryMetadata, tryUnwrapForwardRef, - UndecoratedMetadataExtractor, validateHostDirectives, wrapFunctionExpressionsInParens, } from '../../common'; import { extractDirectiveMetadata, extractHostBindingResources, - getDirectiveUndecoratedMetadataExtractor, parseDirectiveStyles, } from '../../directive'; import {createModuleWithProvidersResolver, NgModuleSymbol} from '../../ng_module'; @@ -293,11 +291,6 @@ export class ComponentDecoratorHandler preserveSignificantWhitespace: this.i18nPreserveSignificantWhitespace, }; - this.undecoratedMetadataExtractor = getDirectiveUndecoratedMetadataExtractor( - reflector, - importTracker, - ); - // Dependencies can't be deferred during HMR, because the HMR update module can't have // dynamic imports and its dependencies need to be passed in directly. If dependencies // are deferred, their imports will be deleted so we may lose the reference to them. @@ -306,7 +299,6 @@ export class ComponentDecoratorHandler private literalCache = new Map(); private elementSchemaRegistry = new DomElementSchemaRegistry(); - private readonly undecoratedMetadataExtractor: UndecoratedMetadataExtractor; /** * During the asynchronous preanalyze phase, it's necessary to parse the template to extract @@ -983,7 +975,6 @@ export class ComponentDecoratorHandler this.isCore, this.annotateForClosureCompiler, (dec) => transformDecoratorResources(dec, component, styles, template), - this.undecoratedMetadataExtractor, ) : null, classDebugInfo: extractClassDebugInfo( diff --git a/packages/compiler-cli/src/ngtsc/annotations/directive/src/handler.ts b/packages/compiler-cli/src/ngtsc/annotations/directive/src/handler.ts index 875308dadc03..c97a5c8f9879 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/directive/src/handler.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/directive/src/handler.ts @@ -74,16 +74,10 @@ import { ReferencesRegistry, resolveProvidersRequiringFactory, toFactoryMetadata, - UndecoratedMetadataExtractor, validateHostDirectives, } from '../../common'; -import { - extractDirectiveMetadata, - extractHostBindingResources, - getDirectiveUndecoratedMetadataExtractor, - HostBindingNodes, -} from './shared'; +import {extractDirectiveMetadata, extractHostBindingResources, HostBindingNodes} from './shared'; import {DirectiveSymbol} from './symbol'; import {JitDeclarationRegistry} from '../../common/src/jit_declaration_registry'; import { @@ -160,16 +154,10 @@ export class DirectiveDecoratorHandler private readonly usePoisonedData: boolean, private readonly typeCheckHostBindings: boolean, private readonly emitDeclarationOnly: boolean, - ) { - this.undecoratedMetadataExtractor = getDirectiveUndecoratedMetadataExtractor( - reflector, - importTracker, - ); - } + ) {} readonly precedence = HandlerPrecedence.PRIMARY; readonly name = 'DirectiveDecoratorHandler'; - private readonly undecoratedMetadataExtractor: UndecoratedMetadataExtractor; detect( node: ClassDeclaration, @@ -252,14 +240,7 @@ export class DirectiveDecoratorHandler hostDirectives: directiveResult.hostDirectives, rawHostDirectives: directiveResult.rawHostDirectives, classMetadata: this.includeClassMetadata - ? extractClassMetadata( - node, - this.reflector, - this.isCore, - this.annotateForClosureCompiler, - undefined, - this.undecoratedMetadataExtractor, - ) + ? extractClassMetadata(node, this.reflector, this.isCore, this.annotateForClosureCompiler) : null, baseClass: readBaseClass(node, this.reflector, this.evaluator), typeCheckMeta: extractDirectiveTypeCheckMeta(node, directiveResult.inputs, this.reflector), diff --git a/packages/compiler-cli/src/ngtsc/annotations/directive/src/shared.ts b/packages/compiler-cli/src/ngtsc/annotations/directive/src/shared.ts index f5ecd7265b3e..65830fd6bb42 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/directive/src/shared.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/directive/src/shared.ts @@ -14,8 +14,6 @@ import { ExternalReference, ForwardRefHandling, getSafePropertyAccessString, - LiteralArrayExpr, - literalMap, MaybeForwardRefExpression, ParsedHostBindings, ParseError, @@ -26,10 +24,7 @@ import { R3QueryMetadata, R3Reference, verifyHostBindings, - R3Identifiers, - ArrowFunctionExpr, WrappedNodeExpr, - literal, } from '@angular/compiler'; import ts from 'typescript'; @@ -81,7 +76,6 @@ import { ReferencesRegistry, toR3Reference, tryUnwrapForwardRef, - UndecoratedMetadataExtractor, unwrapConstructorDependencies, unwrapExpression, validateConstructorDependencies, @@ -861,140 +855,6 @@ export function parseFieldStringArrayValue( return value; } -/** - * Returns a function that can be used to extract data for the `setClassMetadata` - * calls from undecorated directive class members. - */ -export function getDirectiveUndecoratedMetadataExtractor( - reflector: ReflectionHost, - importTracker: ImportedSymbolsTracker, -): UndecoratedMetadataExtractor { - return (member: ClassMember): LiteralArrayExpr | null => { - const input = tryParseSignalInputMapping(member, reflector, importTracker); - if (input !== null) { - return getDecoratorMetaArray([ - [new ExternalExpr(R3Identifiers.inputDecorator), memberMetadataFromSignalInput(input)], - ]); - } - - const output = tryParseInitializerBasedOutput(member, reflector, importTracker); - if (output !== null) { - return getDecoratorMetaArray([ - [ - new ExternalExpr(R3Identifiers.outputDecorator), - memberMetadataFromInitializerOutput(output.metadata), - ], - ]); - } - - const model = tryParseSignalModelMapping(member, reflector, importTracker); - if (model !== null) { - return getDecoratorMetaArray([ - [ - new ExternalExpr(R3Identifiers.inputDecorator), - memberMetadataFromSignalInput(model.input), - ], - [ - new ExternalExpr(R3Identifiers.outputDecorator), - memberMetadataFromInitializerOutput(model.output), - ], - ]); - } - - const query = tryParseSignalQueryFromInitializer(member, reflector, importTracker); - if (query !== null) { - let identifier: ExternalReference; - if (query.name === 'viewChild') { - identifier = R3Identifiers.viewChildDecorator; - } else if (query.name === 'viewChildren') { - identifier = R3Identifiers.viewChildrenDecorator; - } else if (query.name === 'contentChild') { - identifier = R3Identifiers.contentChildDecorator; - } else if (query.name === 'contentChildren') { - identifier = R3Identifiers.contentChildrenDecorator; - } else { - return null; - } - - return getDecoratorMetaArray([ - [new ExternalExpr(identifier), memberMetadataFromSignalQuery(query.call)], - ]); - } - - return null; - }; -} - -function getDecoratorMetaArray( - decorators: [type: ExternalExpr, args: LiteralArrayExpr][], -): LiteralArrayExpr { - return new LiteralArrayExpr( - decorators.map(([type, args]) => - literalMap([ - {key: 'type', value: type, quoted: false}, - {key: 'args', value: args, quoted: false}, - ]), - ), - ); -} - -function memberMetadataFromSignalInput(input: InputMapping): LiteralArrayExpr { - // Note that for signal inputs the transform is captured in the signal - // initializer so we don't need to capture it here. - return new LiteralArrayExpr([ - literalMap([ - { - key: 'isSignal', - value: literal(true), - quoted: false, - }, - { - key: 'alias', - value: literal(input.bindingPropertyName), - quoted: false, - }, - { - key: 'required', - value: literal(input.required), - quoted: false, - }, - ]), - ]); -} - -function memberMetadataFromInitializerOutput(output: InputOrOutput): LiteralArrayExpr { - return new LiteralArrayExpr([literal(output.bindingPropertyName)]); -} - -function memberMetadataFromSignalQuery(call: ts.CallExpression): LiteralArrayExpr { - const firstArg = call.arguments[0]; - const firstArgMeta = - ts.isStringLiteralLike(firstArg) || ts.isCallExpression(firstArg) - ? new WrappedNodeExpr(firstArg) - : // If the first argument is a class reference, we need to wrap it in a `forwardRef` - // because the reference might occur after the current class. This wouldn't be flagged - // on the query initializer, because it executes after the class is initialized, whereas - // `setClassMetadata` runs immediately. - new ExternalExpr(R3Identifiers.forwardRef).callFn([ - new ArrowFunctionExpr([], new WrappedNodeExpr(firstArg)), - ]); - - const entries: Expression[] = [ - // We use wrapped nodes here, because the output AST doesn't support spread assignments. - firstArgMeta, - new WrappedNodeExpr( - ts.factory.createObjectLiteralExpression([ - ...(call.arguments.length > 1 - ? [ts.factory.createSpreadAssignment(call.arguments[1])] - : []), - ts.factory.createPropertyAssignment('isSignal', ts.factory.createTrue()), - ]), - ), - ]; - - return new LiteralArrayExpr(entries); -} - function isStringArrayOrDie(value: any, name: string, node: ts.Expression): value is string[] { if (!Array.isArray(value)) { return false; diff --git a/packages/compiler-cli/test/compliance/test_cases/model_inputs/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/model_inputs/GOLDEN_PARTIAL.js index 33d14ee9b3b6..9dc3dd4539ec 100644 --- a/packages/compiler-cli/test/compliance/test_cases/model_inputs/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/model_inputs/GOLDEN_PARTIAL.js @@ -14,7 +14,7 @@ TestDir.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "0.0. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestDir, decorators: [{ type: Directive, args: [{}] - }], propDecorators: { counter: [{ type: i0.Input, args: [{ isSignal: true, alias: "counter", required: false }] }, { type: i0.Output, args: ["counterChange"] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }, { type: i0.Output, args: ["nameChange"] }] } }); + }] }); /**************************************************************************************************** * PARTIAL FILE: model_directive_definition.d.ts @@ -45,7 +45,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDE args: [{ template: 'Works', }] - }], propDecorators: { counter: [{ type: i0.Input, args: [{ isSignal: true, alias: "counter", required: false }] }, { type: i0.Output, args: ["counterChange"] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }, { type: i0.Output, args: ["nameChange"] }] } }); + }] }); /**************************************************************************************************** * PARTIAL FILE: model_component_definition.d.ts @@ -80,7 +80,7 @@ TestDir.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "0.0. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestDir, decorators: [{ type: Directive, args: [{}] - }], propDecorators: { counter: [{ type: i0.Input, args: [{ isSignal: true, alias: "counter", required: false }] }, { type: i0.Output, args: ["counterChange"] }], modelWithAlias: [{ type: i0.Input, args: [{ isSignal: true, alias: "alias", required: false }] }, { type: i0.Output, args: ["aliasChange"] }], decoratorInput: [{ + }], propDecorators: { decoratorInput: [{ type: Input }], decoratorInputWithAlias: [{ type: Input, diff --git a/packages/compiler-cli/test/compliance/test_cases/output_function/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/output_function/GOLDEN_PARTIAL.js index 724a4967fce1..bfb7ec07b0cf 100644 --- a/packages/compiler-cli/test/compliance/test_cases/output_function/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/output_function/GOLDEN_PARTIAL.js @@ -18,7 +18,7 @@ TestDir.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "0.0. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestDir, decorators: [{ type: Directive, args: [{}] - }], propDecorators: { a: [{ type: i0.Output, args: ["a"] }], b: [{ type: i0.Output, args: ["b"] }], c: [{ type: i0.Output, args: ["cPublic"] }], d: [{ type: i0.Output, args: ["d"] }], e: [{ type: i0.Output, args: ["e"] }] } }); + }] }); /**************************************************************************************************** * PARTIAL FILE: output_in_directive.d.ts @@ -56,7 +56,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDE args: [{ template: 'Works', }] - }], propDecorators: { a: [{ type: i0.Output, args: ["a"] }], b: [{ type: i0.Output, args: ["b"] }], c: [{ type: i0.Output, args: ["cPublic"] }], d: [{ type: i0.Output, args: ["d"] }], e: [{ type: i0.Output, args: ["e"] }] } }); + }] }); /**************************************************************************************************** * PARTIAL FILE: output_in_component.d.ts @@ -97,7 +97,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDE args: [{ standalone: true, }] - }], propDecorators: { click1: [{ type: i0.Output, args: ["click1"] }], click2: [{ type: i0.Output, args: ["click2"] }], click3: [{ type: i0.Output, args: ["click3"] }], _bla: [{ type: i0.Output, args: ["decoratorPublicName"] }], _bla2: [{ type: i0.Output, args: ["decoratorPublicName2"] }], clickDecorator1: [{ + }], propDecorators: { clickDecorator1: [{ type: Output }], clickDecorator2: [{ type: Output diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_bindings/host_bindings/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_bindings/host_bindings/GOLDEN_PARTIAL.js index 47fa28574425..10461822f019 100644 --- a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_bindings/host_bindings/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_bindings/host_bindings/GOLDEN_PARTIAL.js @@ -842,13 +842,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDE selector: '[hostBindingDir]', standalone: false }] - }], propDecorators: { "is-a": [{ + }], propDecorators: { 'is-a': [{ type: HostBinding, args: ['class.a'] - }], "is-\"b\"": [{ + }], 'is-"b"': [{ type: HostBinding, args: ['class.b'] - }], "\"is-c\"": [{ + }], '"is-c"': [{ type: HostBinding, args: ['class.c'] }] } }); diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_listener/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_listener/GOLDEN_PARTIAL.js index 4b1957b46610..166e20b604ae 100644 --- a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_listener/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_listener/GOLDEN_PARTIAL.js @@ -977,7 +977,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDE args: [{ selector: '[ngModel]', }] - }], propDecorators: { ngModel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngModel", required: true }] }, { type: i0.Output, args: ["ngModelChange"] }] } }); + }] }); export class TestCmp { constructor() { this.names = [signal('Angular')]; @@ -1031,7 +1031,7 @@ NgModelDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", versi i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: NgModelDirective, decorators: [{ type: Directive, args: [{ selector: '[ngModel]' }] - }], propDecorators: { ngModel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngModel", required: false }] }, { type: i0.Output, args: ["ngModelChange"] }] } }); + }] }); export class TestCmp { constructor() { this.value = 123; diff --git a/packages/compiler-cli/test/compliance/test_cases/signal_inputs/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/signal_inputs/GOLDEN_PARTIAL.js index 57031f20c3f4..c403b60b196c 100644 --- a/packages/compiler-cli/test/compliance/test_cases/signal_inputs/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/signal_inputs/GOLDEN_PARTIAL.js @@ -14,7 +14,7 @@ TestDir.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "0.0. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestDir, decorators: [{ type: Directive, args: [{}] - }], propDecorators: { counter: [{ type: i0.Input, args: [{ isSignal: true, alias: "counter", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }] } }); + }] }); /**************************************************************************************************** * PARTIAL FILE: input_directive_definition.d.ts @@ -45,7 +45,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDE args: [{ template: 'Works', }] - }], propDecorators: { counter: [{ type: i0.Input, args: [{ isSignal: true, alias: "counter", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }] } }); + }] }); /**************************************************************************************************** * PARTIAL FILE: input_component_definition.d.ts @@ -81,7 +81,7 @@ TestDir.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "0.0. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestDir, decorators: [{ type: Directive, args: [{}] - }], propDecorators: { counter: [{ type: i0.Input, args: [{ isSignal: true, alias: "counter", required: false }] }], signalWithTransform: [{ type: i0.Input, args: [{ isSignal: true, alias: "signalWithTransform", required: false }] }], signalWithTransformAndAlias: [{ type: i0.Input, args: [{ isSignal: true, alias: "publicNameSignal", required: false }] }], decoratorInput: [{ + }], propDecorators: { decoratorInput: [{ type: Input }], decoratorInputWithAlias: [{ type: Input, @@ -127,7 +127,7 @@ TestDir.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "0.0. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestDir, decorators: [{ type: Directive, args: [{}] - }], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }] } }); + }] }); /**************************************************************************************************** * PARTIAL FILE: transform_not_captured.d.ts @@ -163,7 +163,7 @@ TestDir.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "0.0. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestDir, decorators: [{ type: Directive, args: [{}] - }], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], name2: [{ type: i0.Input, args: [{ isSignal: true, alias: "name2", required: true }] }], genericTransform: [{ type: i0.Input, args: [{ isSignal: true, alias: "genericTransform", required: true }] }], genericTransform2: [{ type: i0.Input, args: [{ isSignal: true, alias: "genericTransform2", required: true }] }] } }); + }] }); /**************************************************************************************************** * PARTIAL FILE: complex_transform_functions.d.ts diff --git a/packages/compiler-cli/test/compliance/test_cases/signal_queries/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/signal_queries/GOLDEN_PARTIAL.js index 3229468d1dba..33d4b3d20ff3 100644 --- a/packages/compiler-cli/test/compliance/test_cases/signal_queries/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/signal_queries/GOLDEN_PARTIAL.js @@ -24,7 +24,7 @@ TestDir.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "0.0. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestDir, decorators: [{ type: Directive, args: [{}] - }], propDecorators: { query1: [{ type: i0.ViewChild, args: ['locatorA', { isSignal: true }] }], query2: [{ type: i0.ViewChildren, args: ['locatorB', { isSignal: true }] }], query3: [{ type: i0.ContentChild, args: ['locatorC', { isSignal: true }] }], query4: [{ type: i0.ContentChildren, args: ['locatorD', { isSignal: true }] }], query5: [{ type: i0.ViewChild, args: [forwardRef(() => SomeToken), { isSignal: true }] }], query6: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => SomeToken), { isSignal: true }] }], query7: [{ type: i0.ViewChild, args: ['locatorE', Object.assign({ read: SomeToken }, { isSignal: true })] }], query8: [{ type: i0.ContentChildren, args: ['locatorF, locatorG', Object.assign({ descendants: true }, { isSignal: true })] }], query9: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => nonAnalyzableRefersToString), Object.assign({ descendants: true }, { isSignal: true })] }] } }); + }] }); /**************************************************************************************************** * PARTIAL FILE: query_in_directive.d.ts @@ -66,7 +66,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDE args: [{ template: 'Works', }] - }], propDecorators: { query1: [{ type: i0.ViewChild, args: ['locatorA', { isSignal: true }] }], query2: [{ type: i0.ViewChildren, args: ['locatorB', { isSignal: true }] }], query3: [{ type: i0.ContentChild, args: ['locatorC', { isSignal: true }] }], query4: [{ type: i0.ContentChildren, args: ['locatorD', { isSignal: true }] }] } }); + }] }); /**************************************************************************************************** * PARTIAL FILE: query_in_component.d.ts @@ -100,10 +100,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDE }], propDecorators: { decoratorViewChild: [{ type: ViewChild, args: ['locator1'] - }], signalViewChild: [{ type: i0.ViewChild, args: ['locator1', { isSignal: true }] }], decoratorContentChild: [{ + }], decoratorContentChild: [{ type: ContentChild, args: ['locator2'] - }], signalContentChild: [{ type: i0.ContentChild, args: ['locator2', { isSignal: true }] }] } }); + }] } }); /**************************************************************************************************** * PARTIAL FILE: mixed_query_variants.d.ts diff --git a/packages/compiler-cli/test/compliance/test_cases/source_mapping/inline_templates/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/source_mapping/inline_templates/GOLDEN_PARTIAL.js index 4dc29dd6c109..37f60fb068ca 100644 --- a/packages/compiler-cli/test/compliance/test_cases/source_mapping/inline_templates/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/source_mapping/inline_templates/GOLDEN_PARTIAL.js @@ -930,7 +930,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDE /**************************************************************************************************** * PARTIAL FILE: two_way_binding_simple.js.map ****************************************************************************************************/ -{"version":3,"file":"two_way_binding_simple.js","sourceRoot":"","sources":["../two_way_binding_simple.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;;AAO1F,MAAM,OAAO,OAAO;IALpB;QAME,SAAI,GAAW,EAAE,CAAC;KACnB;;+GAFY,OAAO;mGAAP,OAAO,qEAHN,kCAAkC,gFAWnC,gBAAgB;sGARhB,OAAO;kBALnB,SAAS;mBAAC;oBACP,QAAQ,EAAE,UAAU;oBACpB,QAAQ,EAAE,kCAAkC;oBAC5C,UAAU,EAAE,KAAK;iBACpB;;AASD,MAAM,OAAO,gBAAgB;IAJ7B;QAKW,YAAO,GAAW,EAAE,CAAC;QACpB,mBAAc,GAAyB,IAAI,YAAY,EAAE,CAAC;KACrE;;wHAHY,gBAAgB;4GAAhB,gBAAgB;sGAAhB,gBAAgB;kBAJ5B,SAAS;mBAAC;oBACP,QAAQ,EAAE,WAAW;oBACrB,UAAU,EAAE,KAAK;iBACpB;;sBAEE,KAAK;;sBACL,MAAM;;AAIT,MAAM,OAAO,SAAS;;iHAAT,SAAS;kHAAT,SAAS,iBAdT,OAAO,EAQP,gBAAgB;kHAMhB,SAAS;sGAAT,SAAS;kBADrB,QAAQ;mBAAC,EAAC,YAAY,EAAE,CAAC,OAAO,EAAE,gBAAgB,CAAC,EAAC"} +{"version":3,"file":"two_way_binding_simple.js","sourceRoot":"","sources":["../two_way_binding_simple.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;;AAO1F,MAAM,OAAO,OAAO;IALpB;QAME,SAAI,GAAW,EAAE,CAAC;KACnB;;+GAFY,OAAO;mGAAP,OAAO,qEAHN,kCAAkC,gFAWnC,gBAAgB;sGARhB,OAAO;kBALnB,SAAS;mBAAC;oBACP,QAAQ,EAAE,UAAU;oBACpB,QAAQ,EAAE,kCAAkC;oBAC5C,UAAU,EAAE,KAAK;iBACpB;;AASD,MAAM,OAAO,gBAAgB;IAJ7B;QAKW,YAAO,GAAW,EAAE,CAAC;QACpB,mBAAc,GAAyB,IAAI,YAAY,EAAE,CAAC;KACrE;;wHAHY,gBAAgB;4GAAhB,gBAAgB;sGAAhB,gBAAgB;kBAJ5B,SAAS;mBAAC;oBACP,QAAQ,EAAE,WAAW;oBACrB,UAAU,EAAE,KAAK;iBACpB;8BAEU,OAAO;sBAAf,KAAK;gBACI,cAAc;sBAAvB,MAAM;;AAIT,MAAM,OAAO,SAAS;;iHAAT,SAAS;kHAAT,SAAS,iBAdT,OAAO,EAQP,gBAAgB;kHAMhB,SAAS;sGAAT,SAAS;kBADrB,QAAQ;mBAAC,EAAC,YAAY,EAAE,CAAC,OAAO,EAAE,gBAAgB,CAAC,EAAC"} /**************************************************************************************************** * PARTIAL FILE: two_way_binding_simple.d.ts ****************************************************************************************************/ @@ -1005,7 +1005,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDE /**************************************************************************************************** * PARTIAL FILE: two_way_binding_simple.js.map ****************************************************************************************************/ -{"version":3,"file":"two_way_binding_simple.js","sourceRoot":"","sources":["../two_way_binding_simple.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;;AAO1F,MAAM,OAAO,OAAO;IALpB;QAME,SAAI,GAAW,EAAE,CAAC;KACnB;;+GAFY,OAAO;mGAAP,OAAO,qEAHN,kCAAkC,gFAWnC,gBAAgB;sGARhB,OAAO;kBALnB,SAAS;mBAAC;oBACP,QAAQ,EAAE,UAAU;oBACpB,QAAQ,EAAE,kCAAkC;oBAC5C,UAAU,EAAE,KAAK;iBACpB;;AASD,MAAM,OAAO,gBAAgB;IAJ7B;QAKW,YAAO,GAAW,EAAE,CAAC;QACpB,mBAAc,GAAyB,IAAI,YAAY,EAAE,CAAC;KACrE;;wHAHY,gBAAgB;4GAAhB,gBAAgB;sGAAhB,gBAAgB;kBAJ5B,SAAS;mBAAC;oBACP,QAAQ,EAAE,WAAW;oBACrB,UAAU,EAAE,KAAK;iBACpB;;sBAEE,KAAK;;sBACL,MAAM;;AAIT,MAAM,OAAO,SAAS;;iHAAT,SAAS;kHAAT,SAAS,iBAdT,OAAO,EAQP,gBAAgB;kHAMhB,SAAS;sGAAT,SAAS;kBADrB,QAAQ;mBAAC,EAAC,YAAY,EAAE,CAAC,OAAO,EAAE,gBAAgB,CAAC,EAAC"} +{"version":3,"file":"two_way_binding_simple.js","sourceRoot":"","sources":["../two_way_binding_simple.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;;AAO1F,MAAM,OAAO,OAAO;IALpB;QAME,SAAI,GAAW,EAAE,CAAC;KACnB;;+GAFY,OAAO;mGAAP,OAAO,qEAHN,kCAAkC,gFAWnC,gBAAgB;sGARhB,OAAO;kBALnB,SAAS;mBAAC;oBACP,QAAQ,EAAE,UAAU;oBACpB,QAAQ,EAAE,kCAAkC;oBAC5C,UAAU,EAAE,KAAK;iBACpB;;AASD,MAAM,OAAO,gBAAgB;IAJ7B;QAKW,YAAO,GAAW,EAAE,CAAC;QACpB,mBAAc,GAAyB,IAAI,YAAY,EAAE,CAAC;KACrE;;wHAHY,gBAAgB;4GAAhB,gBAAgB;sGAAhB,gBAAgB;kBAJ5B,SAAS;mBAAC;oBACP,QAAQ,EAAE,WAAW;oBACrB,UAAU,EAAE,KAAK;iBACpB;8BAEU,OAAO;sBAAf,KAAK;gBACI,cAAc;sBAAvB,MAAM;;AAIT,MAAM,OAAO,SAAS;;iHAAT,SAAS;kHAAT,SAAS,iBAdT,OAAO,EAQP,gBAAgB;kHAMhB,SAAS;sGAAT,SAAS;kBADrB,QAAQ;mBAAC,EAAC,YAAY,EAAE,CAAC,OAAO,EAAE,gBAAgB,CAAC,EAAC"} /**************************************************************************************************** * PARTIAL FILE: two_way_binding_simple.d.ts ****************************************************************************************************/ @@ -1080,7 +1080,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDE /**************************************************************************************************** * PARTIAL FILE: two_way_binding_longhand.js.map ****************************************************************************************************/ -{"version":3,"file":"two_way_binding_longhand.js","sourceRoot":"","sources":["../two_way_binding_longhand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;;AAO1F,MAAM,OAAO,OAAO;IALpB;QAME,SAAI,GAAW,EAAE,CAAC;KACnB;;+GAFY,OAAO;mGAAP,OAAO,qEAHN,qCAAqC,gFAWtC,gBAAgB;sGARhB,OAAO;kBALnB,SAAS;mBAAC;oBACP,QAAQ,EAAE,UAAU;oBACpB,QAAQ,EAAE,qCAAqC;oBAC/C,UAAU,EAAE,KAAK;iBACpB;;AASD,MAAM,OAAO,gBAAgB;IAJ7B;QAKW,YAAO,GAAW,EAAE,CAAC;QACpB,mBAAc,GAAyB,IAAI,YAAY,EAAE,CAAC;KACrE;;wHAHY,gBAAgB;4GAAhB,gBAAgB;sGAAhB,gBAAgB;kBAJ5B,SAAS;mBAAC;oBACP,QAAQ,EAAE,WAAW;oBACrB,UAAU,EAAE,KAAK;iBACpB;;sBAEE,KAAK;;sBACL,MAAM;;AAIT,MAAM,OAAO,SAAS;;iHAAT,SAAS;kHAAT,SAAS,iBAdT,OAAO,EAQP,gBAAgB;kHAMhB,SAAS;sGAAT,SAAS;kBADrB,QAAQ;mBAAC,EAAC,YAAY,EAAE,CAAC,OAAO,EAAE,gBAAgB,CAAC,EAAC"} +{"version":3,"file":"two_way_binding_longhand.js","sourceRoot":"","sources":["../two_way_binding_longhand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;;AAO1F,MAAM,OAAO,OAAO;IALpB;QAME,SAAI,GAAW,EAAE,CAAC;KACnB;;+GAFY,OAAO;mGAAP,OAAO,qEAHN,qCAAqC,gFAWtC,gBAAgB;sGARhB,OAAO;kBALnB,SAAS;mBAAC;oBACP,QAAQ,EAAE,UAAU;oBACpB,QAAQ,EAAE,qCAAqC;oBAC/C,UAAU,EAAE,KAAK;iBACpB;;AASD,MAAM,OAAO,gBAAgB;IAJ7B;QAKW,YAAO,GAAW,EAAE,CAAC;QACpB,mBAAc,GAAyB,IAAI,YAAY,EAAE,CAAC;KACrE;;wHAHY,gBAAgB;4GAAhB,gBAAgB;sGAAhB,gBAAgB;kBAJ5B,SAAS;mBAAC;oBACP,QAAQ,EAAE,WAAW;oBACrB,UAAU,EAAE,KAAK;iBACpB;8BAEU,OAAO;sBAAf,KAAK;gBACI,cAAc;sBAAvB,MAAM;;AAIT,MAAM,OAAO,SAAS;;iHAAT,SAAS;kHAAT,SAAS,iBAdT,OAAO,EAQP,gBAAgB;kHAMhB,SAAS;sGAAT,SAAS;kBADrB,QAAQ;mBAAC,EAAC,YAAY,EAAE,CAAC,OAAO,EAAE,gBAAgB,CAAC,EAAC"} /**************************************************************************************************** * PARTIAL FILE: two_way_binding_longhand.d.ts ****************************************************************************************************/ @@ -1155,7 +1155,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDE /**************************************************************************************************** * PARTIAL FILE: two_way_binding_longhand.js.map ****************************************************************************************************/ -{"version":3,"file":"two_way_binding_longhand.js","sourceRoot":"","sources":["../two_way_binding_longhand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;;AAO1F,MAAM,OAAO,OAAO;IALpB;QAME,SAAI,GAAW,EAAE,CAAC;KACnB;;+GAFY,OAAO;mGAAP,OAAO,qEAHN,qCAAqC,gFAWtC,gBAAgB;sGARhB,OAAO;kBALnB,SAAS;mBAAC;oBACP,QAAQ,EAAE,UAAU;oBACpB,QAAQ,EAAE,qCAAqC;oBAC/C,UAAU,EAAE,KAAK;iBACpB;;AASD,MAAM,OAAO,gBAAgB;IAJ7B;QAKW,YAAO,GAAW,EAAE,CAAC;QACpB,mBAAc,GAAyB,IAAI,YAAY,EAAE,CAAC;KACrE;;wHAHY,gBAAgB;4GAAhB,gBAAgB;sGAAhB,gBAAgB;kBAJ5B,SAAS;mBAAC;oBACP,QAAQ,EAAE,WAAW;oBACrB,UAAU,EAAE,KAAK;iBACpB;;sBAEE,KAAK;;sBACL,MAAM;;AAIT,MAAM,OAAO,SAAS;;iHAAT,SAAS;kHAAT,SAAS,iBAdT,OAAO,EAQP,gBAAgB;kHAMhB,SAAS;sGAAT,SAAS;kBADrB,QAAQ;mBAAC,EAAC,YAAY,EAAE,CAAC,OAAO,EAAE,gBAAgB,CAAC,EAAC"} +{"version":3,"file":"two_way_binding_longhand.js","sourceRoot":"","sources":["../two_way_binding_longhand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;;AAO1F,MAAM,OAAO,OAAO;IALpB;QAME,SAAI,GAAW,EAAE,CAAC;KACnB;;+GAFY,OAAO;mGAAP,OAAO,qEAHN,qCAAqC,gFAWtC,gBAAgB;sGARhB,OAAO;kBALnB,SAAS;mBAAC;oBACP,QAAQ,EAAE,UAAU;oBACpB,QAAQ,EAAE,qCAAqC;oBAC/C,UAAU,EAAE,KAAK;iBACpB;;AASD,MAAM,OAAO,gBAAgB;IAJ7B;QAKW,YAAO,GAAW,EAAE,CAAC;QACpB,mBAAc,GAAyB,IAAI,YAAY,EAAE,CAAC;KACrE;;wHAHY,gBAAgB;4GAAhB,gBAAgB;sGAAhB,gBAAgB;kBAJ5B,SAAS;mBAAC;oBACP,QAAQ,EAAE,WAAW;oBACrB,UAAU,EAAE,KAAK;iBACpB;8BAEU,OAAO;sBAAf,KAAK;gBACI,cAAc;sBAAvB,MAAM;;AAIT,MAAM,OAAO,SAAS;;iHAAT,SAAS;kHAAT,SAAS,iBAdT,OAAO,EAQP,gBAAgB;kHAMhB,SAAS;sGAAT,SAAS;kBADrB,QAAQ;mBAAC,EAAC,YAAY,EAAE,CAAC,OAAO,EAAE,gBAAgB,CAAC,EAAC"} /**************************************************************************************************** * PARTIAL FILE: two_way_binding_longhand.d.ts ****************************************************************************************************/ diff --git a/packages/compiler-cli/test/ngtsc/authoring_inputs_spec.ts b/packages/compiler-cli/test/ngtsc/authoring_inputs_spec.ts index 379a3130a75a..34831b88d8b6 100644 --- a/packages/compiler-cli/test/ngtsc/authoring_inputs_spec.ts +++ b/packages/compiler-cli/test/ngtsc/authoring_inputs_spec.ts @@ -467,25 +467,5 @@ runInEachFileSystem(() => { const js = env.getContents('test.js'); expect(js).toContain('inputs: { data: [1, "data"] }'); }); - - it('should capture signal inputs in the setClassMetadata call', () => { - env.write( - 'test.ts', - ` - import {Directive, input} from '@angular/core'; - - @Directive() - export class TestDir { - data = input('test'); - } - `, - ); - env.driveMain(); - const js = env.getContents('test.js'); - expect(js).toContain('import * as i0 from "@angular/core";'); - expect(js).toContain(`i0.ɵsetClassMetadata(TestDir, [{ - type: Directive - }], null, { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }] });`); - }); }); }); diff --git a/packages/compiler-cli/test/ngtsc/authoring_models_spec.ts b/packages/compiler-cli/test/ngtsc/authoring_models_spec.ts index f36d1d91bbc2..13fe7023145a 100644 --- a/packages/compiler-cli/test/ngtsc/authoring_models_spec.ts +++ b/packages/compiler-cli/test/ngtsc/authoring_models_spec.ts @@ -776,30 +776,5 @@ runInEachFileSystem(() => { expect(diagnostics.length).toBe(0); }); }); - - it('should capture model input/output pair in the setClassMetadata call', () => { - env.write( - 'test.ts', - ` - import {Directive, model} from '@angular/core'; - - @Directive() - export class TestDir { - value = model(1); - } - `, - ); - env.driveMain(); - - const js = env.getContents('test.js'); - expect(js).toContain('import * as i0 from "@angular/core";'); - expect(js).toContain( - `i0.ɵsetClassMetadata(TestDir, [{ - type: Directive - }], null, { value: [` + - `{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, ` + - `{ type: i0.Output, args: ["valueChange"] }] });`, - ); - }); }); }); diff --git a/packages/compiler-cli/test/ngtsc/authoring_outputs_spec.ts b/packages/compiler-cli/test/ngtsc/authoring_outputs_spec.ts index 48a3dad4dad5..b3eb034ea66d 100644 --- a/packages/compiler-cli/test/ngtsc/authoring_outputs_spec.ts +++ b/packages/compiler-cli/test/ngtsc/authoring_outputs_spec.ts @@ -324,26 +324,5 @@ runInEachFileSystem(() => { expect(diagnostics.length).toBe(0); }); }); - - it('should capture initializer-based outputs in the setClassMetadata call', () => { - env.write( - 'test.ts', - ` - import {Component, output} from '@angular/core'; - - @Component({selector: 'test', template: ''}) - export class TestDir { - click = output(); - } - `, - ); - env.driveMain(); - const js = env.getContents('test.js'); - expect(js).toContain('import * as i0 from "@angular/core";'); - expect(js).toContain(`i0.ɵsetClassMetadata(TestDir, [{ - type: Component, - args: [{ selector: 'test', template: '' }] - }], null, { click: [{ type: i0.Output, args: ["click"] }] });`); - }); }); }); diff --git a/packages/compiler-cli/test/ngtsc/authoring_queries_spec.ts b/packages/compiler-cli/test/ngtsc/authoring_queries_spec.ts index 1835642d7730..6a9ca68e80af 100644 --- a/packages/compiler-cli/test/ngtsc/authoring_queries_spec.ts +++ b/packages/compiler-cli/test/ngtsc/authoring_queries_spec.ts @@ -389,146 +389,6 @@ runInEachFileSystem(() => { const diagnostics = env.driveDiagnostics(); expect(diagnostics.length).toBe(0); }); - - it('should capture a viewChild query in the setClasMetadata call', () => { - env.write( - 'test.ts', - ` - import {Component, viewChild} from '@angular/core'; - - @Component({selector: 'test', template: ''}) - export class TestDir { - el = viewChild('myLocator'); - } - `, - ); - env.driveMain(); - - const js = env.getContents('test.js'); - expect(js).toContain('import * as i0 from "@angular/core";'); - expect(js).toContain(`i0.ɵsetClassMetadata(TestDir, [{ - type: Component, - args: [{ selector: 'test', template: '' }] - }], null, { el: [{ type: i0.ViewChild, args: ['myLocator', { isSignal: true }] }] });`); - }); - - it('should capture a viewChildren query in the setClasMetadata call', () => { - env.write( - 'test.ts', - ` - import {Component, viewChildren} from '@angular/core'; - - @Component({selector: 'test', template: ''}) - export class TestDir { - el = viewChildren('myLocator'); - } - `, - ); - env.driveMain(); - - const js = env.getContents('test.js'); - expect(js).toContain('import * as i0 from "@angular/core";'); - expect(js).toContain(`i0.ɵsetClassMetadata(TestDir, [{ - type: Component, - args: [{ selector: 'test', template: '' }] - }], null, { el: [{ type: i0.ViewChildren, args: ['myLocator', { isSignal: true }] }] });`); - }); - - it('should capture a contentChild query in the setClasMetadata call', () => { - env.write( - 'test.ts', - ` - import {Component, contentChild} from '@angular/core'; - - @Component({selector: 'test', template: ''}) - export class TestDir { - el = contentChild('myLocator'); - } - `, - ); - env.driveMain(); - - const js = env.getContents('test.js'); - expect(js).toContain('import * as i0 from "@angular/core";'); - expect(js).toContain(`i0.ɵsetClassMetadata(TestDir, [{ - type: Component, - args: [{ selector: 'test', template: '' }] - }], null, { el: [{ type: i0.ContentChild, args: ['myLocator', { isSignal: true }] }] });`); - }); - - it('should capture a contentChildren query in the setClasMetadata call', () => { - env.write( - 'test.ts', - ` - import {Component, contentChildren} from '@angular/core'; - - @Component({selector: 'test', template: ''}) - export class TestDir { - el = contentChildren('myLocator'); - } - `, - ); - env.driveMain(); - - const js = env.getContents('test.js'); - expect(js).toContain('import * as i0 from "@angular/core";'); - expect(js).toContain(`i0.ɵsetClassMetadata(TestDir, [{ - type: Component, - args: [{ selector: 'test', template: '' }] - }], null, { el: [{ type: i0.ContentChildren, args: ['myLocator', { isSignal: true }] }] });`); - }); - - it('should capture a query with options in a setClassMetadata call', () => { - env.write( - 'test.ts', - ` - import {Component, viewChild, ElementRef} from '@angular/core'; - - @Component({selector: 'test', template: ''}) - export class TestDir { - el = viewChild('myLocator', {read: ElementRef}); - } - `, - ); - env.driveMain(); - - const js = env.getContents('test.js'); - expect(js).toContain('import * as i0 from "@angular/core";'); - expect(js).toContain( - `i0.ɵsetClassMetadata(TestDir, [{ - type: Component, - args: [{ selector: 'test', template: '' }] - }], null, { el: [{ type: i0.ViewChild, ` + - `args: ['myLocator', Object.assign({ read: ElementRef }, { isSignal: true })] }] });`, - ); - }); - - it('should wrap reference in query as a forwardRef in the setClassMetadata call', () => { - env.write( - 'test.ts', - ` - import {Component, Directive, viewChild} from '@angular/core'; - - @Component({selector: 'test', template: ''}) - export class TestDir { - el = viewChild(Dep); - } - - @Directive({selector: '[dep]'}) - export class Dep {} - `, - ); - env.driveMain(); - - const js = env.getContents('test.js'); - expect(js).toContain('import * as i0 from "@angular/core";'); - expect(js).toContain( - `i0.ɵsetClassMetadata(TestDir, [{ - type: Component, - args: [{ selector: 'test', template: '' }] - }], null, { el: [{ type: i0.ViewChild, args: [i0.forwardRef(() => Dep), { isSignal: true }] }] });`, - ); - }); }); }); }); From d9883d0d1f13485102c575cd9c4bc6b260fe8b8a Mon Sep 17 00:00:00 2001 From: Jessica Janiuk Date: Fri, 19 Sep 2025 11:07:32 -0700 Subject: [PATCH 2/3] Revert "refactor(compiler): expose member decorator identifiers (#63904)" This reverts commit ef0ff78de2082293bf3cc54ed6324de02faff8ce. --- packages/compiler/src/render3/r3_identifiers.ts | 11 ----------- packages/core/test/render3/jit_environment_spec.ts | 6 ------ 2 files changed, 17 deletions(-) diff --git a/packages/compiler/src/render3/r3_identifiers.ts b/packages/compiler/src/render3/r3_identifiers.ts index c2cf7044785c..3c48d64de48d 100644 --- a/packages/compiler/src/render3/r3_identifiers.ts +++ b/packages/compiler/src/render3/r3_identifiers.ts @@ -477,17 +477,6 @@ export class Identifiers { moduleName: CORE, }; - // Decorators - static inputDecorator: o.ExternalReference = {name: 'Input', moduleName: CORE}; - static outputDecorator: o.ExternalReference = {name: 'Output', moduleName: CORE}; - static viewChildDecorator: o.ExternalReference = {name: 'ViewChild', moduleName: CORE}; - static viewChildrenDecorator: o.ExternalReference = {name: 'ViewChildren', moduleName: CORE}; - static contentChildDecorator: o.ExternalReference = {name: 'ContentChild', moduleName: CORE}; - static contentChildrenDecorator: o.ExternalReference = { - name: 'ContentChildren', - moduleName: CORE, - }; - // type-checking static InputSignalBrandWriteType = {name: 'ɵINPUT_SIGNAL_BRAND_WRITE_TYPE', moduleName: CORE}; static UnwrapDirectiveSignalInputs = {name: 'ɵUnwrapDirectiveSignalInputs', moduleName: CORE}; diff --git a/packages/core/test/render3/jit_environment_spec.ts b/packages/core/test/render3/jit_environment_spec.ts index 1184eaa4920b..87db419d252c 100644 --- a/packages/core/test/render3/jit_environment_spec.ts +++ b/packages/core/test/render3/jit_environment_spec.ts @@ -29,12 +29,6 @@ const INTERFACE_EXCEPTIONS = new Set([ const AOT_ONLY = new Set([ 'ɵsetClassMetadata', 'ɵsetClassMetadataAsync', - 'Input', - 'Output', - 'ViewChild', - 'ViewChildren', - 'ContentChild', - 'ContentChildren', // used in type-checking. 'ɵINPUT_SIGNAL_BRAND_WRITE_TYPE', From 27aa2c8c747c712c9d21a1a12475cf0a7ab9f45c Mon Sep 17 00:00:00 2001 From: Jessica Janiuk Date: Fri, 19 Sep 2025 11:07:52 -0700 Subject: [PATCH 3/3] Revert "refactor(compiler-cli): track member metadata using output AST (#63904)" This reverts commit ffe94b3a89be1c6153063b9d6533d70c14a0ea1c. --- .../ngtsc/annotations/common/src/metadata.ts | 50 +++++++------------ 1 file changed, 19 insertions(+), 31 deletions(-) diff --git a/packages/compiler-cli/src/ngtsc/annotations/common/src/metadata.ts b/packages/compiler-cli/src/ngtsc/annotations/common/src/metadata.ts index 6299337a7456..e6d782d461cd 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/common/src/metadata.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/common/src/metadata.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ -import {ErrorCode, FatalDiagnosticError} from '../../../diagnostics'; +import {ErrorCode, FatalDiagnosticError, makeRelatedInformation} from '../../../diagnostics'; import { ArrowFunctionExpr, Expression, @@ -19,7 +19,6 @@ import { import ts from 'typescript'; import { - ClassMember, ClassMemberAccessLevel, CtorParameter, DeclarationNode, @@ -89,32 +88,15 @@ export function extractClassMetadata( const classMembers = reflection.getMembersOfClass(clazz).filter( (member) => !member.isStatic && + member.decorators !== null && + member.decorators.length > 0 && // Private fields are not supported in the metadata emit member.accessLevel !== ClassMemberAccessLevel.EcmaScriptPrivate, ); - - const decoratedMembers: {key: string; value: Expression; quoted: boolean}[] = []; - const seenMemberNames = new Set(); - let duplicateDecoratedMembers: ClassMember[] | null = null; - - for (const member of classMembers) { - if (member.decorators !== null && member.decorators.length > 0) { - decoratedMembers.push({ - key: member.name, - quoted: false, - value: decoratedClassMemberToMetadata(member.decorators!, isCore), - }); - - if (seenMemberNames.has(member.name)) { - duplicateDecoratedMembers ??= []; - duplicateDecoratedMembers.push(member); - } else { - seenMemberNames.add(member.name); - } - } - } - - if (duplicateDecoratedMembers !== null) { + const duplicateDecoratedMembers = classMembers.filter( + (member, i, arr) => arr.findIndex((arrayMember) => arrayMember.name === member.name) < i, + ); + if (duplicateDecoratedMembers.length > 0) { // This should theoretically never happen, because the only way to have duplicate instance // member names is getter/setter pairs and decorators cannot appear in both a getter and the // corresponding setter. @@ -125,9 +107,13 @@ export function extractClassMetadata( duplicateDecoratedMembers.map((member) => member.name).join(', '), ); } - + const decoratedMembers = classMembers.map((member) => + classMemberToMetadata(member.nameNode ?? member.name, member.decorators!, isCore), + ); if (decoratedMembers.length > 0) { - metaPropDecorators = literalMap(decoratedMembers); + metaPropDecorators = new WrappedNodeExpr( + ts.factory.createObjectLiteralExpression(decoratedMembers), + ); } return { @@ -167,14 +153,16 @@ function ctorParameterToMetadata(param: CtorParameter, isCore: boolean): Express /** * Convert a reflected class member to metadata. */ -function decoratedClassMemberToMetadata( +function classMemberToMetadata( + name: ts.PropertyName | string, decorators: Decorator[], isCore: boolean, -): LiteralArrayExpr { +): ts.PropertyAssignment { const ngDecorators = decorators .filter((dec) => isAngularDecorator(dec, isCore)) - .map((decorator: Decorator) => new WrappedNodeExpr(decoratorToMetadata(decorator))); - return new LiteralArrayExpr(ngDecorators); + .map((decorator: Decorator) => decoratorToMetadata(decorator)); + const decoratorMeta = ts.factory.createArrayLiteralExpression(ngDecorators); + return ts.factory.createPropertyAssignment(name, decoratorMeta); } /**