Commit be8b1dc6 authored by Andrey Lushnikov's avatar Andrey Lushnikov Committed by Commit Bot

DevTools: copy JS path

This patch introduces a new 'Copy js path' option to the context
menu that allows to get a JavaScript reference to the object
in the DOM Tree. This comes handy when dealing with Shadow DOM
trees.

R=dgozman

Change-Id: I07a77597f88b6cc500baed8ae9ee097b35d79b4f
Reviewed-on: https://chromium-review.googlesource.com/c/1300756
Commit-Queue: Andrey Lushnikov <lushnikov@chromium.org>
Reviewed-by: default avatarAleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#606723}
parent 0dc51b6e
Tests that inspect element action works for deep shadow elements.
/html/body/div/div/div//div/div/span
document.querySelector('div#host').shadowRoot.querySelector('span#shadow')
/html/body/div/div/span//div/div/span
document.querySelector('span#hostOpen').shadowRoot.querySelector('span#shadow-open')
......@@ -34,6 +34,7 @@
return;
if (node.getAttribute('id') == tests[0][0]) {
TestRunner.addResult(Elements.DOMPath.xPath(node, false));
TestRunner.addResult(Elements.DOMPath.jsPath(node, false));
tests.shift();
nextTest();
}
......
......@@ -40,6 +40,46 @@ Elements.DOMPath.cssPath = function(node, optimized) {
return steps.join(' > ');
};
/**
* @param {!SDK.DOMNode} node
* @return {boolean}
*/
Elements.DOMPath.canGetJSPath = function(node) {
let wp = node;
while (wp) {
if (wp.ancestorShadowRoot() && wp.ancestorShadowRoot().shadowRootType() !== SDK.DOMNode.ShadowRootTypes.Open)
return false;
wp = wp.ancestorShadowHost();
}
return true;
};
/**
* @param {!SDK.DOMNode} node
* @param {boolean=} optimized
* @return {string}
*/
Elements.DOMPath.jsPath = function(node, optimized) {
if (node.nodeType() !== Node.ELEMENT_NODE)
return '';
const path = [];
let wp = node;
while (wp) {
path.push(Elements.DOMPath.cssPath(wp, optimized));
wp = wp.ancestorShadowHost();
}
path.reverse();
let result = '';
for (let i = 0; i < path.length; ++i) {
if (i)
result += `.shadowRoot.querySelector('${path[i]}')`;
else
result += `document.querySelector('${path[i]}')`;
}
return result;
};
/**
* @param {!SDK.DOMNode} node
* @param {boolean} optimized
......
......@@ -517,8 +517,11 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
Common.UIString('Copy outerHTML'), treeOutline.performCopyOrCut.bind(treeOutline, false, this._node));
menuItem.setShortcut(createShortcut('V', modifier));
}
if (this._node.nodeType() === Node.ELEMENT_NODE)
if (this._node.nodeType() === Node.ELEMENT_NODE) {
section.appendItem(Common.UIString('Copy selector'), this._copyCSSPath.bind(this));
section.appendItem(
Common.UIString('Copy JS path'), this._copyJSPath.bind(this), !Elements.DOMPath.canGetJSPath(this._node));
}
if (!isShadowRoot)
section.appendItem(Common.UIString('Copy XPath'), this._copyXPath.bind(this));
if (!isShadowRoot) {
......@@ -1618,6 +1621,10 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
InspectorFrontendHost.copyText(Elements.DOMPath.cssPath(this._node, true));
}
_copyJSPath() {
InspectorFrontendHost.copyText(Elements.DOMPath.jsPath(this._node, true));
}
_copyXPath() {
InspectorFrontendHost.copyText(Elements.DOMPath.xPath(this._node, true));
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment