From 75277cd94b908996c6b90b79d3a754c543057c7f Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Tue, 15 Nov 2016 09:19:00 -0800 Subject: [PATCH] fix(tsickle): support ctorParams in function closure (#12876) See https://github.com/angular/tsickle/issues/261 for context. --- .../compiler-cli/src/static_reflector.ts | 1 - .../test/static_reflector_spec.ts | 21 ++++++++++++++++++- .../src/reflection/reflection_capabilities.ts | 8 +++++-- .../core/test/reflection/reflector_spec.ts | 19 +++++++++++++++++ 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/modules/@angular/compiler-cli/src/static_reflector.ts b/modules/@angular/compiler-cli/src/static_reflector.ts index fe800b4485..0ca3c7657d 100644 --- a/modules/@angular/compiler-cli/src/static_reflector.ts +++ b/modules/@angular/compiler-cli/src/static_reflector.ts @@ -132,7 +132,6 @@ export class StaticReflector implements ReflectorReader { const ctor = (ctorData).find(a => a['__symbolic'] == 'constructor'); const parameterTypes = this.simplify(type, ctor['parameters'] || []); const parameterDecorators = this.simplify(type, ctor['parameterDecorators'] || []); - parameters = []; parameterTypes.forEach((paramType, index) => { const nestedResult: any[] = []; diff --git a/modules/@angular/compiler-cli/test/static_reflector_spec.ts b/modules/@angular/compiler-cli/test/static_reflector_spec.ts index 6909d8404d..6346a96b07 100644 --- a/modules/@angular/compiler-cli/test/static_reflector_spec.ts +++ b/modules/@angular/compiler-cli/test/static_reflector_spec.ts @@ -7,7 +7,7 @@ */ import {StaticReflector, StaticReflectorHost, StaticSymbol} from '@angular/compiler-cli/src/static_reflector'; -import {HostListener, animate, group, keyframes, sequence, state, style, transition, trigger} from '@angular/core'; +import {HostListener, Inject, animate, group, keyframes, sequence, state, style, transition, trigger} from '@angular/core'; import {MetadataCollector} from '@angular/tsc-wrapped'; import * as ts from 'typescript'; @@ -410,6 +410,13 @@ describe('StaticReflector', () => { expect(props).toEqual({foo: []}); }); + it('should read ctor parameters with forwardRef', () => { + const src = '/tmp/src/forward-ref.ts'; + const dep = host.getStaticSymbol(src, 'Dep'); + const props = reflector.parameters(host.getStaticSymbol(src, 'Forward')); + expect(props).toEqual([[dep, new Inject(dep)]]); + }); + it('should report an error for invalid function calls', () => { expect( () => @@ -1068,6 +1075,18 @@ class MockReflectorHost implements StaticReflectorHost { providers: [ { provider: 'a', useValue: (() => 1)() }] }) export class InvalidMetadata {} + `, + '/tmp/src/forward-ref.ts': ` + import {forwardRef} from 'angular2/core'; + import {Component} from 'angular2/src/core/metadata'; + import {Inject} from 'angular2/src/core/di/metadata'; + @Component({}) + export class Forward { + constructor(@Inject(forwardRef(() => Dep)) d: Dep) {} + } + export class Dep { + @Input f: Forward; + } ` }; diff --git a/modules/@angular/core/src/reflection/reflection_capabilities.ts b/modules/@angular/core/src/reflection/reflection_capabilities.ts index 4844973ced..620812166d 100644 --- a/modules/@angular/core/src/reflection/reflection_capabilities.ts +++ b/modules/@angular/core/src/reflection/reflection_capabilities.ts @@ -56,8 +56,12 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities { } // API of tsickle for lowering decorators to properties on the class. - if ((type).ctorParameters) { - const ctorParameters = (type).ctorParameters; + const tsickleCtorParams = (type).ctorParameters; + if (tsickleCtorParams) { + // Newer tsickle uses a function closure + // Retain the non-function case for compatibility with older tsickle + const ctorParameters = + typeof tsickleCtorParams === 'function' ? tsickleCtorParams() : tsickleCtorParams; const paramTypes = ctorParameters.map((ctorParam: any) => ctorParam && ctorParam.type); const paramAnnotations = ctorParameters.map( (ctorParam: any) => diff --git a/modules/@angular/core/test/reflection/reflector_spec.ts b/modules/@angular/core/test/reflection/reflector_spec.ts index abbf9fe05b..410cda3643 100644 --- a/modules/@angular/core/test/reflection/reflector_spec.ts +++ b/modules/@angular/core/test/reflection/reflector_spec.ts @@ -89,6 +89,25 @@ export function main() { const p = reflector.parameters(ClassWithoutDecorators); expect(p.length).toEqual(2); }); + + // See https://github.com/angular/tsickle/issues/261 + it('should read forwardRef down-leveled type', () => { + class Dep {} + class ForwardLegacy { + constructor(d: Dep) {} + // Older tsickle had a bug: wrote a forward reference + static ctorParameters = [{type: Dep}]; + } + expect(reflector.parameters(ForwardLegacy)).toEqual([[Dep]]); + class Forward { + constructor(d: Dep) {} + // Newer tsickle generates a functionClosure + static ctorParameters = () => [{type: ForwardDep}]; + } + class ForwardDep {} + expect(reflector.parameters(Forward)).toEqual([[ForwardDep]]); + }); + }); describe('propMetadata', () => {