Title: [139429] trunk
Revision
139429
Author
[email protected]
Date
2013-01-11 04:28:24 -0800 (Fri, 11 Jan 2013)

Log Message

Web Inspector: Option+Click on Node Expander Doesn't Work the First Time
https://bugs.webkit.org/show_bug.cgi?id=66868

Source/WebCore:

Up to now, the TreeElement.prototype.expandRecursively() method would correctly
expand children recursively based on the provided depth, but would not wait to
perform this task until all child nodes had been populated, which means that this
would only work incrementally with one additional level of child nodes being shown
expanded in the DOM tree upon alt+clicking a given node with a deep hierarchy.

In order to fix this, this patch adds a new optional argument to the DOMAgent's
requestChildNodes() methods to provide the depth at which we want to retrieve children
of a given node. The DOMAgent provides a new .getSubtree() method that calls
requestChildNodes() with the provided depth.

Then in ElementsTreeOutline, we subclass .expandRecursively() to first call DOMAgent's
new .getSubtree() method and then call the default implementation when all nodes
have been retrieved from the backend.

Patch by Antoine Quint <[email protected]> on 2013-01-11
Reviewed by Pavel Feldman.

Tests: inspector-protocol/dom-request-child-nodes-depth.html
       inspector/elements/expand-recursively.html

* inspector/Inspector.json: Add the new `depth` parameter to DOM.requestChildNodes().
* inspector/InspectorDOMAgent.cpp:
(WebCore::InspectorDOMAgent::pushChildNodesToFrontend): Add a new optional `depth` parameter
which defaults to 1.
(WebCore::InspectorDOMAgent::requestChildNodes): Add a new optional `depth` parameter
which defaults to 1 and allows -1 as an unbound value.
* inspector/InspectorDOMAgent.h:
(InspectorDOMAgent):
* inspector/front-end/DOMAgent.js:
(WebInspector.DOMNode.prototype.):
(WebInspector.DOMNode.prototype.getSubtree): New method allowing to specify at what depth
we want to retrieve children of a given node from the backend.
* inspector/front-end/ElementsTreeOutline.js:
(WebInspector.ElementsTreeElement.prototype.expandRecursively): Override default implementation
to first obtain the deepest subtree for the current node so that deep expansion happens as expected.

LayoutTests:

Adding a new protocol test that covers the new `depth` parameter for the
requestChildNodes method and a new front-end method that tests correct
behavior of the expandRecursively() method.

Patch by Antoine Quint <[email protected]> on 2013-01-11
Reviewed by Pavel Feldman.

* inspector-protocol/dom-request-child-nodes-depth-expected.txt: Added.
* inspector-protocol/dom-request-child-nodes-depth.html: Added.
* inspector/elements/expand-recursively-expected.txt: Added.
* inspector/elements/expand-recursively.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (139428 => 139429)


--- trunk/LayoutTests/ChangeLog	2013-01-11 12:26:37 UTC (rev 139428)
+++ trunk/LayoutTests/ChangeLog	2013-01-11 12:28:24 UTC (rev 139429)
@@ -1,3 +1,19 @@
+2013-01-11  Antoine Quint  <[email protected]>
+
+        Web Inspector: Option+Click on Node Expander Doesn't Work the First Time
+        https://bugs.webkit.org/show_bug.cgi?id=66868
+
+        Adding a new protocol test that covers the new `depth` parameter for the
+        requestChildNodes method and a new front-end method that tests correct
+        behavior of the expandRecursively() method.
+
+        Reviewed by Pavel Feldman.
+
+        * inspector-protocol/dom-request-child-nodes-depth-expected.txt: Added.
+        * inspector-protocol/dom-request-child-nodes-depth.html: Added.
+        * inspector/elements/expand-recursively-expected.txt: Added.
+        * inspector/elements/expand-recursively.html: Added.
+
 2013-01-11  Noel Gordon  <[email protected]>
 
         [chromium] Add ImageOnlyFailure for fast/css/font-face-unicode-range.html on win

Added: trunk/LayoutTests/inspector/elements/expand-recursively-expected.txt (0 => 139429)


