Commit 6dfd32cb authored by Paul Lewis's avatar Paul Lewis Committed by Commit Bot

DevTools: Warn when revealed node is detached from the document.

If a user right clicks on an element in the console and chooses to reveal it in
the elements panel, and the element is not in the document, the operation fails
but it is not communicated to the user. This patch adds a warning if the node
appears to be detached from the document; it is done through checking the
parentNode property, which is the most suitable means in lieu of having the
isConnected property available in the Node object.

Bug: 967156
Change-Id: I58228facb54e9afc87215d68176f473121121db4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1681891
Commit-Queue: Paul Lewis <aerotwist@chromium.org>
Reviewed-by: default avatarErik Luo <luoe@chromium.org>
Cr-Commit-Position: refs/heads/master@{#706474}
parent 87c8d8fd
......@@ -993,6 +993,24 @@ Elements.ElementsPanel.DOMNodeRevealer = class {
function onNodeResolved(resolvedNode) {
panel._pendingNodeReveal = false;
// A detached node could still have a parent and ownerDocument
// properties, which means stepping up through the hierarchy to ensure
// that the root node is the document itself. Any break implies
// detachment.
let currentNode = resolvedNode;
while (currentNode.parentNode) {
currentNode = currentNode.parentNode;
}
const isDetached = !(currentNode instanceof SDK.DOMDocument);
const isDocument = node instanceof SDK.DOMDocument;
if (!isDocument && isDetached) {
const msg = ls`Node cannot be found in the current page.`;
Common.console.warn(msg);
reject(new Error(msg));
return;
}
if (resolvedNode) {
panel.revealAndSelectNode(resolvedNode, !omitFocus).then(resolve);
return;
......
......@@ -123,6 +123,9 @@
<message name="IDS_DEVTOOLS_5c6236c705b0086fbbdb2df3133f8a06" desc="Title of a setting under the Elements category in Settings">
Reveal DOM node on hover
</message>
<message name="IDS_DEVTOOLS_5e1078f1bee74e1e385b7813280b0c74" desc="Text when node can not be found in page">
Node cannot be found in the current page.
</message>
<message name="IDS_DEVTOOLS_5eeb03a9c080c299d4804ac765c818c2" desc="No matches element text content in Styles Sidebar Pane of the Elements panel">
No matching selector or style
</message>
......@@ -279,4 +282,4 @@
<message name="IDS_DEVTOOLS_fd9bcae718daadf263a2e73c7745f0a7" desc="Tree element expand all button element button text content in Elements Tree Outline of the Elements panel">
Show All Nodes (<ph name="VISIBLECHILDREN_LENGTH___EXPANDEDCHILDCOUNT">$1d<ex>3</ex></ph> More)
</message>
</grit-part>
\ No newline at end of file
</grit-part>
......@@ -6,6 +6,12 @@ Running: init
Running: revealNode
Node revealed in the Elements panel
Running: revealRemovedNode
Removed node not revealed
Running: revealNodeWithRemovedParent
Node with removed parent not revealed
Running: revealUILocation
UILocation bar.js:2:1 revealed in the Sources panel
......
......@@ -11,8 +11,12 @@
await TestRunner.showPanel('resources');
await TestRunner.showPanel('network');
await TestRunner.loadHTML(`
<div id="div">
<div id="targetnode">
</div>
<span id="toremove"></span>
<span id="containertoremove">
<span id="child"></span>
</span>
`);
await TestRunner.evaluateInPagePromise(`
function loadResource(url)
......@@ -24,14 +28,17 @@
`);
await TestRunner.addScriptTag('resources/bar.js');
var node;
var divNode;
var spanNode;
var childNode;
var container;
var resource;
var uiLocation;
var requestWithResource;
var requestWithoutResource;
TestRunner.runTestSuite([
function init(next) {
async function init(next) {
installHooks();
TestRunner.resourceTreeModel.forAllResources(function(r) {
......@@ -42,14 +49,14 @@
});
uiLocation = Workspace.workspace.uiSourceCodeForURL(resource.url).uiLocation(2, 1);
ElementsTestRunner.nodeWithId('div', nodeCallback);
divNode = await ElementsTestRunner.nodeWithIdPromise('targetnode');
spanNode = await ElementsTestRunner.nodeWithIdPromise('toremove');
childNode = await ElementsTestRunner.nodeWithIdPromise('child');
container = await ElementsTestRunner.nodeWithIdPromise('containertoremove');
function nodeCallback(foundNode) {
node = foundNode;
NetworkTestRunner.recordNetwork();
var url = TestRunner.url('bar.js');
TestRunner.evaluateInPage(`loadResource('${url}')`, firstXhrCallback);
}
NetworkTestRunner.recordNetwork();
var url = TestRunner.url('bar.js');
TestRunner.evaluateInPage(`loadResource('${url}')`, firstXhrCallback);
function firstXhrCallback() {
requestWithResource = SDK.networkLog.requestForURL(resource.url);
......@@ -69,7 +76,29 @@
},
function revealNode(next) {
Common.Revealer.reveal(node).then(next);
Common.Revealer.reveal(divNode).then(next);
},
function revealRemovedNode(next) {
spanNode.removeNode(function() {
Common.Revealer.reveal(spanNode).then(() => {
TestRunner.addResult('Removed node revealed');
}, () => {
TestRunner.addResult('Removed node not revealed');
}).finally(next);
});
},
function revealNodeWithRemovedParent(next) {
// Note: we remove the container, and then check that the child also can
// not be revealed since it is also detached.
container.parentNode.removeNode(function() {
Common.Revealer.reveal(childNode).then(() => {
TestRunner.addResult('Node with removed parent revealed');
}, () => {
TestRunner.addResult('Node with removed parent not revealed');
}).finally(next);
});
},
function revealUILocation(next) {
......
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