Fixes the hang that could happen when option-clicking to expand
authortimothy@apple.com <timothy@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 13 May 2008 22:31:11 +0000 (22:31 +0000)
committertimothy@apple.com <timothy@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 13 May 2008 22:31:11 +0000 (22:31 +0000)
a disclosure triangle in the Properties pane. This change limits
the recursion depth when expanding the tree elements.

<rdar://problem/5847681> Safari hangs when option-clicking a
disclosure triangle in the Inspector's Properties pane

Reviewed by John Sullivan.

* page/inspector/treeoutline.js:
(TreeElement.prototype.expandRecursively): Pass an empty info object to
traverseNextTreeElement to get the depthChange value. This is used to
compute a current depth. If the depth exceeds the maxDepth argument, the
item isn't expanded and children wont be populated when traverseNextTreeElement
is called until the depth goes below the maxDepth.
(TreeElement.prototype.traverseNextTreeElement): Added a new info
argument that can be optionally used to return extra info like depth change.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@33413 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/page/inspector/treeoutline.js

index 010950a..b9b5103 100644 (file)
@@ -1,5 +1,25 @@
 2008-05-13  Timothy Hatcher  <timothy@apple.com>
 
+        Fixes the hang that could happen when option-clicking to expand
+        a disclosure triangle in the Properties pane. This change limits
+        the recursion depth when expanding the tree elements.
+
+        <rdar://problem/5847681> Safari hangs when option-clicking a
+        disclosure triangle in the Inspector's Properties pane
+
+        Reviewed by John Sullivan.
+
+        * page/inspector/treeoutline.js:
+        (TreeElement.prototype.expandRecursively): Pass an empty info object to
+        traverseNextTreeElement to get the depthChange value. This is used to
+        compute a current depth. If the depth exceeds the maxDepth argument, the
+        item isn't expanded and children wont be populated when traverseNextTreeElement
+        is called until the depth goes below the maxDepth.
+        (TreeElement.prototype.traverseNextTreeElement): Added a new info
+        argument that can be optionally used to return extra info like depth change.
+
+2008-05-13  Timothy Hatcher  <timothy@apple.com>
+
         Adds info text to panes and sections in the Inspector's sidebars
         that would normally be empty. These help the user know why there
         is nothing in these sections.
index 1248055..bd032c3 100644 (file)
@@ -637,12 +637,23 @@ TreeElement.prototype.expand = function()
         this.onexpand(this);
 }
 
-TreeElement.prototype.expandRecursively = function()
+TreeElement.prototype.expandRecursively = function(maxDepth)
 {
     var item = this;
+    var info = {};
+    var depth = 0;
+
+    // The Inspector uses TreeOutlines to represents object properties, so recursive expansion
+    // in some case can be infinite, since JavaScript objects can hold circular references.
+    // So default to a recursion cap of 3 levels, since that gives fairly good results.
+    if (typeof maxDepth === "undefined" || typeof maxDepth === "null")
+        maxDepth = 3;
+
     while (item) {
-        item.expand();
-        item = item.traverseNextTreeElement(false, this);
+        if (depth < maxDepth)
+            item.expand();
+        item = item.traverseNextTreeElement(false, this, (depth >= maxDepth), info);
+        depth += info.depthChange;
     }
 }
 
@@ -702,14 +713,20 @@ TreeElement.prototype.deselect = function(supressOnDeselect)
         this.ondeselect(this);
 }
 
-TreeElement.prototype.traverseNextTreeElement = function(skipHidden, stayWithin, dontPopulate)
+TreeElement.prototype.traverseNextTreeElement = function(skipHidden, stayWithin, dontPopulate, info)
 {
     if (!dontPopulate && this.hasChildren && this.onpopulate)
         this.onpopulate(this);
 
+    if (info)
+        info.depthChange = 0;
+
     var element = skipHidden ? (this.revealed() ? this.children[0] : null) : this.children[0];
-    if (element && (!skipHidden || (skipHidden && this.expanded)))
+    if (element && (!skipHidden || (skipHidden && this.expanded))) {
+        if (info)
+            info.depthChange = 1;
         return element;
+    }
 
     if (this === stayWithin)
         return null;
@@ -719,8 +736,11 @@ TreeElement.prototype.traverseNextTreeElement = function(skipHidden, stayWithin,
         return element;
 
     element = this;
-    while (element && !element.root && !(skipHidden ? (element.revealed() ? element.nextSibling : null) : element.nextSibling) && element.parent !== stayWithin)
+    while (element && !element.root && !(skipHidden ? (element.revealed() ? element.nextSibling : null) : element.nextSibling) && element.parent !== stayWithin) {
+        if (info)
+            info.depthChange -= 1;
         element = element.parent;
+    }
 
     if (!element)
         return null;