fix(compiler): don’t throw when using `ANALYZE_FOR_ENTRY_COMPONENTS` with user classes (#13679)
Fixed #13565
This commit is contained in:
parent
b2ae7b607e
commit
7690d02133
|
@ -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';
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
@ -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}]);
|
||||
|
@ -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', () => {
|
||||
|
|
|
@ -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'})]);
|
||||
|
||||
|
@ -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', () => {
|
||||
|
@ -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')]
|
||||
|
@ -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', () => {
|
||||
|
@ -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')],
|
||||
|
@ -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', () => {
|
||||
|
|
Loading…
Reference in New Issue