fix(ivy): remove query results from embedded views on view destroy (#29056)
PR Close #29056
This commit is contained in:
parent
d2f015f57e
commit
c875851bb4
|
@ -17,11 +17,11 @@ import {NodeInjectorFactory} from './interfaces/injector';
|
||||||
import {TElementNode, TNode, TNodeFlags, TNodeType, TProjectionNode, TViewNode, unusedValueExportToPlacateAjd as unused2} from './interfaces/node';
|
import {TElementNode, TNode, TNodeFlags, TNodeType, TProjectionNode, TViewNode, unusedValueExportToPlacateAjd as unused2} from './interfaces/node';
|
||||||
import {unusedValueExportToPlacateAjd as unused3} from './interfaces/projection';
|
import {unusedValueExportToPlacateAjd as unused3} from './interfaces/projection';
|
||||||
import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, isProceduralRenderer, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer';
|
import {ProceduralRenderer3, RComment, RElement, RNode, RText, Renderer3, isProceduralRenderer, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer';
|
||||||
import {CHILD_HEAD, CLEANUP, FLAGS, HEADER_OFFSET, HookData, LView, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, TVIEW, T_HOST, unusedValueExportToPlacateAjd as unused5} from './interfaces/view';
|
import {CHILD_HEAD, CLEANUP, FLAGS, HookData, LView, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, TVIEW, T_HOST, unusedValueExportToPlacateAjd as unused5} from './interfaces/view';
|
||||||
import {assertNodeType} from './node_assert';
|
import {assertNodeType} from './node_assert';
|
||||||
import {renderStringify} from './util/misc_utils';
|
import {renderStringify} from './util/misc_utils';
|
||||||
import {findComponentView, getLViewParent} from './util/view_traversal_utils';
|
import {findComponentView, getLViewParent} from './util/view_traversal_utils';
|
||||||
import {getNativeByTNode, isComponent, isLContainer, isLView, isRootView, unwrapRNode} from './util/view_utils';
|
import {getNativeByTNode, isComponent, isLContainer, isLView, isRootView, unwrapRNode, viewAttachedToContainer} from './util/view_utils';
|
||||||
|
|
||||||
const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4 + unused5;
|
const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4 + unused5;
|
||||||
|
|
||||||
|
@ -350,7 +350,8 @@ export function detachView(lContainer: LContainer, removeIndex: number): LView {
|
||||||
views.splice(removeIndex, 1);
|
views.splice(removeIndex, 1);
|
||||||
addRemoveViewFromContainer(viewToDetach, false);
|
addRemoveViewFromContainer(viewToDetach, false);
|
||||||
|
|
||||||
if (viewToDetach[QUERIES]) {
|
if ((viewToDetach[FLAGS] & LViewFlags.Attached) &&
|
||||||
|
!(viewToDetach[FLAGS] & LViewFlags.Destroyed) && viewToDetach[QUERIES]) {
|
||||||
viewToDetach[QUERIES] !.removeView();
|
viewToDetach[QUERIES] !.removeView();
|
||||||
}
|
}
|
||||||
viewToDetach[PARENT] = null;
|
viewToDetach[PARENT] = null;
|
||||||
|
@ -422,10 +423,8 @@ export function getParentState(lViewOrLContainer: LView | LContainer, rootView:
|
||||||
*
|
*
|
||||||
* @param view The LView to clean up
|
* @param view The LView to clean up
|
||||||
*/
|
*/
|
||||||
function cleanUpView(viewOrContainer: LView | LContainer): void {
|
function cleanUpView(view: LView | LContainer): void {
|
||||||
if ((viewOrContainer as LView).length >= HEADER_OFFSET) {
|
if (isLView(view) && !(view[FLAGS] & LViewFlags.Destroyed)) {
|
||||||
const view = viewOrContainer as LView;
|
|
||||||
|
|
||||||
// Usually the Attached flag is removed when the view is detached from its parent, however
|
// Usually the Attached flag is removed when the view is detached from its parent, however
|
||||||
// if it's a root view, the flag won't be unset hence why we're also removing on destroy.
|
// if it's a root view, the flag won't be unset hence why we're also removing on destroy.
|
||||||
view[FLAGS] &= ~LViewFlags.Attached;
|
view[FLAGS] &= ~LViewFlags.Attached;
|
||||||
|
@ -445,6 +444,10 @@ function cleanUpView(viewOrContainer: LView | LContainer): void {
|
||||||
ngDevMode && ngDevMode.rendererDestroy++;
|
ngDevMode && ngDevMode.rendererDestroy++;
|
||||||
(view[RENDERER] as ProceduralRenderer3).destroy();
|
(view[RENDERER] as ProceduralRenderer3).destroy();
|
||||||
}
|
}
|
||||||
|
// For embedded views still attached to a container: remove query result from this view.
|
||||||
|
if (viewAttachedToContainer(view) && view[QUERIES]) {
|
||||||
|
view[QUERIES] !.removeView();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -713,8 +713,7 @@ describe('Query API', () => {
|
||||||
expect(q.query.map((d: TextDirective) => d.text)).toEqual(['2', '1']);
|
expect(q.query.map((d: TextDirective) => d.text)).toEqual(['2', '1']);
|
||||||
});
|
});
|
||||||
|
|
||||||
fixmeIvy('FW-920: Queries in nested views are not destroyed properly')
|
it('should remove manually projected templates if their parent view is destroyed', () => {
|
||||||
.it('should remove manually projected templates if their parent view is destroyed', () => {
|
|
||||||
const template = `
|
const template = `
|
||||||
<manual-projecting #q><ng-template #tpl><div text="1"></div></ng-template></manual-projecting>
|
<manual-projecting #q><ng-template #tpl><div text="1"></div></ng-template></manual-projecting>
|
||||||
<div *ngIf="shouldShow">
|
<div *ngIf="shouldShow">
|
||||||
|
@ -730,6 +729,7 @@ describe('Query API', () => {
|
||||||
|
|
||||||
view.componentInstance.shouldShow = false;
|
view.componentInstance.shouldShow = false;
|
||||||
view.detectChanges();
|
view.detectChanges();
|
||||||
|
|
||||||
expect(q.query.length).toBe(0);
|
expect(q.query.length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue