Skip to content

Commit

Permalink
fix(compiler): don’t throw when using ANALYZE_FOR_ENTRY_COMPONENTS
Browse files Browse the repository at this point in the history
…with user classes (#13679)

Fixed #13565
  • Loading branch information
tbosch authored and IgorMinar committed Jan 6, 2017
1 parent ec0ca01 commit 230e33f
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 6 deletions.
25 changes: 21 additions & 4 deletions modules/@angular/core/src/reflection/reflection_capabilities.ts
Expand Up @@ -7,7 +7,7 @@
*/

import {global, isPresent, stringify} from '../facade/lang';
import {Type} from '../type';
import {Type, isType} from '../type';

import {PlatformReflectionCapabilities} from './platform_reflection_capabilities';
import {GetterFn, MethodFn, SetterFn} from './types';
Expand Down Expand Up @@ -105,7 +105,10 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
parameters(type: Type<any>): any[][] {
// Note: only report metadata if we have at least one class decorator
// to stay in sync with the static reflector.
const parentCtor = Object.getPrototypeOf(type.prototype).constructor;
if (!isType(type)) {
return [];
}
const parentCtor = getParentCtor(type);
let parameters = this._ownParameters(type, parentCtor);
if (!parameters && parentCtor !== Object) {
parameters = this.parameters(parentCtor);
Expand Down Expand Up @@ -135,7 +138,10 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
}

annotations(typeOrFunc: Type<any>): any[] {
const parentCtor = Object.getPrototypeOf(typeOrFunc.prototype).constructor;
if (!isType(typeOrFunc)) {
return [];
}
const parentCtor = getParentCtor(typeOrFunc);
const ownAnnotations = this._ownAnnotations(typeOrFunc, parentCtor) || [];
const parentAnnotations = parentCtor !== Object ? this.annotations(parentCtor) : [];
return parentAnnotations.concat(ownAnnotations);
Expand Down Expand Up @@ -170,7 +176,10 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
}

propMetadata(typeOrFunc: any): {[key: string]: any[]} {
const parentCtor = Object.getPrototypeOf(typeOrFunc.prototype).constructor;
if (!isType(typeOrFunc)) {
return {};
}
const parentCtor = getParentCtor(typeOrFunc);
const propMetadata: {[key: string]: any[]} = {};
if (parentCtor !== Object) {
const parentPropMetadata = this.propMetadata(parentCtor);
Expand Down Expand Up @@ -233,3 +242,11 @@ function convertTsickleDecoratorIntoMetadata(decoratorInvocations: any[]): any[]
return new annotationCls(...annotationArgs);
});
}

function getParentCtor(ctor: Function): Type<any> {
const parentProto = Object.getPrototypeOf(ctor.prototype);
const parentCtor = parentProto ? parentProto.constructor : null;
// Note: We always use `Object` as the null value
// to simplify checking later on.
return parentCtor || Object;
}
3 changes: 3 additions & 0 deletions modules/@angular/core/src/type.ts
Expand Up @@ -18,5 +18,8 @@
*/
export const Type = Function;

export function isType(v: any): v is Type<any> {
return typeof v === 'function';
}

export interface Type<T> extends Function { new (...args: any[]): T; }
20 changes: 18 additions & 2 deletions modules/@angular/core/test/linker/regression_integration_spec.ts
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {Component, Injector, OpaqueToken, Pipe, PipeTransform, Provider} from '@angular/core';
import {ANALYZE_FOR_ENTRY_COMPONENTS, Component, Injector, OpaqueToken, Pipe, PipeTransform, Provider} from '@angular/core';
import {TestBed} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/matchers';

Expand Down Expand Up @@ -119,7 +119,7 @@ function declareTests({useJit}: {useJit: boolean}) {
expect(injector.get(token)).toEqual(tokenValue);
});

it('should support providers with an anonymous function', () => {
it('should support providers with an anonymous function as token', () => {
const token = () => true;
const tokenValue = 1;
const injector = createInjector([{provide: token, useValue: tokenValue}]);
Expand Down Expand Up @@ -147,6 +147,22 @@ function declareTests({useJit}: {useJit: boolean}) {
const injector = createInjector([{provide: 'someToken', useValue: data}]);
expect(injector.get('someToken')).toEqual(data);
});

describe('ANALYZE_FOR_ENTRY_COMPONENTS providers', () => {

it('should support class instances', () => {
class SomeObject {
someMethod() {}
}

expect(
() => createInjector([
{provide: ANALYZE_FOR_ENTRY_COMPONENTS, useValue: new SomeObject(), multi: true}
]))
.not.toThrow();
});
});

});

it('should allow logging a previous elements class binding via interpolation', () => {
Expand Down
21 changes: 21 additions & 0 deletions modules/@angular/core/test/reflection/reflector_spec.ts
Expand Up @@ -190,6 +190,8 @@ export function main() {

class ChildNoDecorators extends Parent {}

class NoDecorators {}

// Check that metadata for Parent was not changed!
expect(reflector.annotations(Parent)).toEqual([new ClassDecorator({value: 'parent'})]);

Expand All @@ -199,6 +201,11 @@ export function main() {

expect(reflector.annotations(ChildNoDecorators)).toEqual([new ClassDecorator(
{value: 'parent'})]);

expect(reflector.annotations(NoDecorators)).toEqual([]);
expect(reflector.annotations(<any>{})).toEqual([]);
expect(reflector.annotations(<any>1)).toEqual([]);
expect(reflector.annotations(null)).toEqual([]);
});

it('should inherit parameters', () => {
Expand Down Expand Up @@ -226,6 +233,8 @@ export function main() {
constructor(a: any, b: any, c: any) { super(null, null); }
}

class NoDecorators {}

// Check that metadata for Parent was not changed!
expect(reflector.parameters(Parent)).toEqual([
[A, new ParamDecorator('a')], [B, new ParamDecorator('b')]
Expand All @@ -242,6 +251,11 @@ export function main() {
expect(reflector.parameters(ChildWithCtorNoDecorator)).toEqual([
undefined, undefined, undefined
]);

expect(reflector.parameters(NoDecorators)).toEqual([]);
expect(reflector.parameters(<any>{})).toEqual([]);
expect(reflector.parameters(<any>1)).toEqual([]);
expect(reflector.parameters(null)).toEqual([]);
});

it('should inherit property metadata', () => {
Expand All @@ -263,6 +277,8 @@ export function main() {
c: C;
}

class NoDecorators {}

// Check that metadata for Parent was not changed!
expect(reflector.propMetadata(Parent)).toEqual({
'a': [new PropDecorator('a')],
Expand All @@ -274,6 +290,11 @@ export function main() {
'b': [new PropDecorator('b1'), new PropDecorator('b2')],
'c': [new PropDecorator('c')]
});

expect(reflector.propMetadata(NoDecorators)).toEqual({});
expect(reflector.propMetadata(<any>{})).toEqual({});
expect(reflector.propMetadata(<any>1)).toEqual({});
expect(reflector.propMetadata(null)).toEqual({});
});

it('should inherit lifecycle hooks', () => {
Expand Down

0 comments on commit 230e33f

Please sign in to comment.