From e64b54b67b1b7dfc3a72c8b1e52cf061069e6194 Mon Sep 17 00:00:00 2001 From: Chuck Jazdzewski Date: Fri, 28 Jul 2017 15:48:59 -0700 Subject: [PATCH] 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 --- packages/compiler/src/aot/static_reflector.ts | 2 +- .../test/aot/static_reflector_spec.ts | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/packages/compiler/src/aot/static_reflector.ts b/packages/compiler/src/aot/static_reflector.ts index 5a9a74ed2b..d5e465657b 100644 --- a/packages/compiler/src/aot/static_reflector.ts +++ b/packages/compiler/src/aot/static_reflector.ts @@ -376,7 +376,6 @@ export class StaticReflector implements CompileReflector { if (calling.get(functionSymbol)) { throw new Error('Recursion not supported'); } - calling.set(functionSymbol, true); try { const value = targetFunction['value']; if (value && (depth != 0 || value.__symbolic != 'error')) { @@ -387,6 +386,7 @@ export class StaticReflector implements CompileReflector { if (defaults && defaults.length > args.length) { args.push(...defaults.slice(args.length).map((value: any) => simplify(value))); } + calling.set(functionSymbol, true); const functionScope = BindingScope.build(); for (let i = 0; i < parameters.length; i++) { functionScope.define(parameters[i], args[i]); diff --git a/packages/compiler/test/aot/static_reflector_spec.ts b/packages/compiler/test/aot/static_reflector_spec.ts index 8d72f75166..c594c15a30 100644 --- a/packages/compiler/test/aot/static_reflector_spec.ts +++ b/packages/compiler/test/aot/static_reflector_spec.ts @@ -462,6 +462,20 @@ describe('StaticReflector', () => { 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 it('should not throw on unknown decorators', () => { const data = Object.create(DEFAULT_TEST_DATA); @@ -1392,6 +1406,25 @@ const DEFAULT_TEST_DATA: {[key: string]: any} = { 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': ` import {Component} from '@angular/core'; import {MyModule} from './static-field';