fix(Compiler): relax childIsRecursive check (#8705)
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](https://github.com/angular/angular/issues/7084)
This commit is contained in:
parent
ef37d2ae0b
commit
3d5bb23184
|
@ -115,7 +115,9 @@ export class RuntimeCompiler implements ComponentResolver {
|
||||||
this._metadataResolver.getViewDirectivesMetadata(dep.comp.type.runtime);
|
this._metadataResolver.getViewDirectivesMetadata(dep.comp.type.runtime);
|
||||||
var childViewPipes: CompilePipeMetadata[] =
|
var childViewPipes: CompilePipeMetadata[] =
|
||||||
this._metadataResolver.getViewPipesMetadata(dep.comp.type.runtime);
|
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);
|
childCompilingComponentsPath.push(childCacheKey);
|
||||||
|
|
||||||
var childComp = this._loadAndCompileComponent(
|
var childComp = this._loadAndCompileComponent(
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
|
||||||
|
|
||||||
import {IS_DART} from '../../src/facade/lang';
|
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 {NgIf, NgClass} from '@angular/common';
|
||||||
import {CompilerConfig} from '@angular/compiler';
|
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',
|
it('should support ngClass before a component and content projection inside of an ngIf',
|
||||||
inject(
|
inject(
|
||||||
[TestComponentBuilder, AsyncTestCompleter],
|
[TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: any) => {
|
||||||
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
|
|
||||||
tcb.overrideView(
|
tcb.overrideView(
|
||||||
MyComp1, new ViewMetadata({
|
MyComp1, new ViewMetadata({
|
||||||
template: `A<cmp-content *ngIf="true" [ngClass]="'red'">B</cmp-content>C`,
|
template: `A<cmp-content *ngIf="true" [ngClass]="'red'">B</cmp-content>C`,
|
||||||
|
@ -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: `<ng-content></ng-content>`})
|
@Component({selector: 'cmp-content', template: `<ng-content></ng-content>`})
|
||||||
class CmpWithNgContent {
|
class CmpWithNgContent {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'left',
|
||||||
|
template: `L<right *ngIf="false"></right>`,
|
||||||
|
directives: [
|
||||||
|
NgIf,
|
||||||
|
forwardRef(() => RightComp),
|
||||||
|
]
|
||||||
|
})
|
||||||
|
class LeftComp {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'right',
|
||||||
|
template: `R<left *ngIf="false"></left>`,
|
||||||
|
directives: [
|
||||||
|
NgIf,
|
||||||
|
forwardRef(() => LeftComp),
|
||||||
|
]
|
||||||
|
})
|
||||||
|
class RightComp {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'fakeRecursiveComp',
|
||||||
|
template: `[<left *ngIf="false"></left><right *ngIf="false"></right>]`,
|
||||||
|
directives: [
|
||||||
|
NgIf,
|
||||||
|
forwardRef(() => LeftComp),
|
||||||
|
forwardRef(() => RightComp),
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class FakeRecursiveComp {
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue