diff --git a/packages/core/src/reflection/reflection_capabilities.ts b/packages/core/src/reflection/reflection_capabilities.ts index 70d67a5cf9096..57e58c2f18e2b 100644 --- a/packages/core/src/reflection/reflection_capabilities.ts +++ b/packages/core/src/reflection/reflection_capabilities.ts @@ -15,9 +15,12 @@ import {GetterFn, MethodFn, SetterFn} from './types'; /** - * Attention: This regex has to hold even if the code is minified! + * Attention: These regex has to hold even if the code is minified! */ export const DELEGATE_CTOR = /^function\s+\S+\(\)\s*{[\s\S]+\.apply\(this,\s*arguments\)/; +export const INHERITED_CLASS = /^class\s+[A-Za-z\d$_]*\s*extends\s+[A-Za-z\d$_]+\s*{/; +export const INHERITED_CLASS_WITH_CTOR = + /^class\s+[A-Za-z\d$_]*\s*extends\s+[A-Za-z\d$_]+\s*{[\s\S]*constructor\s*\(/; export class ReflectionCapabilities implements PlatformReflectionCapabilities { private _reflect: any; @@ -57,6 +60,7 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities { } private _ownParameters(type: Type, parentCtor: any): any[][]|null { + const typeStr = type.toString(); // If we have no decorators, we only have function.length as metadata. // In that case, to detect whether a child class declared an own constructor or not, // we need to look inside of that constructor to check whether it is @@ -64,7 +68,8 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities { // This also helps to work around for https://github.com/Microsoft/TypeScript/issues/12439 // that sets 'design:paramtypes' to [] // if a class inherits from another class but has no ctor declared itself. - if (DELEGATE_CTOR.exec(type.toString())) { + if (DELEGATE_CTOR.exec(typeStr) || + (INHERITED_CLASS.exec(typeStr) && !INHERITED_CLASS_WITH_CTOR.exec(typeStr))) { return null; } diff --git a/packages/core/test/reflection/reflector_spec.ts b/packages/core/test/reflection/reflector_spec.ts index 7c77e5033a5f9..291a74a815840 100644 --- a/packages/core/test/reflection/reflector_spec.ts +++ b/packages/core/test/reflection/reflector_spec.ts @@ -7,7 +7,7 @@ */ import {Reflector} from '@angular/core/src/reflection/reflection'; -import {DELEGATE_CTOR, ReflectionCapabilities} from '@angular/core/src/reflection/reflection_capabilities'; +import {DELEGATE_CTOR, INHERITED_CLASS, INHERITED_CLASS_WITH_CTOR, ReflectionCapabilities} from '@angular/core/src/reflection/reflection_capabilities'; import {global} from '@angular/core/src/util'; import {makeDecorator, makeParamDecorator, makePropDecorator} from '@angular/core/src/util/decorators'; @@ -188,6 +188,41 @@ class TestObj { Object.defineProperty(dummyArrowFn, 'prototype', {value: undefined}); expect(() => reflector.annotations(dummyArrowFn as any)).not.toThrow(); }); + + it('should support native class', () => { + const ChildNoCtor = `class ChildNoCtor extends Parent {}\n`; + const ChildWithCtor = `class ChildWithCtor extends Parent {\n` + + ` constructor() { super(); }` + + `}\n`; + const ChildNoCtorPrivateProps = `class ChildNoCtorPrivateProps extends Parent {\n` + + ` private x = 10;\n` + + `}\n`; + + const checkNoOwnMetadata = (str: string) => + INHERITED_CLASS.exec(str) && !INHERITED_CLASS_WITH_CTOR.exec(str); + + expect(checkNoOwnMetadata(ChildNoCtor)).toBeTruthy(); + expect(checkNoOwnMetadata(ChildNoCtorPrivateProps)).toBeTruthy(); + expect(checkNoOwnMetadata(ChildWithCtor)).toBeFalsy(); + }); + + it('should properly handle all class forms', () => { + const ctor = (str: string) => expect(INHERITED_CLASS.exec(str)).toBeTruthy() && + expect(INHERITED_CLASS_WITH_CTOR.exec(str)).toBeTruthy(); + const noCtor = (str: string) => expect(INHERITED_CLASS.exec(str)).toBeTruthy() && + expect(INHERITED_CLASS_WITH_CTOR.exec(str)).toBeFalsy(); + + ctor(`class Bar extends Foo {constructor(){}}`); + ctor(`class Bar extends Foo { constructor ( ) {} }`); + ctor(`class Bar extends Foo { other(){}; constructor(){} }`); + + noCtor(`class extends Foo{}`); + noCtor(`class extends Foo {}`); + noCtor(`class Bar extends Foo {}`); + noCtor(`class $Bar1_ extends $Fo0_ {}`); + noCtor(`class Bar extends Foo { other(){} }`); + }); + }); describe('inheritance with decorators', () => {