--- trunk/LayoutTests/inspector/elements/expand-recursively-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector/elements/expand-recursively-expected.txt	2013-01-11 12:28:24 UTC (rev 139429)
@@ -0,0 +1,28 @@
+Tests that expanding elements recursively works.
+
+===== Initial state of tree outline =====
+
++ <div id="depth-1">…</div>
+
+===== State of tree outline after calling .expandRecursively() =====
+
+- <div id="depth-1">
+    - <div id="depth-2">
+        - <div id="depth-3">
+            - <div id="depth-4">
+                - <div id="depth-5">
+                    - <div id="depth-6">
+                        - <div id="depth-7">
+                            - <div id="depth-8">
+                                - <div id="depth-9">
+                                      <div id="depth-10"></div>
+                                  </div>
+                              </div>
+                          </div>
+                      </div>
+                  </div>
+              </div>
+          </div>
+      </div>
+  </div>
+

Added: trunk/LayoutTests/inspector/elements/expand-recursively.html (0 => 139429)


--- trunk/LayoutTests/inspector/elements/expand-recursively.html	                        (rev 0)
+++ trunk/LayoutTests/inspector/elements/expand-recursively.html	2013-01-11 12:28:24 UTC (rev 139429)
@@ -0,0 +1,67 @@
+<html>
+<head>
+<script src=""
+<script src=""
+<script>
+
+function test()
+{
+    WebInspector.showPanel("elements");
+    var treeOutline = WebInspector.panels.elements.treeOutline;
+    InspectorTest.findNode(function() { return false; }, firstStep);
+        
+    function firstStep()
+    {
+        InspectorTest.addResult("===== Initial state of tree outline =====\n");
+        dump();
+
+        var topNode = treeOutline.children[0].children[1].children[1];
+        topNode.expandRecursively();
+        InspectorTest.runAfterPendingDispatches(secondStep);
+    };
+        
+    function secondStep()
+    {
+        InspectorTest.addResult("\n===== State of tree outline after calling .expandRecursively() =====\n");
+        dump();
+
+        InspectorTest.completeTest();
+    };
+
+    function dump()
+    {
+        var node = InspectorTest.expandedNodeWithId("depth-1");
+        InspectorTest.dumpElementsTree(node);
+    };
+}
+
+</script>
+</head>
+
+<body _onload_="runTest()">
+<p>
+Tests that expanding elements recursively works.
+</p>
+
+<div id="depth-1">
+    <div id="depth-2">
+        <div id="depth-3">
+            <div id="depth-4">
+                <div id="depth-5">
+                    <div id="depth-6">
+                        <div id="depth-7">
+                            <div id="depth-8">
+                                <div id="depth-9">
+                                    <div id="depth-10"></div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+</body>
+</html>

Added: trunk/LayoutTests/inspector-protocol/dom-request-child-nodes-depth-expected.txt (0 => 139429)


--- trunk/LayoutTests/inspector-protocol/dom-request-child-nodes-depth-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector-protocol/dom-request-child-nodes-depth-expected.txt	2013-01-11 12:28:24 UTC (rev 139429)
@@ -0,0 +1,21 @@
+
+=== Get the Document ===
+
+
+=== Get immediate children of the body ===
+
+PASS: First child is a div
+PASS: First child is div#depth-1
+PASS: First child has one child
+PASS: First child has no .children property
+
+=== Get all children of div#depth-1 ===
+
+PASS: div#depth-1 has nodes 9 levels deep
+
+=== Pass an invalid depth ===
+
+Backend error: Please provide a positive integer as a depth or -1 for entire subtree (-32000)
+
+PASS: Expected number of setChildNodes events
+

Added: trunk/LayoutTests/inspector-protocol/dom-request-child-nodes-depth.html (0 => 139429)


