fix(core): error if DebugRenderer2.destroyNode is called twice in a row (#41565)
Fixes an error that will be thrown if `DebugRenderer2.destroyNode` is called with a node that has already been destroyed. The error happened, because we had a non-null assertion, even though the value can be null. Note that this fix applies only to ViewEngine, because Ivy doesn't provide the `DebugRenderer2`. I decided to resolve it, because it fix is straightforward and this error has been showing up in our logs for a long time now, making actual errors harder to find. PR Close #41565
This commit is contained in:
parent
ebc80b3b5c
commit
aa0e54fe97
@ -703,11 +703,15 @@ export class DebugRenderer2 implements Renderer2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
destroyNode(node: any) {
|
destroyNode(node: any) {
|
||||||
const debugNode = getDebugNode(node)!;
|
const debugNode = getDebugNode(node);
|
||||||
removeDebugNodeFromIndex(debugNode);
|
|
||||||
if (debugNode instanceof DebugNode__PRE_R3__) {
|
if (debugNode) {
|
||||||
debugNode.listeners.length = 0;
|
removeDebugNodeFromIndex(debugNode);
|
||||||
|
if (debugNode instanceof DebugNode__PRE_R3__) {
|
||||||
|
debugNode.listeners.length = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.delegate.destroyNode) {
|
if (this.delegate.destroyNode) {
|
||||||
this.delegate.destroyNode(node);
|
this.delegate.destroyNode(node);
|
||||||
}
|
}
|
||||||
|
@ -208,6 +208,7 @@ class TestApp {
|
|||||||
width = 200;
|
width = 200;
|
||||||
color = 'red';
|
color = 'red';
|
||||||
isClosed = true;
|
isClosed = true;
|
||||||
|
constructor(public renderer: Renderer2) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({selector: 'test-cmpt', template: ``})
|
@Component({selector: 'test-cmpt', template: ``})
|
||||||
@ -618,6 +619,22 @@ class TestCmptWithPropInterpolation {
|
|||||||
expect(fixture.debugElement.query(By.css('.myclass'))).toBeTruthy();
|
expect(fixture.debugElement.query(By.css('.myclass'))).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not throw when calling DebugRenderer2.destroyNode twice in a row', () => {
|
||||||
|
const fixture = TestBed.createComponent(TestApp);
|
||||||
|
fixture.detectChanges();
|
||||||
|
const firstChild = fixture.debugElement.children[0];
|
||||||
|
const renderer = fixture.componentInstance.renderer;
|
||||||
|
|
||||||
|
expect(firstChild).toBeTruthy();
|
||||||
|
expect(() => {
|
||||||
|
// `destroyNode` needs to be null checked, because only ViewEngine provides a
|
||||||
|
// `DebugRenderer2` which has the behavior we're testing for. Ivy provides
|
||||||
|
// `BaseAnimationRenderer` which doesn't have the issue.
|
||||||
|
renderer.destroyNode?.(firstChild);
|
||||||
|
renderer.destroyNode?.(firstChild);
|
||||||
|
}).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
describe('DebugElement.query with dynamically created descendant elements', () => {
|
describe('DebugElement.query with dynamically created descendant elements', () => {
|
||||||
let fixture: ComponentFixture<{}>;
|
let fixture: ComponentFixture<{}>;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user