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 {global, isPresent, stringify} from '../facade/lang';
|
||||||
import {Type} from '../type';
|
import {Type, isType} from '../type';
|
||||||
|
|
||||||
import {PlatformReflectionCapabilities} from './platform_reflection_capabilities';
|
import {PlatformReflectionCapabilities} from './platform_reflection_capabilities';
|
||||||
import {GetterFn, MethodFn, SetterFn} from './types';
|
import {GetterFn, MethodFn, SetterFn} from './types';
|
||||||
|
@ -105,7 +105,10 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
|
||||||
parameters(type: Type<any>): any[][] {
|
parameters(type: Type<any>): any[][] {
|
||||||
// Note: only report metadata if we have at least one class decorator
|
// Note: only report metadata if we have at least one class decorator
|
||||||
// to stay in sync with the static reflector.
|
// 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);
|
let parameters = this._ownParameters(type, parentCtor);
|
||||||
if (!parameters && parentCtor !== Object) {
|
if (!parameters && parentCtor !== Object) {
|
||||||
parameters = this.parameters(parentCtor);
|
parameters = this.parameters(parentCtor);
|
||||||
|
@ -135,7 +138,10 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
annotations(typeOrFunc: Type<any>): any[] {
|
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 ownAnnotations = this._ownAnnotations(typeOrFunc, parentCtor) || [];
|
||||||
const parentAnnotations = parentCtor !== Object ? this.annotations(parentCtor) : [];
|
const parentAnnotations = parentCtor !== Object ? this.annotations(parentCtor) : [];
|
||||||
return parentAnnotations.concat(ownAnnotations);
|
return parentAnnotations.concat(ownAnnotations);
|
||||||
|
@ -170,7 +176,10 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
propMetadata(typeOrFunc: any): {[key: string]: any[]} {
|
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[]} = {};
|
const propMetadata: {[key: string]: any[]} = {};
|
||||||
if (parentCtor !== Object) {
|
if (parentCtor !== Object) {
|
||||||
const parentPropMetadata = this.propMetadata(parentCtor);
|
const parentPropMetadata = this.propMetadata(parentCtor);
|
||||||
|
@ -233,3 +242,11 @@ function convertTsickleDecoratorIntoMetadata(decoratorInvocations: any[]): any[]
|
||||||
return new annotationCls(...annotationArgs);
|
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 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; }
|
export interface Type<T> extends Function { new (...args: any[]): T; }
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* 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 {TestBed} from '@angular/core/testing';
|
||||||
import {expect} from '@angular/platform-browser/testing/matchers';
|
import {expect} from '@angular/platform-browser/testing/matchers';
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ function declareTests({useJit}: {useJit: boolean}) {
|
||||||
expect(injector.get(token)).toEqual(tokenValue);
|
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 token = () => true;
|
||||||
const tokenValue = 1;
|
const tokenValue = 1;
|
||||||
const injector = createInjector([{provide: token, useValue: tokenValue}]);
|
const injector = createInjector([{provide: token, useValue: tokenValue}]);
|
||||||
|
@ -147,6 +147,22 @@ function declareTests({useJit}: {useJit: boolean}) {
|
||||||
const injector = createInjector([{provide: 'someToken', useValue: data}]);
|
const injector = createInjector([{provide: 'someToken', useValue: data}]);
|
||||||
expect(injector.get('someToken')).toEqual(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', () => {
|
it('should allow logging a previous elements class binding via interpolation', () => {
|
||||||
|
|
|
@ -190,6 +190,8 @@ export function main() {
|
||||||
|
|
||||||
class ChildNoDecorators extends Parent {}
|
class ChildNoDecorators extends Parent {}
|
||||||
|
|
||||||
|
class NoDecorators {}
|
||||||
|
|
||||||
// Check that metadata for Parent was not changed!
|
// Check that metadata for Parent was not changed!
|
||||||
expect(reflector.annotations(Parent)).toEqual([new ClassDecorator({value: 'parent'})]);
|
expect(reflector.annotations(Parent)).toEqual([new ClassDecorator({value: 'parent'})]);
|
||||||
|
|
||||||
|
@ -199,6 +201,11 @@ export function main() {
|
||||||
|
|
||||||
expect(reflector.annotations(ChildNoDecorators)).toEqual([new ClassDecorator(
|
expect(reflector.annotations(ChildNoDecorators)).toEqual([new ClassDecorator(
|
||||||
{value: 'parent'})]);
|
{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', () => {
|
it('should inherit parameters', () => {
|
||||||
|
@ -226,6 +233,8 @@ export function main() {
|
||||||
constructor(a: any, b: any, c: any) { super(null, null); }
|
constructor(a: any, b: any, c: any) { super(null, null); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class NoDecorators {}
|
||||||
|
|
||||||
// Check that metadata for Parent was not changed!
|
// Check that metadata for Parent was not changed!
|
||||||
expect(reflector.parameters(Parent)).toEqual([
|
expect(reflector.parameters(Parent)).toEqual([
|
||||||
[A, new ParamDecorator('a')], [B, new ParamDecorator('b')]
|
[A, new ParamDecorator('a')], [B, new ParamDecorator('b')]
|
||||||
|
@ -242,6 +251,11 @@ export function main() {
|
||||||
expect(reflector.parameters(ChildWithCtorNoDecorator)).toEqual([
|
expect(reflector.parameters(ChildWithCtorNoDecorator)).toEqual([
|
||||||
undefined, undefined, undefined
|
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', () => {
|
it('should inherit property metadata', () => {
|
||||||
|
@ -263,6 +277,8 @@ export function main() {
|
||||||
c: C;
|
c: C;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class NoDecorators {}
|
||||||
|
|
||||||
// Check that metadata for Parent was not changed!
|
// Check that metadata for Parent was not changed!
|
||||||
expect(reflector.propMetadata(Parent)).toEqual({
|
expect(reflector.propMetadata(Parent)).toEqual({
|
||||||
'a': [new PropDecorator('a')],
|
'a': [new PropDecorator('a')],
|
||||||
|
@ -274,6 +290,11 @@ export function main() {
|
||||||
'b': [new PropDecorator('b1'), new PropDecorator('b2')],
|
'b': [new PropDecorator('b1'), new PropDecorator('b2')],
|
||||||
'c': [new PropDecorator('c')]
|
'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', () => {
|
it('should inherit lifecycle hooks', () => {
|
||||||
|
|
Loading…
Reference in New Issue