feat(ivy): expose window.ng.getDebugNode
helper (#32727)
PR Close #32727
This commit is contained in:
parent
252966bcca
commit
4726ac2481
@ -16,4 +16,4 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export {markDirty} from './instructions/all';
|
export {markDirty} from './instructions/all';
|
||||||
export {getComponent, getContext, getDirectives, getHostElement, getInjector, getListeners, getRootComponents, getViewComponent} from './util/discovery_utils';
|
export {getComponent, getContext, getDebugNode, getDirectives, getHostElement, getInjector, getListeners, getRootComponents, getViewComponent} from './util/discovery_utils';
|
||||||
|
@ -358,21 +358,7 @@ export function toDebugNodes(tNode: TNode | null, lView: LView): DebugNode[]|nul
|
|||||||
const debugNodes: DebugNode[] = [];
|
const debugNodes: DebugNode[] = [];
|
||||||
let tNodeCursor: TNode|null = tNode;
|
let tNodeCursor: TNode|null = tNode;
|
||||||
while (tNodeCursor) {
|
while (tNodeCursor) {
|
||||||
const rawValue = lView[tNode.index];
|
debugNodes.push(buildDebugNode(tNodeCursor, lView));
|
||||||
const native = unwrapRNode(rawValue);
|
|
||||||
const componentLViewDebug = toDebug(readLViewValue(rawValue));
|
|
||||||
const styles = isStylingContext(tNode.styles) ?
|
|
||||||
new NodeStylingDebug(tNode.styles as any as TStylingContext, lView) :
|
|
||||||
null;
|
|
||||||
const classes = isStylingContext(tNode.classes) ?
|
|
||||||
new NodeStylingDebug(tNode.classes as any as TStylingContext, lView, true) :
|
|
||||||
null;
|
|
||||||
debugNodes.push({
|
|
||||||
html: toHtml(native),
|
|
||||||
native: native as any, styles, classes,
|
|
||||||
nodes: toDebugNodes(tNode.child, lView),
|
|
||||||
component: componentLViewDebug,
|
|
||||||
});
|
|
||||||
tNodeCursor = tNodeCursor.next;
|
tNodeCursor = tNodeCursor.next;
|
||||||
}
|
}
|
||||||
return debugNodes;
|
return debugNodes;
|
||||||
@ -381,6 +367,24 @@ export function toDebugNodes(tNode: TNode | null, lView: LView): DebugNode[]|nul
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function buildDebugNode(tNode: TNode, lView: LView): DebugNode {
|
||||||
|
const rawValue = lView[tNode.index];
|
||||||
|
const native = unwrapRNode(rawValue);
|
||||||
|
const componentLViewDebug = toDebug(readLViewValue(rawValue));
|
||||||
|
const styles = isStylingContext(tNode.styles) ?
|
||||||
|
new NodeStylingDebug(tNode.styles as any as TStylingContext, lView) :
|
||||||
|
null;
|
||||||
|
const classes = isStylingContext(tNode.classes) ?
|
||||||
|
new NodeStylingDebug(tNode.classes as any as TStylingContext, lView, true) :
|
||||||
|
null;
|
||||||
|
return {
|
||||||
|
html: toHtml(native),
|
||||||
|
native: native as any, styles, classes,
|
||||||
|
nodes: toDebugNodes(tNode.child, lView),
|
||||||
|
component: componentLViewDebug,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export class LContainerDebug {
|
export class LContainerDebug {
|
||||||
constructor(private readonly _raw_lContainer: LContainer) {}
|
constructor(private readonly _raw_lContainer: LContainer) {}
|
||||||
|
|
||||||
|
@ -10,14 +10,15 @@ import {Injector} from '../../di/injector';
|
|||||||
import {assertLView} from '../assert';
|
import {assertLView} from '../assert';
|
||||||
import {discoverLocalRefs, getComponentAtNodeIndex, getDirectivesAtNodeIndex, getLContext} from '../context_discovery';
|
import {discoverLocalRefs, getComponentAtNodeIndex, getDirectivesAtNodeIndex, getLContext} from '../context_discovery';
|
||||||
import {NodeInjector} from '../di';
|
import {NodeInjector} from '../di';
|
||||||
|
import {DebugNode, buildDebugNode} from '../instructions/lview_debug';
|
||||||
import {LContext} from '../interfaces/context';
|
import {LContext} from '../interfaces/context';
|
||||||
import {DirectiveDef} from '../interfaces/definition';
|
import {DirectiveDef} from '../interfaces/definition';
|
||||||
import {TElementNode, TNode, TNodeProviderIndexes} from '../interfaces/node';
|
import {TElementNode, TNode, TNodeProviderIndexes} from '../interfaces/node';
|
||||||
import {CLEANUP, CONTEXT, FLAGS, HOST, LView, LViewFlags, TVIEW} from '../interfaces/view';
|
import {CLEANUP, CONTEXT, FLAGS, HEADER_OFFSET, HOST, LView, LViewFlags, TVIEW} from '../interfaces/view';
|
||||||
|
|
||||||
import {stringifyForError} from './misc_utils';
|
import {stringifyForError} from './misc_utils';
|
||||||
import {getLViewParent, getRootContext} from './view_traversal_utils';
|
import {getLViewParent, getRootContext} from './view_traversal_utils';
|
||||||
import {unwrapRNode} from './view_utils';
|
import {getTNode, unwrapRNode} from './view_utils';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -343,3 +344,31 @@ function sortListeners(a: Listener, b: Listener) {
|
|||||||
function isDirectiveDefHack(obj: any): obj is DirectiveDef<any> {
|
function isDirectiveDefHack(obj: any): obj is DirectiveDef<any> {
|
||||||
return obj.type !== undefined && obj.template !== undefined && obj.declaredInputs !== undefined;
|
return obj.type !== undefined && obj.template !== undefined && obj.declaredInputs !== undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the attached `DebugNode` instance for an element in the DOM.
|
||||||
|
*
|
||||||
|
* @param element DOM element which is owned by an existing component's view.
|
||||||
|
*
|
||||||
|
* @publicApi
|
||||||
|
*/
|
||||||
|
export function getDebugNode(element: Node): DebugNode|null {
|
||||||
|
let debugNode: DebugNode|null = null;
|
||||||
|
|
||||||
|
const lContext = loadLContextFromNode(element);
|
||||||
|
const lView = lContext.lView;
|
||||||
|
let nodeIndex = -1;
|
||||||
|
for (let i = HEADER_OFFSET; i < lView.length; i++) {
|
||||||
|
if (lView[i] === element) {
|
||||||
|
nodeIndex = i - HEADER_OFFSET;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nodeIndex !== -1) {
|
||||||
|
const tNode = getTNode(nodeIndex, lView);
|
||||||
|
debugNode = buildDebugNode(tNode, lView);
|
||||||
|
}
|
||||||
|
|
||||||
|
return debugNode;
|
||||||
|
}
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
import {assertDefined} from '../../util/assert';
|
import {assertDefined} from '../../util/assert';
|
||||||
import {global} from '../../util/global';
|
import {global} from '../../util/global';
|
||||||
|
import {getComponent, getContext, getDebugNode, getDirectives, getHostElement, getInjector, getListeners, getRootComponents, getViewComponent, markDirty} from '../global_utils_api';
|
||||||
import {getComponent, getContext, getDirectives, getHostElement, getInjector, getListeners, getRootComponents, getViewComponent, markDirty} from '../global_utils_api';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -48,6 +47,7 @@ export function publishDefaultGlobalUtils() {
|
|||||||
publishGlobalUtil('getInjector', getInjector);
|
publishGlobalUtil('getInjector', getInjector);
|
||||||
publishGlobalUtil('getRootComponents', getRootComponents);
|
publishGlobalUtil('getRootComponents', getRootComponents);
|
||||||
publishGlobalUtil('getDirectives', getDirectives);
|
publishGlobalUtil('getDirectives', getDirectives);
|
||||||
|
publishGlobalUtil('getDebugNode', getDebugNode);
|
||||||
publishGlobalUtil('markDirty', markDirty);
|
publishGlobalUtil('markDirty', markDirty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import {ComponentFixture, TestBed} from '@angular/core/testing';
|
|||||||
import {onlyInIvy} from '@angular/private/testing';
|
import {onlyInIvy} from '@angular/private/testing';
|
||||||
|
|
||||||
import {getHostElement, markDirty} from '../../src/render3/index';
|
import {getHostElement, markDirty} from '../../src/render3/index';
|
||||||
import {getComponent, getContext, getDirectives, getInjectionTokens, getInjector, getListeners, getLocalRefs, getRootComponents, getViewComponent, loadLContext} from '../../src/render3/util/discovery_utils';
|
import {getComponent, getContext, getDebugNode, getDirectives, getInjectionTokens, getInjector, getListeners, getLocalRefs, getRootComponents, getViewComponent, loadLContext} from '../../src/render3/util/discovery_utils';
|
||||||
|
|
||||||
onlyInIvy('Ivy-specific utilities').describe('discovery utils', () => {
|
onlyInIvy('Ivy-specific utilities').describe('discovery utils', () => {
|
||||||
let fixture: ComponentFixture<MyApp>;
|
let fixture: ComponentFixture<MyApp>;
|
||||||
@ -403,4 +403,31 @@ onlyInIvy('Ivy-specific utilities').describe('discovery utils deprecated', () =>
|
|||||||
expect(localRefs.elRef.tagName.toLowerCase()).toBe('div');
|
expect(localRefs.elRef.tagName.toLowerCase()).toBe('div');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('getDebugNode()', () => {
|
||||||
|
it('should create an instance of `DebugNode` when called for a specific element', () => {
|
||||||
|
@Component({
|
||||||
|
template: `
|
||||||
|
<div class="parent">
|
||||||
|
<div class="child"></div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
class Comp {
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({declarations: [Comp]});
|
||||||
|
const fixture = TestBed.createComponent(Comp);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const parent = fixture.nativeElement.querySelector('.parent') !;
|
||||||
|
const child = fixture.nativeElement.querySelector('.child') !;
|
||||||
|
|
||||||
|
const parentDebug = getDebugNode(parent) !;
|
||||||
|
const childDebug = getDebugNode(child) !;
|
||||||
|
|
||||||
|
expect(parentDebug.native).toBe(parent);
|
||||||
|
expect(childDebug.native).toBe(child);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
2
tools/public_api_guard/global_utils.d.ts
vendored
2
tools/public_api_guard/global_utils.d.ts
vendored
@ -2,6 +2,8 @@ export declare function getComponent<T = {}>(element: Element): T | null;
|
|||||||
|
|
||||||
export declare function getContext<T = {}>(element: Element): T | null;
|
export declare function getContext<T = {}>(element: Element): T | null;
|
||||||
|
|
||||||
|
export declare function getDebugNode(element: Node): DebugNode | null;
|
||||||
|
|
||||||
export declare function getDirectives(target: {}): Array<{}>;
|
export declare function getDirectives(target: {}): Array<{}>;
|
||||||
|
|
||||||
export declare function getHostElement<T>(directive: T): Element;
|
export declare function getHostElement<T>(directive: T): Element;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user