Bug 769299 - Make the Inspector less fragile when the selection is deleted. r=dcamp

This commit is contained in:
Paul Rouget 2012-06-28 17:43:57 +02:00
parent 7aac884610
commit ede8134305
7 changed files with 98 additions and 2 deletions

View File

@ -330,6 +330,9 @@ Highlighter.prototype = {
*/
isNodeHighlightable: function Highlighter_isNodeHighlightable(aNode)
{
if (!LayoutHelpers.isNodeConnected(aNode)) {
return false;
}
if (aNode.nodeType != aNode.ELEMENT_NODE) {
return false;
}

View File

@ -893,7 +893,9 @@ InspectorUI.prototype = {
clearPseudoClassLocks: function IUI_clearPseudoClassLocks()
{
this.breadcrumbs.nodeHierarchy.forEach(function(crumb) {
DOMUtils.clearPseudoClassLocks(crumb.node);
if (LayoutHelpers.isNodeConnected(crumb.node)) {
DOMUtils.clearPseudoClassLocks(crumb.node);
}
});
},

View File

@ -40,6 +40,8 @@ _BROWSER_FILES = \
browser_inspector_treePanel_menu.js \
browser_inspector_pseudoclass_lock.js \
browser_inspector_pseudoClass_menu.js \
browser_inspector_destroyselection.html \
browser_inspector_destroyselection.js \
head.js \
$(NULL)

View File

@ -0,0 +1,4 @@
<!DOCTYPE html>
<h1>mop</h1>
<iframe src="data:text/html;charset=utf-8,<!DOCTYPE HTML>%0D%0A<h1>kill me<span>.</span><%2Fh1>"></iframe>

View File

@ -0,0 +1,62 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test()
{
waitForExplicitFinish();
//ignoreAllUncaughtExceptions();
let node, iframe;
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(setupTest, content);
}, true);
content.location = "http://mochi.test:8888/browser/browser/devtools/highlighter/test/browser_inspector_destroyselection.html";
function setupTest()
{
iframe = content.document.querySelector("iframe");
node = iframe.contentDocument.querySelector("span");
Services.obs.addObserver(runTests,
InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
InspectorUI.openInspectorUI(node);
}
function runTests()
{
Services.obs.removeObserver(runTests,
InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED);
is(InspectorUI.selection, node, "node selected");
iframe.parentNode.removeChild(iframe);
iframe = null;
let tmp = {};
Cu.import("resource:///modules/devtools/LayoutHelpers.jsm", tmp);
ok(!tmp.LayoutHelpers.isNodeConnected(node), "Node considered as disconnected.");
Services.obs.addObserver(testBreadcrumbs,
InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
executeSoon(function() {
InspectorUI.closeInspectorUI();
});
}
function testBreadcrumbs()
{
Services.obs.removeObserver(testBreadcrumbs, InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
ok(!InspectorUI.breadcrumbs, "Breadcrumbs destroyed");
finishUp();
}
function finishUp() {
node = null;
gBrowser.removeCurrentTab();
finish();
}
}

View File

@ -286,7 +286,11 @@ LayoutView.prototype = {
*/
update: function LV_update() {
let node = this.inspector.selection;
if (!node || !this.documentReady) return;
if (!node ||
!LayoutHelpers.isNodeConnected(node) ||
!this.documentReady) {
return;
}
// First, we update the first part of the layout view, with
// the size of the element.

View File

@ -291,4 +291,23 @@ LayoutHelpers = {
LH_scrollIntoViewIfNeeded(win.frameElement, centered);
}
},
/**
* Check if a node and its document are still alive
* and attached to the window.
*
* @param aNode
*/
isNodeConnected: function LH_isNodeConnected(aNode)
{
try {
let connected = (aNode.ownerDocument && aNode.ownerDocument.defaultView &&
!(aNode.compareDocumentPosition(aNode.ownerDocument.documentElement) &
aNode.DOCUMENT_POSITION_DISCONNECTED));
return connected;
} catch (e) {
// "can't access dead object" error
return false;
}
},
};