Commit 2e5ad0a8 authored by Erik Luo's avatar Erik Luo Committed by Commit Bot

DevTools: fix mismatch between DOMNode childNodeCount and children

Expanding an ElementsTreeElement used to immediately set a
populated flag to true before requesting getChildNodes().
If a ChildNodeCountUpdated event arrives before the children
are set, we may call updateModifiedParentNode() and try to
create visibleChildren when they are null, breaking the tree.

This CL moves the place where 'populated' is set, so that
updateModifiedParentNode() does not update tree children
before they are available.

Bug: 829884
Change-Id: Id68e71fb7a58336d781207b298a53354af3e5cfc
Reviewed-on: https://chromium-review.googlesource.com/1049113
Commit-Queue: Erik Luo <luoe@chromium.org>
Reviewed-by: default avatarAndrey Lushnikov <lushnikov@chromium.org>
Reviewed-by: default avatarJoel Einbinder <einbinder@chromium.org>
Cr-Commit-Position: refs/heads/master@{#557132}
parent 76551bcd
Tests that Elements properly populate and select after immediate updates crbug.com/829884
BEFORE: children: null, childNodeCount: 2
AFTER: children: null, childNodeCount: 3
AFTER EXPAND: TreeElement childCount: 3
Selected element:'BODY'
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(async function() {
TestRunner.addResult(`Tests that Elements properly populate and select after immediate updates crbug.com/829884\n`);
await TestRunner.loadModule('elements_test_runner');
await TestRunner.showPanel('elements');
await TestRunner.loadHTML(`
<!DOCTYPE HTML">
<html>
<head></head>
<body id="body">
<div>FooBar1</div>
<div>FooBar2</div>
</body>
</html>
`);
const treeOutline = ElementsTestRunner.firstElementsTreeOutline();
ElementsTestRunner.selectNodeWithId('body', node => {
TestRunner.addResult(`BEFORE: children: ${node.children()}, childNodeCount: ${node.childNodeCount()}`);
// Any operation that modifies the node, followed by an immediate, synchronous update.
TestRunner.domModel._childNodeCountUpdated(node.id, 3);
treeOutline._updateModifiedNodes();
TestRunner.addResult(`AFTER: children: ${node.children()}, childNodeCount: ${node.childNodeCount()}`);
ElementsTestRunner.expandElementsTree(afterExpand);
});
function afterExpand() {
ElementsTestRunner.selectNodeWithId('body', node => {
treeElement = node[treeOutline.treeElementSymbol()];
TestRunner.addResult(`AFTER EXPAND: TreeElement childCount: ${treeElement.childCount()}`);
var selectedElement = treeOutline.selectedTreeElement;
var nodeName = selectedElement ? selectedElement.node().nodeName() : 'null';
TestRunner.addResult('Selected element:\'' + nodeName + '\'');
TestRunner.completeTest();
});
}
})();
...@@ -287,7 +287,6 @@ Elements.ElementsTreeElement = class extends UI.TreeElement { ...@@ -287,7 +287,6 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
* @override * @override
*/ */
onpopulate() { onpopulate() {
this.populated = true;
this.treeOutline.populateTreeElement(this); this.treeOutline.populateTreeElement(this);
} }
......
...@@ -1154,7 +1154,10 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline { ...@@ -1154,7 +1154,10 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
populateTreeElement(treeElement) { populateTreeElement(treeElement) {
if (treeElement.childCount() || !treeElement.isExpandable()) if (treeElement.childCount() || !treeElement.isExpandable())
return; return;
treeElement.node().getChildNodes(() => this._updateModifiedParentNode(treeElement.node())); treeElement.node().getChildNodes(() => {
treeElement.populated = true;
this._updateModifiedParentNode(treeElement.node());
});
} }
/** /**
......
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