fix(core): make decorators closure safe (#16905)

This is required as e.g. `token` from `@Inject` is
accessed in string form via makeParamDecorator
but as a property in the `ReflectiveInjector`.

Closes #16889 as this is a more general fix.
This commit is contained in:
Tobias Bosch
2017-05-23 10:52:40 -07:00
committed by Chuck Jazdzewski
parent 5af143e8e4
commit a80ac0a8d3
9 changed files with 76 additions and 122 deletions

View File

@ -29,10 +29,11 @@ interface PropDecorator {
}
/** @Annotation */ const ClassDecorator =
<ClassDecoratorFactory>makeDecorator('ClassDecorator', {value: undefined});
<ClassDecoratorFactory>makeDecorator('ClassDecorator', (data: any) => data);
/** @Annotation */ const ParamDecorator =
makeParamDecorator('ParamDecorator', [['value', undefined]]);
/** @Annotation */ const PropDecorator = makePropDecorator('PropDecorator', [['value', undefined]]);
makeParamDecorator('ParamDecorator', (value: any) => ({value}));
/** @Annotation */ const PropDecorator =
makePropDecorator('PropDecorator', (value: any) => ({value}));
class AType {
constructor(public value: any) {}

View File

@ -17,14 +17,15 @@ class DecoratedChild extends DecoratedParent {}
export function main() {
const Reflect = global['Reflect'];
const TerminalDecorator = makeDecorator('TerminalDecorator', {terminal: true});
const TerminalDecorator =
makeDecorator('TerminalDecorator', (data: any) => ({terminal: true, ...data}));
const TestDecorator = makeDecorator(
'TestDecorator', {marker: undefined}, Object, (fn: any) => fn.Terminal = TerminalDecorator);
'TestDecorator', (data: any) => data, 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]]);
const Prop = makePropDecorator('Prop', (value: any) => ({value}));
class TestClass {
@Prop('firefox!')
@ -36,13 +37,14 @@ export function main() {
});
it('should work with any default plain values', () => {
const Default = makePropDecorator('Default', [['value', 5]]);
const Default =
makePropDecorator('Default', (data: any) => ({value: data != null ? data : 5}));
expect(new Default(0)['value']).toEqual(0);
});
it('should work with any object values', () => {
// make sure we don't walk up the prototype chain
const Default = makePropDecorator('Default', [{value: 5}]);
const Default = makePropDecorator('Default', (data: any) => ({value: 5, ...data}));
const value = Object.create({value: 10});
expect(new Default(value)['value']).toEqual(5);
});