--- trunk/LayoutTests/inspector-protocol/dom-request-child-nodes-depth.html	                        (rev 0)
+++ trunk/LayoutTests/inspector-protocol/dom-request-child-nodes-depth.html	2013-01-11 12:28:24 UTC (rev 139429)
@@ -0,0 +1,140 @@
+<html>
+<head>
+<script type="text/_javascript_" src=""
+<script type="text/_javascript_">
+
+function test()
+{
+
+    var eventsCount = 0;
+
+    getDocument();
+
+    InspectorTest.eventHandler["DOM.setChildNodes"] = function setChildNodes(messageObject)
+    {
+        eventsCount++;
+
+        if (eventsCount === 1)
+            gotImmediateChildren(messageObject);
+        else if (eventsCount === 2)
+            gotAllChildren(messageObject);
+    };
+    
+    function getDocument()
+    {
+        // We must first get the document so that later on we may get sensible nodeIds.
+        step({
+            name: "Get the Document",
+            command: "DOM.getDocument",
+            parameters: {},
+            callback: getImmediateChildren
+        });
+    };
+
+    function getImmediateChildren(result)
+    {
+        var bodyId = result.root.children[0].children[1].nodeId;
+        step({
+            name: "Get immediate children of the body",
+            command: "DOM.requestChildNodes",
+            parameters: {"nodeId": bodyId}
+        });
+    };
+
+    function gotImmediateChildren(messageObject)
+    {
+        var firstChild = messageObject.params.nodes[0];
+        assert("First child is a div", firstChild.localName, "div");
+        assert("First child is div#depth-1", firstChild.attributes[1], "depth-1");
+        assert("First child has one child", firstChild.childNodeCount, 1);
+        assert("First child has no .children property", firstChild.children, undefined);
+
+        step({
+            name: "Get all children of div#depth-1",
+            command: "DOM.requestChildNodes",
+            parameters: {"nodeId": firstChild.nodeId, "depth": -1}
+        });
+    };
+
+    function gotAllChildren(messageObject)
+    {
+        var depth = 1;
+        var firstChild = messageObject.params.nodes[0];
+        var node = firstChild;
+        while (node && node.children) {
+            depth++;
+            node = node.children[0];
+        }
+
+        assert("div#depth-1 has nodes 9 levels deep", depth, 9);
+
+        step({
+            name: "Pass an invalid depth",
+            command: "DOM.requestChildNodes",
+            parameters: {"nodeId": firstChild.nodeId, "depth": 0},
+            callback: finishTest
+        });
+    };
+    
+    function finishTest()
+    {
+        assert("Expected number of setChildNodes events", eventsCount, 2);
+        
+        InspectorTest.completeTest();
+    };
+
+    function step(test)
+    {
+        InspectorTest.log("\n=== " + test.name + " ===\n");
+        InspectorTest.sendCommand(test.command, test.parameters, function(messageObject) {
+            if (messageObject.hasOwnProperty("error"))
+                InspectorTest.log("Backend error: " + messageObject.error.message + " (" + messageObject.error.code + ")\n");
+
+            if (test.callback)
+                test.callback(messageObject.result);
+        });
+    };
+
+    function assert(message, actual, expected)
+    {
+        if (actual === expected)
+            InspectorTest.log("PASS: " + message);
+        else {
+            InspectorTest.log("FAIL: " + message + ", expected \"" + expected + "\" but got \"" + actual + "\"");
+            InspectorTest.completeTest();
+        }
+    };
+
+};
+
+window.addEventListener("DOMContentLoaded", function () {
+    runTest();
+}, false);
+
+</script>
+</head>
+<body>
+
+<div id="depth-1">
+    <div id="depth-2">
+        <div id="depth-3">
+            <div id="depth-4">
+                <div id="depth-5">
+                    <div id="depth-6">
+                        <div id="depth-7">
+                            <div id="depth-8">
+                                <div id="depth-9">
+                                    <div id="depth-10">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (139428 => 139429)


