refactor(core): add a name to all decorators and other fixes

This commit is contained in:
Tobias Bosch 2016-09-12 20:30:42 -07:00 committed by Igor Minar
parent cc2873a94d
commit 42d442dcd5
12 changed files with 72 additions and 65 deletions

View File

@ -47,7 +47,7 @@ export class ReflectorHost implements StaticReflectorHost, ImportGenerator {
angularImportLocations() { angularImportLocations() {
return { return {
coreDecorators: '@angular/core/src/metadata', coreDecorators: '@angular/core/src/metadata',
diDecorators: '@angular/core/src/di/decorators', diDecorators: '@angular/core/src/di/metadata',
diMetadata: '@angular/core/src/di/metadata', diMetadata: '@angular/core/src/di/metadata',
diOpaqueToken: '@angular/core/src/di/opaque_token', diOpaqueToken: '@angular/core/src/di/opaque_token',
animationMetadata: '@angular/core/src/animation/metadata', animationMetadata: '@angular/core/src/animation/metadata',

View File

@ -125,7 +125,7 @@ describe('reflector_host', () => {
let {coreDecorators, diDecorators, diMetadata, animationMetadata, provider} = let {coreDecorators, diDecorators, diMetadata, animationMetadata, provider} =
reflectorNestedGenDir.angularImportLocations(); reflectorNestedGenDir.angularImportLocations();
expect(coreDecorators).toEqual('@angular/core/src/metadata'); expect(coreDecorators).toEqual('@angular/core/src/metadata');
expect(diDecorators).toEqual('@angular/core/src/di/decorators'); expect(diDecorators).toEqual('@angular/core/src/di/metadata');
expect(diMetadata).toEqual('@angular/core/src/di/metadata'); expect(diMetadata).toEqual('@angular/core/src/di/metadata');
expect(animationMetadata).toEqual('@angular/core/src/animation/metadata'); expect(animationMetadata).toEqual('@angular/core/src/animation/metadata');
expect(provider).toEqual('@angular/core/src/di/provider'); expect(provider).toEqual('@angular/core/src/di/provider');

View File

@ -444,7 +444,7 @@ class MockReflectorHost implements StaticReflectorHost {
angularImportLocations() { angularImportLocations() {
return { return {
coreDecorators: 'angular2/src/core/metadata', coreDecorators: 'angular2/src/core/metadata',
diDecorators: 'angular2/src/core/di/decorators', diDecorators: 'angular2/src/core/di/metadata',
diMetadata: 'angular2/src/core/di/metadata', diMetadata: 'angular2/src/core/di/metadata',
diOpaqueToken: 'angular2/src/core/di/opaque_token', diOpaqueToken: 'angular2/src/core/di/opaque_token',
animationMetadata: 'angular2/src/core/animation/metadata', animationMetadata: 'angular2/src/core/animation/metadata',

View File

@ -74,7 +74,7 @@ export interface Inject { token: any; }
* @stable * @stable
* @Annotation * @Annotation
*/ */
export const Inject: InjectDecorator = makeParamDecorator([['token', undefined]]); export const Inject: InjectDecorator = makeParamDecorator('Inject', [['token', undefined]]);
/** /**
@ -122,7 +122,7 @@ export interface Optional {}
* @stable * @stable
* @Annotation * @Annotation
*/ */
export const Optional: OptionalDecorator = makeParamDecorator([]); export const Optional: OptionalDecorator = makeParamDecorator('Optional', []);
/** /**
* Type of the Injectable decorator / constructor function. * Type of the Injectable decorator / constructor function.
@ -179,7 +179,7 @@ export interface Injectable {}
* @stable * @stable
* @Annotation * @Annotation
*/ */
export const Injectable: InjectableDecorator = makeParamDecorator([]); export const Injectable: InjectableDecorator = makeParamDecorator('Injectable', []);
/** /**
* Type of the Self decorator / constructor function. * Type of the Self decorator / constructor function.
@ -232,7 +232,7 @@ export interface Self {}
* @stable * @stable
* @Annotation * @Annotation
*/ */
export const Self: SelfDecorator = makeParamDecorator([]); export const Self: SelfDecorator = makeParamDecorator('Self', []);
/** /**
@ -284,7 +284,7 @@ export interface SkipSelf {}
* @stable * @stable
* @Annotation * @Annotation
*/ */
export const SkipSelf: SkipSelfDecorator = makeParamDecorator([]); export const SkipSelf: SkipSelfDecorator = makeParamDecorator('SkipSelf', []);
/** /**
* Type of the Host decorator / constructor function. * Type of the Host decorator / constructor function.
@ -362,4 +362,4 @@ export interface Host {}
* @stable * @stable
* @Annotation * @Annotation
*/ */
export const Host: HostDecorator = makeParamDecorator([]); export const Host: HostDecorator = makeParamDecorator('Host', []);

View File

@ -122,7 +122,8 @@ export interface Attribute { attributeName?: string; }
* @stable * @stable
* @Annotation * @Annotation
*/ */
export const Attribute: AttributeDecorator = makeParamDecorator([['attributeName', undefined]]); export const Attribute: AttributeDecorator =
makeParamDecorator('Attribute', [['attributeName', undefined]]);
/** /**
* Type of the Query metadata. * Type of the Query metadata.
@ -192,6 +193,7 @@ export type ContentChildren = Query;
* @Annotation * @Annotation
*/ */
export const ContentChildren: ContentChildrenDecorator = makePropDecorator( export const ContentChildren: ContentChildrenDecorator = makePropDecorator(
'ContentChildren',
[ [
['selector', undefined], ['selector', undefined],
{first: false, isViewQuery: false, descendants: false, read: undefined} {first: false, isViewQuery: false, descendants: false, read: undefined}
@ -251,6 +253,7 @@ export type ContentChild = Query;
* @Annotation * @Annotation
*/ */
export const ContentChild: ContentChildDecorator = makePropDecorator( export const ContentChild: ContentChildDecorator = makePropDecorator(
'ContentChild',
[ [
['selector', undefined], { ['selector', undefined], {
first: true, first: true,
@ -362,6 +365,7 @@ export type ViewChildren = Query;
* @Annotation * @Annotation
*/ */
export const ViewChildren: ViewChildrenDecorator = makePropDecorator( export const ViewChildren: ViewChildrenDecorator = makePropDecorator(
'ViewChildren',
[ [
['selector', undefined], { ['selector', undefined], {
first: false, first: false,
@ -467,6 +471,7 @@ export type ViewChild = Query;
* @Annotation * @Annotation
*/ */
export const ViewChild: ViewChildDecorator = makePropDecorator( export const ViewChild: ViewChildDecorator = makePropDecorator(
'ViewChild',
[ [
['selector', undefined], { ['selector', undefined], {
first: true, first: true,

View File

@ -770,7 +770,7 @@ export interface Directive {
* @stable * @stable
* @Annotation * @Annotation
*/ */
export const Directive: DirectiveDecorator = <DirectiveDecorator>makeDecorator({ export const Directive: DirectiveDecorator = <DirectiveDecorator>makeDecorator('Directive', {
selector: undefined, selector: undefined,
inputs: undefined, inputs: undefined,
outputs: undefined, outputs: undefined,
@ -1051,7 +1051,7 @@ export interface Component extends Directive {
* @Annotation * @Annotation
*/ */
export const Component: ComponentDecorator = <ComponentDecorator>makeDecorator( export const Component: ComponentDecorator = <ComponentDecorator>makeDecorator(
{ 'Component', {
selector: undefined, selector: undefined,
inputs: undefined, inputs: undefined,
outputs: undefined, outputs: undefined,
@ -1110,7 +1110,7 @@ export interface Pipe {
* @stable * @stable
* @Annotation * @Annotation
*/ */
export const Pipe: PipeDecorator = <PipeDecorator>makeDecorator({ export const Pipe: PipeDecorator = <PipeDecorator>makeDecorator('Pipe', {
name: undefined, name: undefined,
pure: true, pure: true,
}); });
@ -1184,7 +1184,8 @@ export interface Input {
* @stable * @stable
* @Annotation * @Annotation
*/ */
export const Input: InputDecorator = makePropDecorator([['bindingPropertyName', undefined]]); export const Input: InputDecorator =
makePropDecorator('Input', [['bindingPropertyName', undefined]]);
/** /**
* Type of the Output decorator / constructor function. * Type of the Output decorator / constructor function.
@ -1249,7 +1250,8 @@ export interface Output { bindingPropertyName?: string; }
* @stable * @stable
* @Annotation * @Annotation
*/ */
export const Output: OutputDecorator = makePropDecorator([['bindingPropertyName', undefined]]); export const Output: OutputDecorator =
makePropDecorator('Output', [['bindingPropertyName', undefined]]);
/** /**
@ -1310,7 +1312,7 @@ export interface HostBinding { hostPropertyName?: string; }
* @Annotation * @Annotation
*/ */
export const HostBinding: HostBindingDecorator = export const HostBinding: HostBindingDecorator =
makePropDecorator([['hostPropertyName', undefined]]); makePropDecorator('HostBinding', [['hostPropertyName', undefined]]);
/** /**
@ -1374,4 +1376,4 @@ export interface HostListener {
* @Annotation * @Annotation
*/ */
export const HostListener: HostListenerDecorator = export const HostListener: HostListenerDecorator =
makePropDecorator([['eventName', undefined], ['args', []]]); makePropDecorator('HostListener', [['eventName', undefined], ['args', []]]);

View File

@ -191,7 +191,7 @@ export interface NgModule {
* @stable * @stable
* @Annotation * @Annotation
*/ */
export const NgModule: NgModuleDecorator = <NgModuleDecorator>makeDecorator({ export const NgModule: NgModuleDecorator = <NgModuleDecorator>makeDecorator('NgModule', {
providers: undefined, providers: undefined,
declarations: undefined, declarations: undefined,
imports: undefined, imports: undefined,

View File

@ -182,11 +182,9 @@ function convertTsickleDecoratorIntoMetadata(decoratorInvocations: any[]): any[]
return []; return [];
} }
return decoratorInvocations.map(decoratorInvocation => { return decoratorInvocations.map(decoratorInvocation => {
var decoratorType = decoratorInvocation.type; const decoratorType = decoratorInvocation.type;
var annotationCls = decoratorType.annotationCls; const annotationCls = decoratorType.annotationCls;
var annotationArgs = decoratorInvocation.args ? decoratorInvocation.args : []; const annotationArgs = decoratorInvocation.args ? decoratorInvocation.args : [];
var annotation = Object.create(annotationCls.prototype); return new annotationCls(...annotationArgs);
annotationCls.apply(annotation, annotationArgs);
return annotation;
}); });
} }

View File

@ -252,19 +252,20 @@ export function Class(clsDef: ClassDefinition): Type<any> {
var Reflect = global.Reflect; var Reflect = global.Reflect;
export function makeDecorator( export function makeDecorator(
props: {[key: string]: any}, parentClass?: any, name: string, props: {[key: string]: any}, parentClass?: any,
chainFn: (fn: Function) => void = null): (...args: any[]) => (cls: any) => any { chainFn: (fn: Function) => void = null): (...args: any[]) => (cls: any) => any {
const annotationCls = makeMetadataClass([props], parentClass); const metaCtor = makeMetadataCtor([props]);
function DecoratorFactory(objOrType: any): (cls: any) => any { function DecoratorFactory(objOrType: any): (cls: any) => any {
if (!(Reflect && Reflect.getMetadata)) { if (!(Reflect && Reflect.getMetadata)) {
throw 'reflect-metadata shim is required when using class decorators'; throw 'reflect-metadata shim is required when using class decorators';
} }
const annotationInstance = new (<any>annotationCls)(objOrType); if (this instanceof DecoratorFactory) {
if (this instanceof annotationCls) { metaCtor.call(this, objOrType);
return annotationInstance; return this;
} else { } else {
const annotationInstance = new (<any>DecoratorFactory)(objOrType);
const chainAnnotation = const chainAnnotation =
isFunction(this) && this.annotations instanceof Array ? this.annotations : []; isFunction(this) && this.annotations instanceof Array ? this.annotations : [];
chainAnnotation.push(annotationInstance); chainAnnotation.push(annotationInstance);
@ -280,13 +281,15 @@ export function makeDecorator(
return TypeDecorator; return TypeDecorator;
} }
} }
DecoratorFactory.prototype = annotationCls.prototype; if (parentClass) {
(<any>DecoratorFactory).annotationCls = annotationCls; DecoratorFactory.prototype = Object.create(parentClass.prototype);
}
DecoratorFactory.prototype.toString = () => `@${name}`;
(<any>DecoratorFactory).annotationCls = DecoratorFactory;
return DecoratorFactory; return DecoratorFactory;
} }
function makeMetadataClass( function makeMetadataCtor(props: ([string, any] | {[key: string]: any})[]): any {
props: ([string, any] | {[key: string]: any})[], parentClass?: any): any {
function ctor(...args: any[]) { function ctor(...args: any[]) {
props.forEach((prop, i) => { props.forEach((prop, i) => {
const argVal = args[i]; const argVal = args[i];
@ -302,24 +305,18 @@ function makeMetadataClass(
} }
}); });
} }
if (parentClass) {
ctor.prototype = Object.create(parentClass.prototype);
}
return ctor; return ctor;
} }
export function makeParamDecorator( export function makeParamDecorator(
props: ([string, any] | {[key: string]: any})[], parentClass?: any): any { name: string, props: ([string, any] | {[key: string]: any})[], parentClass?: any): any {
const annotationCls = makeMetadataClass(props, parentClass); const metaCtor = makeMetadataCtor(props);
function ParamDecoratorFactory(...args: any[]): any { function ParamDecoratorFactory(...args: any[]): any {
let annotationInstance = Object.create(annotationCls.prototype); if (this instanceof ParamDecoratorFactory) {
annotationCls.apply(annotationInstance, args); metaCtor.apply(this, args);
return this;
if (this instanceof annotationCls) {
return annotationInstance;
} }
const annotationInstance = new (<any>ParamDecoratorFactory)(...args);
(<any>ParamDecorator).annotation = annotationInstance; (<any>ParamDecorator).annotation = annotationInstance;
return ParamDecorator; return ParamDecorator;
@ -341,21 +338,23 @@ export function makeParamDecorator(
return cls; return cls;
} }
} }
ParamDecoratorFactory.prototype = annotationCls.prototype; if (parentClass) {
(<any>ParamDecoratorFactory).annotationCls = annotationCls; ParamDecoratorFactory.prototype = Object.create(parentClass.prototype);
}
ParamDecoratorFactory.prototype.toString = () => `@${name}`;
(<any>ParamDecoratorFactory).annotationCls = ParamDecoratorFactory;
return ParamDecoratorFactory; return ParamDecoratorFactory;
} }
export function makePropDecorator( export function makePropDecorator(
props: ([string, any] | {[key: string]: any})[], parentClass?: any): any { name: string, props: ([string, any] | {[key: string]: any})[], parentClass?: any): any {
const annotationCls = makeMetadataClass(props, parentClass); const metaCtor = makeMetadataCtor(props);
function PropDecoratorFactory(...args: any[]): any { function PropDecoratorFactory(...args: any[]): any {
var decoratorInstance = Object.create(annotationCls.prototype); if (this instanceof PropDecoratorFactory) {
annotationCls.apply(decoratorInstance, args); metaCtor.apply(this, args);
return this;
if (this instanceof annotationCls) {
return decoratorInstance;
} else { } else {
var decoratorInstance = new (<any>PropDecoratorFactory)(...args);
return function PropDecorator(target: any, name: string) { return function PropDecorator(target: any, name: string) {
const meta = Reflect.getOwnMetadata('propMetadata', target.constructor) || {}; const meta = Reflect.getOwnMetadata('propMetadata', target.constructor) || {};
meta[name] = meta[name] || []; meta[name] = meta[name] || [];
@ -364,7 +363,10 @@ export function makePropDecorator(
}; };
} }
} }
PropDecoratorFactory.prototype = annotationCls.prototype; if (parentClass) {
(<any>PropDecoratorFactory).annotationCls = annotationCls; PropDecoratorFactory.prototype = Object.create(parentClass.prototype);
}
PropDecoratorFactory.prototype.toString = () => `@${name}`;
(<any>PropDecoratorFactory).annotationCls = PropDecoratorFactory;
return PropDecoratorFactory; return PropDecoratorFactory;
} }

View File

@ -32,9 +32,11 @@ export function propDecorator(value: any /** TODO #9100 */) {
} }
/** @Annotation */ export const ClassDecorator = /** @Annotation */ export const ClassDecorator =
<ClassDecoratorFactory>makeDecorator({value: undefined}); <ClassDecoratorFactory>makeDecorator('ClassDecorator', {value: undefined});
/** @Annotation */ export const ParamDecorator = makeParamDecorator([['value', undefined]]); /** @Annotation */ export const ParamDecorator =
/** @Annotation */ export const PropDecorator = makePropDecorator([['value', undefined]]); makeParamDecorator('ParamDecorator', [['value', undefined]]);
/** @Annotation */ export const PropDecorator =
makePropDecorator('PropDecorator', [['value', undefined]]);
// used only in Dart // used only in Dart
export class HasGetterAndSetterDecorators {} export class HasGetterAndSetterDecorators {}

View File

@ -19,9 +19,9 @@ class DecoratedChild extends DecoratedParent {}
export function main() { export function main() {
var Reflect = global.Reflect; var Reflect = global.Reflect;
var TerminalDecorator = makeDecorator({terminal: true}); var TerminalDecorator = makeDecorator('TerminalDecorator', {terminal: true});
var TestDecorator = var TestDecorator = makeDecorator(
makeDecorator({marker: undefined}, Object, (fn: any) => fn.Terminal = TerminalDecorator); 'TestDecorator', {marker: undefined}, Object, (fn: any) => fn.Terminal = TerminalDecorator);
describe('decorators', () => { describe('decorators', () => {
it('should invoke as decorator', () => { it('should invoke as decorator', () => {

View File

@ -11,7 +11,5 @@ export function getTypeOf(instance: any /** TODO #9100 */) {
} }
export function instantiateType(type: Function, params: any[] = []) { export function instantiateType(type: Function, params: any[] = []) {
var instance = Object.create(type.prototype); return new (<any>type)(...params);
instance.constructor.apply(instance, params);
return instance;
} }