fix(tsickle): support ctorParams in function closure (#12876)

See https://github.com/angular/tsickle/issues/261 for context.
This commit is contained in:
Alex Eagle 2016-11-15 09:19:00 -08:00 committed by Victor Berchet
parent 46d150266b
commit 75277cd94b
4 changed files with 45 additions and 4 deletions

View File

@ -132,7 +132,6 @@ export class StaticReflector implements ReflectorReader {
const ctor = (<any[]>ctorData).find(a => a['__symbolic'] == 'constructor');
const parameterTypes = <any[]>this.simplify(type, ctor['parameters'] || []);
const parameterDecorators = <any[]>this.simplify(type, ctor['parameterDecorators'] || []);
parameters = [];
parameterTypes.forEach((paramType, index) => {
const nestedResult: any[] = [];

View File

@ -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;
}
`
};

View File

@ -56,8 +56,12 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
}
// API of tsickle for lowering decorators to properties on the class.
if ((<any>type).ctorParameters) {
const ctorParameters = (<any>type).ctorParameters;
const tsickleCtorParams = (<any>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) =>

View File

@ -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', () => {