--- trunk/Source/WebCore/ChangeLog	2013-01-11 12:26:37 UTC (rev 139428)
+++ trunk/Source/WebCore/ChangeLog	2013-01-11 12:28:24 UTC (rev 139429)
@@ -1,3 +1,44 @@
+2013-01-11  Antoine Quint  <[email protected]>
+
+        Web Inspector: Option+Click on Node Expander Doesn't Work the First Time
+        https://bugs.webkit.org/show_bug.cgi?id=66868
+
+        Up to now, the TreeElement.prototype.expandRecursively() method would correctly
+        expand children recursively based on the provided depth, but would not wait to
+        perform this task until all child nodes had been populated, which means that this
+        would only work incrementally with one additional level of child nodes being shown
+        expanded in the DOM tree upon alt+clicking a given node with a deep hierarchy.
+        
+        In order to fix this, this patch adds a new optional argument to the DOMAgent's
+        requestChildNodes() methods to provide the depth at which we want to retrieve children
+        of a given node. The DOMAgent provides a new .getSubtree() method that calls
+        requestChildNodes() with the provided depth.
+
+        Then in ElementsTreeOutline, we subclass .expandRecursively() to first call DOMAgent's
+        new .getSubtree() method and then call the default implementation when all nodes
+        have been retrieved from the backend.
+
+        Reviewed by Pavel Feldman.
+
+        Tests: inspector-protocol/dom-request-child-nodes-depth.html
+               inspector/elements/expand-recursively.html
+
+        * inspector/Inspector.json: Add the new `depth` parameter to DOM.requestChildNodes().
+        * inspector/InspectorDOMAgent.cpp:
+        (WebCore::InspectorDOMAgent::pushChildNodesToFrontend): Add a new optional `depth` parameter
+        which defaults to 1.
+        (WebCore::InspectorDOMAgent::requestChildNodes): Add a new optional `depth` parameter
+        which defaults to 1 and allows -1 as an unbound value.
+        * inspector/InspectorDOMAgent.h:
+        (InspectorDOMAgent):
+        * inspector/front-end/DOMAgent.js:
+        (WebInspector.DOMNode.prototype.):
+        (WebInspector.DOMNode.prototype.getSubtree): New method allowing to specify at what depth
+        we want to retrieve children of a given node from the backend.
+        * inspector/front-end/ElementsTreeOutline.js:
+        (WebInspector.ElementsTreeElement.prototype.expandRecursively): Override default implementation
+        to first obtain the deepest subtree for the current node so that deep expansion happens as expected.
+
 2013-01-11  Alexander Pavlov  <[email protected]>
 
         Web Inspector: [Elements] Search in the DOM tree does not scroll horizontally

Modified: trunk/Source/WebCore/inspector/Inspector.json (139428 => 139429)


--- trunk/Source/WebCore/inspector/Inspector.json	2013-01-11 12:26:37 UTC (rev 139428)
+++ trunk/Source/WebCore/inspector/Inspector.json	2013-01-11 12:28:24 UTC (rev 139429)
@@ -1707,9 +1707,10 @@
             {
                 "name": "requestChildNodes",
                 "parameters": [
-                    { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to get children for." }
+                    { "name": "nodeId", "$ref": "NodeId", "description": "Id of the node to get children for." },
+                    { "name": "depth", "type": "integer", "optional": true, "description": "The maximum depth at which children should be retrieved, defaults to 1. Use -1 for the entire subtree or provide an integer larger than 0." }
                 ],
-                "description": "Requests that children of the node with given id are returned to the caller in form of <code>setChildNodes</code> events."
+                "description": "Requests that children of the node with given id are returned to the caller in form of <code>setChildNodes</code> events where not only immediate children are retrieved, but all children down to the specified depth."
             },
             {
                 "name": "querySelector",

Modified: trunk/Source/WebCore/inspector/InspectorDOMAgent.cpp (139428 => 139429)


--- trunk/Source/WebCore/inspector/InspectorDOMAgent.cpp	2013-01-11 12:26:37 UTC (rev 139428)
+++ trunk/Source/WebCore/inspector/InspectorDOMAgent.cpp	2013-01-11 12:28:24 UTC (rev 139429)
@@ -433,7 +433,7 @@
     root = buildObjectForNode(m_document.get(), 2, &m_documentNodeToIdMap);
 }
 
-void InspectorDOMAgent::pushChildNodesToFrontend(int nodeId)
+void InspectorDOMAgent::pushChildNodesToFrontend(int nodeId, int depth)
 {
     Node* node = nodeForId(nodeId);
     if (!node || (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE && node->nodeType() != Node::DOCUMENT_FRAGMENT_NODE))
@@ -442,7 +442,7 @@
         return;
 
     NodeToIdMap* nodeMap = m_idToNodesMap.get(nodeId);
-    RefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > children = buildArrayForContainerChildren(node, 1, nodeMap);
+    RefPtr<TypeBuilder::Array<TypeBuilder::DOM::Node> > children = buildArrayForContainerChildren(node, depth, nodeMap);
     m_frontend->setChildNodes(nodeId, children.release());
 }
 
@@ -478,9 +478,22 @@
     return 0;
 }
 
