fix(ivy): align DebugNode/DebugElement behavior with View Engine (#30756)
Two issues with DebugNode/DebugElement in Ivy were causing problems in user tests. 1. The DebugNodes returned by Ivy were not actually instances of DebugNode. This was due to an issue with the Ivy switch logic in debug_node.ts. The declaration of the exported DebugNode reference was set to `DebugNode__PRE_R3__ as any`. The cast prevented the Ivy switch transform from detecting this as a switchable declaration. The transform cannot handle arbitrary syntax, and exports *must* be of the form "const x = y__PRE_R3__;" or they will not work. The cast to any in this case was not needed, so this commit removes it. 2. DebugNodes returned by Ivy multiple times for the same element were not reference-identical. This was previously considered a minor breaking change in Ivy, but testing has shown that users depend on referential equality of DebugNodes. This commit caches a DebugNode on a DOM node when first creating it, to allow returning the same instance in subsequent operations. PR Close #30756
This commit is contained in:
parent
09c57ecf95
commit
d82adbe8c4
|
@ -638,14 +638,19 @@ function getDebugNode__PRE_R3__(nativeNode: any): DebugNode|null {
|
|||
return _nativeNodeToDebugNode.get(nativeNode) || null;
|
||||
}
|
||||
|
||||
const NG_DEBUG_PROPERTY = '__ng_debug__';
|
||||
|
||||
export function getDebugNode__POST_R3__(nativeNode: Element): DebugElement__POST_R3__;
|
||||
export function getDebugNode__POST_R3__(nativeNode: Node): DebugNode__POST_R3__;
|
||||
export function getDebugNode__POST_R3__(nativeNode: null): null;
|
||||
export function getDebugNode__POST_R3__(nativeNode: any): DebugNode|null {
|
||||
if (nativeNode instanceof Node) {
|
||||
return nativeNode.nodeType == Node.ELEMENT_NODE ?
|
||||
new DebugElement__POST_R3__(nativeNode as Element) :
|
||||
new DebugNode__POST_R3__(nativeNode);
|
||||
if (!(nativeNode.hasOwnProperty(NG_DEBUG_PROPERTY))) {
|
||||
(nativeNode as any)[NG_DEBUG_PROPERTY] = nativeNode.nodeType == Node.ELEMENT_NODE ?
|
||||
new DebugElement__POST_R3__(nativeNode as Element) :
|
||||
new DebugNode__POST_R3__(nativeNode);
|
||||
}
|
||||
return (nativeNode as any)[NG_DEBUG_PROPERTY];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -678,9 +683,9 @@ export interface Predicate<T> { (value: T): boolean; }
|
|||
/**
|
||||
* @publicApi
|
||||
*/
|
||||
export const DebugNode: {new (...args: any[]): DebugNode} = DebugNode__PRE_R3__ as any;
|
||||
export const DebugNode: {new (...args: any[]): DebugNode} = DebugNode__PRE_R3__;
|
||||
|
||||
/**
|
||||
* @publicApi
|
||||
*/
|
||||
export const DebugElement: {new (...args: any[]): DebugElement} = DebugElement__PRE_R3__ as any;
|
||||
export const DebugElement: {new (...args: any[]): DebugElement} = DebugElement__PRE_R3__;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
|
||||
import {Component, Directive, ElementRef, EmbeddedViewRef, EventEmitter, HostBinding, Injectable, Input, NO_ERRORS_SCHEMA, TemplateRef, ViewChild, ViewContainerRef} from '@angular/core';
|
||||
import {Component, DebugNode, Directive, ElementRef, EmbeddedViewRef, EventEmitter, HostBinding, Injectable, Input, NO_ERRORS_SCHEMA, TemplateRef, ViewChild, ViewContainerRef} from '@angular/core';
|
||||
import {ComponentFixture, TestBed, async} from '@angular/core/testing';
|
||||
import {By} from '@angular/platform-browser/src/dom/debug/by';
|
||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
||||
|
@ -678,5 +678,22 @@ class TestCmptWithPropBindings {
|
|||
expect(divB.nativeElement.getAttribute('id')).toBe('b');
|
||||
});
|
||||
|
||||
it('should be an instance of DebugNode', () => {
|
||||
fixture = TestBed.createComponent(ParentComp);
|
||||
fixture.detectChanges();
|
||||
expect(fixture.debugElement).toBeAnInstanceOf(DebugNode);
|
||||
});
|
||||
|
||||
it('should return the same element when queried twice', () => {
|
||||
fixture = TestBed.createComponent(ParentComp);
|
||||
fixture.detectChanges();
|
||||
|
||||
const childTestElsFirst = fixture.debugElement.queryAll(By.css('child-comp'));
|
||||
const childTestElsSecond = fixture.debugElement.queryAll(By.css('child-comp'));
|
||||
|
||||
expect(childTestElsFirst.length).toBe(1);
|
||||
expect(childTestElsSecond[0]).toBe(childTestElsFirst[0]);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue