diff --git a/modules/@angular/compiler/src/runtime_compiler.ts b/modules/@angular/compiler/src/runtime_compiler.ts
index 504eab0074..8275c27cfa 100644
--- a/modules/@angular/compiler/src/runtime_compiler.ts
+++ b/modules/@angular/compiler/src/runtime_compiler.ts
@@ -115,7 +115,9 @@ export class RuntimeCompiler implements ComponentResolver {
this._metadataResolver.getViewDirectivesMetadata(dep.comp.type.runtime);
var childViewPipes: CompilePipeMetadata[] =
this._metadataResolver.getViewPipesMetadata(dep.comp.type.runtime);
- var childIsRecursive = ListWrapper.contains(childCompilingComponentsPath, childCacheKey);
+ var childIsRecursive = childCompilingComponentsPath.indexOf(childCacheKey) > -1 ||
+ childViewDirectives.some(
+ dir => childCompilingComponentsPath.indexOf(dir.type.runtime) > -1);
childCompilingComponentsPath.push(childCacheKey);
var childComp = this._loadAndCompileComponent(
diff --git a/modules/@angular/core/test/linker/regression_integration_spec.ts b/modules/@angular/core/test/linker/regression_integration_spec.ts
index 71eb42383b..5de0418b86 100644
--- a/modules/@angular/core/test/linker/regression_integration_spec.ts
+++ b/modules/@angular/core/test/linker/regression_integration_spec.ts
@@ -4,7 +4,7 @@ import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
import {IS_DART} from '../../src/facade/lang';
-import {Component, Pipe, PipeTransform, provide, ViewMetadata, OpaqueToken, Injector} from '@angular/core';
+import {Component, Pipe, PipeTransform, provide, ViewMetadata, PLATFORM_PIPES, OpaqueToken, Injector, forwardRef} from '@angular/core';
import {NgIf, NgClass} from '@angular/common';
import {CompilerConfig} from '@angular/compiler';
@@ -162,8 +162,7 @@ function declareTests({useJit}: {useJit: boolean}) {
it('should support ngClass before a component and content projection inside of an ngIf',
inject(
- [TestComponentBuilder, AsyncTestCompleter],
- (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
+ [TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: any) => {
tcb.overrideView(
MyComp1, new ViewMetadata({
template: `ABC`,
@@ -177,6 +176,15 @@ function declareTests({useJit}: {useJit: boolean}) {
});
}));
+ it('should handle mutual recursion entered from multiple sides - #7084',
+ inject(
+ [TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: any) => {
+ tcb.createAsync(FakeRecursiveComp).then((fixture) => {
+ fixture.detectChanges();
+ expect(fixture.nativeElement).toHaveText('[]');
+ async.done();
+ });
+ }));
});
}
@@ -199,3 +207,37 @@ class CustomPipe implements PipeTransform {
@Component({selector: 'cmp-content', template: ``})
class CmpWithNgContent {
}
+
+@Component({
+ selector: 'left',
+ template: `L`,
+ directives: [
+ NgIf,
+ forwardRef(() => RightComp),
+ ]
+})
+class LeftComp {
+}
+
+@Component({
+ selector: 'right',
+ template: `R`,
+ directives: [
+ NgIf,
+ forwardRef(() => LeftComp),
+ ]
+})
+class RightComp {
+}
+
+@Component({
+ selector: 'fakeRecursiveComp',
+ template: `[]`,
+ directives: [
+ NgIf,
+ forwardRef(() => LeftComp),
+ forwardRef(() => RightComp),
+ ]
+})
+export class FakeRecursiveComp {
+}