Skip to content

Commit e366473

Browse files
crisbetothePunderWoman
authored andcommitted
refactor(core): replace usages of removeChild (#57203)
These changes replace most usages of `removeChild` with `remove`. The latter has the advantage of not having to look up the `parentNode` and ensure that the child being removed actually belongs to the specific parent. The refactor should be fairly safe since all the browsers we cover support `remove`. [Something similar was done in Components](angular/components#23592) some time ago and there haven't been any bug reports as a result. PR Close #57203
1 parent 0c12d8e commit e366473

32 files changed

+53
-95
lines changed

packages/animations/browser/src/render/animation_renderer.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,8 @@ export class AnimationRendererFactory implements RendererFactory2 {
2929
private engine: AnimationEngine,
3030
private _zone: NgZone,
3131
) {
32-
engine.onRemovalComplete = (element: any, delegate: Renderer2) => {
33-
// Note: if a component element has a leave animation, and a host leave animation,
34-
// the view engine will call `removeChild` for the parent
35-
// component renderer as well as for the child component renderer.
36-
// Therefore, we need to check if we already removed the element.
37-
const parentNode = delegate?.parentNode(element);
38-
if (parentNode) {
39-
delegate.removeChild(parentNode, element);
40-
}
32+
engine.onRemovalComplete = (element: any, delegate: Renderer2 | null) => {
33+
delegate?.removeChild(null, element);
4134
};
4235
}
4336

packages/animations/browser/src/render/renderer.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,13 @@ export class BaseAnimationRenderer implements Renderer2 {
7878
}
7979

8080
removeChild(parent: any, oldChild: any, isHostElement?: boolean): void {
81-
this.engine.onRemove(this.namespaceId, oldChild, this.delegate);
81+
// Prior to the changes in #57203, this method wasn't being called at all by `core` if the child
82+
// doesn't have a parent. There appears to be some animation-specific downstream logic that
83+
// depends on the null check happening before the animation engine. This check keeps the old
84+
// behavior while allowing `core` to not have to check for the parent element anymore.
85+
if (this.parentNode(oldChild)) {
86+
this.engine.onRemove(this.namespaceId, oldChild, this.delegate);
87+
}
8288
}
8389

8490
selectRootElement(selectorOrNode: any, preserveContent?: boolean) {

packages/animations/browser/test/dsl/animation_spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ describe('Animation', () => {
5656
});
5757

5858
afterEach(() => {
59-
document.body.removeChild(rootElement);
59+
rootElement.remove();
6060
});
6161

6262
describe('validation', () => {

packages/animations/browser/test/dsl/animation_trigger_spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ describe('AnimationTrigger', () => {
2929
});
3030

3131
afterEach(() => {
32-
document.body.removeChild(element);
32+
element.remove();
3333
});
3434

3535
describe('trigger validation', () => {

packages/animations/browser/test/render/timeline_animation_engine_spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import {MockAnimationDriver, MockAnimationPlayer} from '../../testing/src/mock_a
3939
document.body.appendChild(element);
4040
});
4141

42-
afterEach(() => document.body.removeChild(element));
42+
afterEach(() => element.remove());
4343

4444
it('should animate a timeline', () => {
4545
const engine = makeEngine(getBodyNode());

packages/animations/browser/test/render/transition_animation_engine_spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ const DEFAULT_NAMESPACE_ID = 'id';
4949
});
5050

5151
afterEach(() => {
52-
document.body.removeChild(element);
52+
element.remove();
5353
});
5454

5555
function makeEngine(normalizer?: AnimationStyleNormalizer) {

packages/common/http/src/jsonp.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,7 @@ export class JsonpClientBackend implements HttpBackend {
164164
// success, error, and cancellation paths, so it's extracted out for convenience.
165165
const cleanup = () => {
166166
// Remove the <script> tag if it's still on the page.
167-
if (node.parentNode) {
168-
node.parentNode.removeChild(node);
169-
}
167+
node.remove();
170168

171169
// Remove the response callback from the callbackMap (window object in the
172170
// browser).

packages/common/http/test/jsonp_mock.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ export class MockScriptElement {
2121
removeEventListener(event: 'load' | 'error'): void {
2222
delete this.listeners[event];
2323
}
24+
25+
remove() {
26+
this.ownerDocument.removeNode(this);
27+
}
2428
}
2529

2630
export class MockDocument {

packages/common/test/viewport_scroller_spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ describe('BrowserViewportScroller', () => {
108108
return {
109109
anchorNode,
110110
cleanup: () => {
111-
document.body.removeChild(tallItem);
112-
document.body.removeChild(anchorNode);
111+
tallItem.remove();
112+
anchorNode.remove();
113113
},
114114
};
115115
}
@@ -128,8 +128,8 @@ describe('BrowserViewportScroller', () => {
128128
return {
129129
anchorNode,
130130
cleanup: () => {
131-
document.body.removeChild(tallItem);
132-
document.body.removeChild(elementWithShadowRoot);
131+
tallItem.remove();
132+
elementWithShadowRoot.remove();
133133
},
134134
};
135135
}

packages/core/src/render3/interfaces/renderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export interface Renderer {
4343
destroyNode?: ((node: RNode) => void) | null;
4444
appendChild(parent: RElement, newChild: RNode): void;
4545
insertBefore(parent: RNode, newChild: RNode, refChild: RNode | null, isMove?: boolean): void;
46-
removeChild(parent: RElement, oldChild: RNode, isHostElement?: boolean): void;
46+
removeChild(parent: RElement | null, oldChild: RNode, isHostElement?: boolean): void;
4747
selectRootElement(selectorOrNode: string | any, preserveContent?: boolean): RElement;
4848

4949
parentNode(node: RNode): RElement | null;

0 commit comments

Comments
 (0)