fix(core): allow null / undefined values in query results (#35796)
Before this change ngIvy implementation of queries would throw upon encountering null / undefined query result collected from an embedded view. It turns out that we might have a provider that explicitly provides a null / undefined value in a place of a token queried for. This commit removes a check from the ngIvy query implementation that was asserting on a query result to be defined. Fixes #35673 PR Close #35796
This commit is contained in:
parent
44e47da4cf
commit
5652fb1018
|
@ -363,9 +363,7 @@ function collectQueryResults<T>(tView: TView, lView: LView, queryIndex: number,
|
||||||
for (let i = 0; i < tQueryMatches.length; i += 2) {
|
for (let i = 0; i < tQueryMatches.length; i += 2) {
|
||||||
const tNodeIdx = tQueryMatches[i];
|
const tNodeIdx = tQueryMatches[i];
|
||||||
if (tNodeIdx > 0) {
|
if (tNodeIdx > 0) {
|
||||||
const viewResult = lViewResults[i / 2];
|
result.push(lViewResults[i / 2] as T);
|
||||||
ngDevMode && assertDefined(viewResult, 'materialized query result should be defined');
|
|
||||||
result.push(viewResult as T);
|
|
||||||
} else {
|
} else {
|
||||||
const childQueryIndex = tQueryMatches[i + 1];
|
const childQueryIndex = tQueryMatches[i + 1];
|
||||||
|
|
||||||
|
|
|
@ -1425,6 +1425,78 @@ describe('query logic', () => {
|
||||||
expect(fixture.componentInstance.queryResults.last).toBeAnInstanceOf(WithMultiProvider);
|
expect(fixture.componentInstance.queryResults.last).toBeAnInstanceOf(WithMultiProvider);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should allow undefined provider value in a [View/Content]Child queries', () => {
|
||||||
|
@Directive({selector: '[group]'})
|
||||||
|
class GroupDir {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Directive(
|
||||||
|
{selector: '[undefinedGroup]', providers: [{provide: GroupDir, useValue: undefined}]})
|
||||||
|
class UndefinedGroup {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
template: `
|
||||||
|
<div group></div>
|
||||||
|
<ng-template [ngIf]="true">
|
||||||
|
<div undefinedGroup></div>
|
||||||
|
</ng-template>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
class App {
|
||||||
|
@ViewChild(GroupDir) group !: GroupDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule(
|
||||||
|
{declarations: [App, GroupDir, UndefinedGroup], imports: [CommonModule]});
|
||||||
|
const fixture = TestBed.createComponent(App);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(fixture.componentInstance.group).toBeAnInstanceOf(GroupDir);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow null / undefined provider value in a [View/Content]Children queries', () => {
|
||||||
|
@Directive({selector: '[group]'})
|
||||||
|
class GroupDir {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Directive({selector: '[nullGroup]', providers: [{provide: GroupDir, useValue: null}]})
|
||||||
|
class NullGroup {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Directive(
|
||||||
|
{selector: '[undefinedGroup]', providers: [{provide: GroupDir, useValue: undefined}]})
|
||||||
|
class UndefinedGroup {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
template: `
|
||||||
|
<ng-template [ngIf]="true">
|
||||||
|
<div nullGroup></div>
|
||||||
|
</ng-template>
|
||||||
|
<div group></div>
|
||||||
|
<ng-template [ngIf]="true">
|
||||||
|
<div undefinedGroup></div>
|
||||||
|
</ng-template>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
class App {
|
||||||
|
@ViewChildren(GroupDir) groups !: QueryList<GroupDir>;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule(
|
||||||
|
{declarations: [App, GroupDir, NullGroup, UndefinedGroup], imports: [CommonModule]});
|
||||||
|
const fixture = TestBed.createComponent(App);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const queryList = fixture.componentInstance.groups;
|
||||||
|
expect(queryList.length).toBe(3);
|
||||||
|
|
||||||
|
const groups = queryList.toArray();
|
||||||
|
expect(groups[0]).toBeNull();
|
||||||
|
expect(groups[1]).toBeAnInstanceOf(GroupDir);
|
||||||
|
expect(groups[2]).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue