fix(compiler): do not consider arguments when determining recursion

The static reflectory check for macro function recursion was too
agressive and disallowed calling a function with argument that also
calls the same function. For example, it disallowed nested animation
groups.

Fixes: #17467
This commit is contained in:
Chuck Jazdzewski 2017-07-28 15:48:59 -07:00 committed by Alex Rickabaugh
parent cc2a4c41f9
commit e64b54b67b
2 changed files with 34 additions and 1 deletions

View File

@ -376,7 +376,6 @@ export class StaticReflector implements CompileReflector {
if (calling.get(functionSymbol)) { if (calling.get(functionSymbol)) {
throw new Error('Recursion not supported'); throw new Error('Recursion not supported');
} }
calling.set(functionSymbol, true);
try { try {
const value = targetFunction['value']; const value = targetFunction['value'];
if (value && (depth != 0 || value.__symbolic != 'error')) { if (value && (depth != 0 || value.__symbolic != 'error')) {
@ -387,6 +386,7 @@ export class StaticReflector implements CompileReflector {
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)));
} }
calling.set(functionSymbol, true);
const functionScope = BindingScope.build(); const functionScope = BindingScope.build();
for (let i = 0; i < parameters.length; i++) { for (let i = 0; i < parameters.length; i++) {
functionScope.define(parameters[i], args[i]); functionScope.define(parameters[i], args[i]);

View File

@ -462,6 +462,20 @@ describe('StaticReflector', () => {
expect(annotations[0].providers[0].useValue.members[0]).toEqual('staticMethod'); expect(annotations[0].providers[0].useValue.members[0]).toEqual('staticMethod');
}); });
it('should be able to get metadata for a class calling a macro function', () => {
const annotations = reflector.annotations(
reflector.getStaticSymbol('/tmp/src/call-macro-function.ts', 'MyComponent'));
expect(annotations.length).toBe(1);
expect(annotations[0].providers.useValue).toBe(100);
});
it('should be able to get metadata for a class calling a nested macro function', () => {
const annotations = reflector.annotations(
reflector.getStaticSymbol('/tmp/src/call-macro-function.ts', 'MyComponentNested'));
expect(annotations.length).toBe(1);
expect(annotations[0].providers.useValue.useValue).toBe(100);
});
// #13605 // #13605
it('should not throw on unknown decorators', () => { it('should not throw on unknown decorators', () => {
const data = Object.create(DEFAULT_TEST_DATA); const data = Object.create(DEFAULT_TEST_DATA);
@ -1392,6 +1406,25 @@ const DEFAULT_TEST_DATA: {[key: string]: any} = {
static VALUE = 'Some string'; static VALUE = 'Some string';
} }
`, `,
'/tmp/src/macro-function.ts': `
export function v(value: any) {
return { provide: 'a', useValue: value };
}
`,
'/tmp/src/call-macro-function.ts': `
import {Component} from '@angular/core';
import {v} from './macro-function';
@Component({
providers: v(100)
})
export class MyComponent { }
@Component({
providers: v(v(100))
})
export class MyComponentNested { }
`,
'/tmp/src/static-field-reference.ts': ` '/tmp/src/static-field-reference.ts': `
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {MyModule} from './static-field'; import {MyModule} from './static-field';