fix(compiler): avoid evaluating arguments to unknown decorators

Fixes #13605
This commit is contained in:
Chuck Jazdzewski 2017-01-05 15:22:38 -08:00 committed by Matias Niemelä
parent 6d29faefea
commit d061adc02d
2 changed files with 38 additions and 3 deletions

View File

@ -322,6 +322,7 @@ export class StaticReflector implements ReflectorReader {
if (value && (depth != 0 || value.__symbolic != 'error')) { if (value && (depth != 0 || value.__symbolic != 'error')) {
const parameters: string[] = targetFunction['parameters']; const parameters: string[] = targetFunction['parameters'];
const defaults: any[] = targetFunction.defaults; const defaults: any[] = targetFunction.defaults;
args = args.map(arg => simplifyInContext(context, arg, depth + 1));
if (defaults && defaults.length > args.length) { if (defaults && defaults.length > args.length) {
args.push(...defaults.slice(args.length).map((value: any) => simplify(value))); args.push(...defaults.slice(args.length).map((value: any) => simplify(value)));
} }
@ -511,15 +512,15 @@ export class StaticReflector implements ReflectorReader {
return context; return context;
} }
const argExpressions: any[] = expression['arguments'] || []; const argExpressions: any[] = expression['arguments'] || [];
const args =
argExpressions.map(arg => simplifyInContext(context, arg, depth + 1));
let converter = self.conversionMap.get(staticSymbol); let converter = self.conversionMap.get(staticSymbol);
if (converter) { if (converter) {
const args =
argExpressions.map(arg => simplifyInContext(context, arg, depth + 1));
return converter(context, args); return converter(context, args);
} else { } else {
// Determine if the function is one we can simplify. // Determine if the function is one we can simplify.
const targetFunction = resolveReferenceValue(staticSymbol); const targetFunction = resolveReferenceValue(staticSymbol);
return simplifyCall(staticSymbol, targetFunction, args); return simplifyCall(staticSymbol, targetFunction, argExpressions);
} }
} }
break; break;

View File

@ -449,6 +449,40 @@ describe('StaticReflector', () => {
expect(annotations[0].providers[0].useValue.members[0]).toEqual('staticMethod'); expect(annotations[0].providers[0].useValue.members[0]).toEqual('staticMethod');
}); });
// #13605
it('should not throw on unknown decorators', () => {
const data = Object.create(DEFAULT_TEST_DATA);
const file = '/tmp/src/app.component.ts';
data[file] = `
import { Component } from '@angular/core';
export const enum TypeEnum {
type
}
export function MyValidationDecorator(p1: any, p2: any): any {
return null;
}
export function ValidationFunction(a1: any): any {
return null;
}
@Component({
selector: 'my-app',
template: "<h1>Hello {{name}}</h1>",
})
export class AppComponent {
name = 'Angular';
@MyValidationDecorator( TypeEnum.type, ValidationFunction({option: 'value'}))
myClassProp: number;
}`;
init(data);
const appComponent = reflector.getStaticSymbol(file, 'AppComponent');
expect(() => reflector.propMetadata(appComponent)).not.toThrow();
});
describe('inheritance', () => { describe('inheritance', () => {
class ClassDecorator { class ClassDecorator {
constructor(public value: any) {} constructor(public value: any) {}