fix(core): fix property decorators

fixes #12224
This commit is contained in:
Victor Berchet 2016-10-11 19:40:00 -07:00 committed by Igor Minar
parent bf1e2613b2
commit 3993279527
2 changed files with 26 additions and 7 deletions

View File

@ -354,6 +354,7 @@ export function makeParamDecorator(
export function makePropDecorator( export function makePropDecorator(
name: string, props: ([string, any] | {[key: string]: any})[], parentClass?: any): any { name: string, props: ([string, any] | {[key: string]: any})[], parentClass?: any): any {
const metaCtor = makeMetadataCtor(props); const metaCtor = makeMetadataCtor(props);
function PropDecoratorFactory(...args: any[]): any { function PropDecoratorFactory(...args: any[]): any {
if (this instanceof PropDecoratorFactory) { if (this instanceof PropDecoratorFactory) {
metaCtor.apply(this, args); metaCtor.apply(this, args);
@ -361,16 +362,19 @@ export function makePropDecorator(
} }
const decoratorInstance = new (<any>PropDecoratorFactory)(...args); const 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.hasOwnProperty(name) && meta[name] || [];
meta[name].unshift(decoratorInstance); meta[name].unshift(decoratorInstance);
Reflect.defineMetadata('propMetadata', meta, target.constructor); Reflect.defineMetadata('propMetadata', meta, target.constructor);
}; };
} }
if (parentClass) { if (parentClass) {
PropDecoratorFactory.prototype = Object.create(parentClass.prototype); PropDecoratorFactory.prototype = Object.create(parentClass.prototype);
} }
PropDecoratorFactory.prototype.toString = () => `@${name}`; PropDecoratorFactory.prototype.toString = () => `@${name}`;
(<any>PropDecoratorFactory).annotationCls = PropDecoratorFactory; (<any>PropDecoratorFactory).annotationCls = PropDecoratorFactory;
return PropDecoratorFactory; return PropDecoratorFactory;

View File

@ -8,8 +8,7 @@
import {Inject} from '@angular/core'; import {Inject} from '@angular/core';
import {reflector} from '@angular/core/src/reflection/reflection'; import {reflector} from '@angular/core/src/reflection/reflection';
import {Class, makeDecorator} from '@angular/core/src/util/decorators'; import {Class, makeDecorator, makePropDecorator} from '@angular/core/src/util/decorators';
import {describe, expect, it} from '@angular/core/testing/testing_internal';
import {global} from '../../src/facade/lang'; import {global} from '../../src/facade/lang';
@ -23,6 +22,21 @@ export function main() {
const TestDecorator = makeDecorator( const TestDecorator = makeDecorator(
'TestDecorator', {marker: undefined}, Object, (fn: any) => fn.Terminal = TerminalDecorator); 'TestDecorator', {marker: undefined}, Object, (fn: any) => fn.Terminal = TerminalDecorator);
describe('Property decorators', () => {
// https://github.com/angular/angular/issues/12224
it('should work on the "watch" property', () => {
const Prop = makePropDecorator('Prop', [['value', undefined]]);
class TestClass {
@Prop('firefox!')
watch: any;
}
const p = reflector.propMetadata(TestClass);
expect(p['watch']).toEqual([new Prop('firefox!')]);
});
});
describe('decorators', () => { describe('decorators', () => {
it('should invoke as decorator', () => { it('should invoke as decorator', () => {
function Type() {} function Type() {}
@ -64,10 +78,11 @@ export function main() {
constructor: function() {}, constructor: function() {},
extendWorks: function() { return 'extend ' + this.arg; } extendWorks: function() { return 'extend ' + this.arg; }
}), }),
constructor: [String, function(arg: any /** TODO #9100 */) { this.arg = arg; }], constructor: [String, function(arg: any) { this.arg = arg; }],
methodA: [ methodA: [
i0 = new Inject(String), [i1 = Inject(String), Number], i0 = new Inject(String),
function(a: any /** TODO #9100 */, b: any /** TODO #9100 */) {} [i1 = Inject(String), Number],
function(a: any, b: any) {},
], ],
works: function() { return this.arg; }, works: function() { return this.arg; },
prototype: 'IGNORE' prototype: 'IGNORE'