Skip to content

Commit

Permalink
fix(Compiler): relax childIsRecursive check
Browse files Browse the repository at this point in the history
Fix how the compiler checks for recursive components by also considering
component descendants. Previously, it only checked if the current
component was evaluated previously. This failed in certain cases of
mutually recursive components, causing `createAsync` in tests to not
resolve.

closes [7084](angular#7084)
  • Loading branch information
KiaraGrouwstra committed Jun 22, 2016
1 parent 397f5e2 commit 927f6a5
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 17 deletions.
5 changes: 5 additions & 0 deletions modules/@angular/compiler/src/runtime_compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ export class RuntimeCompiler implements ComponentResolver {
var childViewPipes: CompilePipeMetadata[] =
this._metadataResolver.getViewPipesMetadata(dep.comp.type.runtime);
var childIsRecursive = ListWrapper.contains(childCompilingComponentsPath, childCacheKey);
childViewDirectives.map(x => x.type.runtime).forEach(descendant => {
if (ListWrapper.contains(childCompilingComponentsPath, descendant)) {
childIsRecursive = true;
}
});
childCompilingComponentsPath.push(childCacheKey);

var childComp = this._loadAndCompileComponent(
Expand Down
72 changes: 55 additions & 17 deletions modules/@angular/core/test/linker/regression_integration_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -161,22 +161,29 @@ 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) => {
tcb.overrideView(
MyComp1, new ViewMetadata({
template: `A<cmp-content *ngIf="true" [ngClass]="'red'">B</cmp-content>C`,
directives: [NgClass, NgIf, CmpWithNgContent]
}))
.createAsync(MyComp1)
.then((fixture) => {
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('ABC');
async.done();
});
}));

inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideView(
MyComp1, new ViewMetadata({
template: `A<cmp-content *ngIf="true" [ngClass]="'red'">B</cmp-content>C`,
directives: [NgClass, NgIf, CmpWithNgContent]
}))
.createAsync(MyComp1)
.then((fixture) => {
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('ABC');
async.done();
});
}));

it('should handle mutual recursion entered from multiple sides - #7084',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.createAsync(FakeRecursiveComp)
.then((fixture) => {
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('[]');
async.done();
});
}));

});
}
Expand All @@ -199,3 +206,34 @@ class CustomPipe implements PipeTransform {
@Component({selector: 'cmp-content', template: `<ng-content></ng-content>`})
class CmpWithNgContent {
}

@Component({
selector: 'left',
template: `L<right *ngIf="false"></right>`,
directives: [
forwardRef(() => RightComp),
]
})
class LeftComp {
}

@Component({
selector: 'right',
template: `R<left *ngIf="false"></left>`,
directives: [
forwardRef(() => LeftComp),
]
})
class RightComp {
}

@Component({
selector: 'fakeRecursiveComp',
template: `[<left *ngIf="false"></left><right *ngIf="false"></right>]`,
directives: [
forwardRef(() => LeftComp),
forwardRef(() => RightComp),
]
})
export class FakeRecursiveComp {
}

0 comments on commit 927f6a5

Please sign in to comment.