-void InspectorDOMAgent::requestChildNodes(ErrorString*, int nodeId)
+void InspectorDOMAgent::requestChildNodes(ErrorString* errorString, int nodeId, const int* depth)
 {
-    pushChildNodesToFrontend(nodeId);
+    int sanitizedDepth;
+
+    if (!depth)
+        sanitizedDepth = 1;
+    else if (*depth == -1)
+        sanitizedDepth = INT_MAX;
+    else if (*depth > 0)
+        sanitizedDepth = *depth;
+    else {
+        *errorString = "Please provide a positive integer as a depth or -1 for entire subtree";
+        return;
+    }
+
+    pushChildNodesToFrontend(nodeId, sanitizedDepth);
 }
 
 void InspectorDOMAgent::querySelector(ErrorString* errorString, int nodeId, const String& selectors, int* elementId)

Modified: trunk/Source/WebCore/inspector/InspectorDOMAgent.h (139428 => 139429)


--- trunk/Source/WebCore/inspector/InspectorDOMAgent.h	2013-01-11 12:26:37 UTC (rev 139428)
+++ trunk/Source/WebCore/inspector/InspectorDOMAgent.h	2013-01-11 12:28:24 UTC (rev 139429)
@@ -122,7 +122,7 @@
     virtual void querySelector(ErrorString*, int nodeId, const String& selectors, int* elementId);
     virtual void querySelectorAll(ErrorString*, int nodeId, const String& selectors, RefPtr<TypeBuilder::Array<int> >& result);
     virtual void getDocument(ErrorString*, RefPtr<TypeBuilder::DOM::Node>& root);
-    virtual void requestChildNodes(ErrorString*, int nodeId);
+    virtual void requestChildNodes(ErrorString*, int nodeId, const int* depth);
     virtual void setAttributeValue(ErrorString*, int elementId, const String& name, const String& value);
     virtual void setAttributesAsText(ErrorString*, int elementId, const String& text, const String* name);
     virtual void removeAttribute(ErrorString*, int elementId, const String& name);
@@ -218,7 +218,7 @@
     Element* assertEditableElement(ErrorString*, int nodeId);
 
     int pushNodePathToFrontend(Node*);
-    void pushChildNodesToFrontend(int nodeId);
+    void pushChildNodesToFrontend(int nodeId, int depth = 1);
 
     bool hasBreakpoint(Node*, int type);
     void updateSubtreeBreakpoints(Node* root, uint32_t rootMask, bool value);

Modified: trunk/Source/WebCore/inspector/front-end/DOMAgent.js (139428 => 139429)


--- trunk/Source/WebCore/inspector/front-end/DOMAgent.js	2013-01-11 12:26:37 UTC (rev 139428)
+++ trunk/Source/WebCore/inspector/front-end/DOMAgent.js	2013-01-11 12:28:24 UTC (rev 139429)
@@ -301,6 +301,25 @@
     },
 
     /**
+     * @param {number} depth
+     * @param {function(Array.<WebInspector.DOMNode>)=} callback
+     */
+    getSubtree: function(depth, callback)
+    {
+        /**
+         * @this {WebInspector.DOMNode}
+         * @param {?Protocol.Error} error
+         */
+        function mycallback(error)
+        {
+            if (callback)
+                callback(error ? null : this.children);                
+        }
+
+        DOMAgent.requestChildNodes(this.id, depth, mycallback.bind(this));
+    },
+
+    /**
      * @param {function(?Protocol.Error)=} callback
      */
     getOuterHTML: function(callback)

Modified: trunk/Source/WebCore/inspector/front-end/ElementsTreeOutline.js (139428 => 139429)


--- trunk/Source/WebCore/inspector/front-end/ElementsTreeOutline.js	2013-01-11 12:26:37 UTC (rev 139428)
+++ trunk/Source/WebCore/inspector/front-end/ElementsTreeOutline.js	2013-01-11 12:28:24 UTC (rev 139429)
@@ -1048,6 +1048,16 @@
         this.expandedChildrenLimit = Math.max(this.representedObject._childNodeCount, this.expandedChildrenLimit + WebInspector.ElementsTreeElement.InitialChildrenLimit);
     },
 
+    expandRecursively: function()
+    {
+        function callback()
+        {
+            TreeElement.prototype.expandRecursively.call(this, Number.MAX_VALUE);
+        }
+        
+        this.representedObject.getSubtree(-1, callback.bind(this));
+    },
+
     onexpand: function()
     {
         if (this._elementCloseTag)
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to