Title: [288243] trunk/Source/WebInspectorUI
Revision
288243
Author
drou...@apple.com
Date
2022-01-19 14:38:19 -0800 (Wed, 19 Jan 2022)

Log Message

Web Inspector: blackboxed call frames should be grouped everywhere
https://bugs.webkit.org/show_bug.cgi?id=234648
<rdar://problem/87018103>

Reviewed by Patrick Angle.

* UserInterface/Controllers/CallFrameTreeController.js:
(WI.CallFrameTreeController.prototype.groupBlackboxedCallFrames): Added.
(WI.CallFrameTreeController.prototype.groupBlackboxedCallFrames.displayable): Added.
(WI.CallFrameTreeController.prototype.set callFrames): Added.
* UserInterface/Views/StackTraceView.js:
(WI.StackTraceView):
* UserInterface/Views/ThreadTreeElement.js:
(WI.ThreadTreeElement.prototype.refresh):
* UserInterface/Views/TimelineDataGrid.js:
(WI.TimelineDataGrid.prototype._createPopoverContent):
(WI.TimelineDataGrid.prototype._popoverCallStackTreeElementRemoved):
Centralize code for creating stack trace views so that the logic that groups blackboxed call
frames (and the associated `WI.BlackboxedGroupTreeElement`/`WI.BlackboxedGroupView`) can be
shared without duplication.

* UserInterface/Views/BlackboxedGroupTreeElement.js:
(WI.BlackboxedGroupTreeElement):
(WI.BlackboxedGroupTreeElement.prototype.expand):
(WI.BlackboxedGroupTreeElement.prototype.customTitleTooltip): Added.
Add a parameter to control whether to remember when expanding blackboxed call frame groups
so that they can later be auto-expanded. This is needed because that feature is intended so
that stepping doesn't re-collapse previously expanded blackboxed call frame groups. A more
technical reason is that non-debugging call stacks can live (i.e. be shown) for a long time
and therefore there's no good way to clear the remembered state, and we probably don't want
to have a previous expansion in the Timelines Tab or Canvas Tab suddenly cause all matching
blackboxed call frame groups in the Sources Tab to always be expanded.
Drive-by: Override the tooltip to explain that clicking shows the blackboxed call frames.

* UserInterface/Views/BlackboxedGroupView.js: Added.
(WI.BlackboxedGroupView):
(WI.BlackboxedGroupView.generateTitle):
(WI.BlackboxedGroupView.generateSubtitle):
(WI.BlackboxedGroupView.generateTooltip):
* UserInterface/Views/BlackboxedGroupView.css: Added.
(.blackboxed-group):
(.blackboxed-group > *):
(.blackboxed-group .icon):
(.blackboxed-group .subtitle):
(.blackboxed-group .separator):
(@media (prefers-color-scheme: dark) .blackboxed-group .icon):
(@media (prefers-color-scheme: dark) .blackboxed-group .subtitle):
(@media (prefers-color-scheme: dark) .blackboxed-group .separator):
Add a non-tree UI class for showing blackboxed call frame groups (just like how there's
`WI.CallFrameTreeElement` for tree UIs and `WI.CallFrameView` for non-tree UIs). Also
centralize the UI strings for all blackboxed call frame group UIs as `static` methods.

* UserInterface/Views/BlackboxedGroupTreeElement.css:
(.tree-outline .item.blackboxed-group.selected > *): Added.
(.tree-outline:not(:focus-within) .item.blackboxed-group.selected > *, body:is(.window-inactive, .window-docked-inactive) .tree-outline .item.blackboxed-group.selected > *): Added.
(.tree-outline .item.blackboxed-group): Deleted.
(.tree-outline .item.blackboxed-group:not(.selected) > *, .tree-outline:not(:focus-within) .item.blackboxed-group.selected > *, body:is(.window-inactive, .window-docked-inactive) .tree-outline .item.blackboxed-group.selected > *): Deleted.
(.tree-outline .item.blackboxed-group .icon): Deleted.
(@media (prefers-color-scheme: dark) .tree-outline .item.blackboxed-group .icon): Deleted.
Share styles from `UserInterface/Views/BlackboxedGroupView.css` since both share `.blackboxed-group`.

* UserInterface/Views/CallFrameTreeElement.js:
Drive-by: Combine optional parameters into an `options = {}` for current code cleanliness
          and greater flexibility for future changes.

* UserInterface/Views/Variables.css:
(:root):
* UserInterface/Views/CallFrameTreeElement.css:
(.tree-outline .item.call-frame.blackboxed:not(.selected)):
* UserInterface/Views/CallFrameView.css:
(.call-frame.blackboxed > .title,):
Drive-by: Rename `--blackboxed-tree-item-opacity` since it's now also used outside trees.

* UserInterface/Main.html:
* Localizations/en.lproj/localizedStrings.js:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebInspectorUI/ChangeLog (288242 => 288243)


--- trunk/Source/WebInspectorUI/ChangeLog	2022-01-19 22:28:13 UTC (rev 288242)
+++ trunk/Source/WebInspectorUI/ChangeLog	2022-01-19 22:38:19 UTC (rev 288243)
@@ -1,3 +1,81 @@
+2022-01-19  Devin Rousso  <drou...@apple.com>
+
+        Web Inspector: blackboxed call frames should be grouped everywhere
+        https://bugs.webkit.org/show_bug.cgi?id=234648
+        <rdar://problem/87018103>
+
+        Reviewed by Patrick Angle.
+
+        * UserInterface/Controllers/CallFrameTreeController.js:
+        (WI.CallFrameTreeController.prototype.groupBlackboxedCallFrames): Added.
+        (WI.CallFrameTreeController.prototype.groupBlackboxedCallFrames.displayable): Added.
+        (WI.CallFrameTreeController.prototype.set callFrames): Added.
+        * UserInterface/Views/StackTraceView.js:
+        (WI.StackTraceView):
+        * UserInterface/Views/ThreadTreeElement.js:
+        (WI.ThreadTreeElement.prototype.refresh):
+        * UserInterface/Views/TimelineDataGrid.js:
+        (WI.TimelineDataGrid.prototype._createPopoverContent):
+        (WI.TimelineDataGrid.prototype._popoverCallStackTreeElementRemoved):
+        Centralize code for creating stack trace views so that the logic that groups blackboxed call
+        frames (and the associated `WI.BlackboxedGroupTreeElement`/`WI.BlackboxedGroupView`) can be
+        shared without duplication.
+
+        * UserInterface/Views/BlackboxedGroupTreeElement.js:
+        (WI.BlackboxedGroupTreeElement):
+        (WI.BlackboxedGroupTreeElement.prototype.expand):
+        (WI.BlackboxedGroupTreeElement.prototype.customTitleTooltip): Added.
+        Add a parameter to control whether to remember when expanding blackboxed call frame groups
+        so that they can later be auto-expanded. This is needed because that feature is intended so
+        that stepping doesn't re-collapse previously expanded blackboxed call frame groups. A more
+        technical reason is that non-debugging call stacks can live (i.e. be shown) for a long time
+        and therefore there's no good way to clear the remembered state, and we probably don't want
+        to have a previous expansion in the Timelines Tab or Canvas Tab suddenly cause all matching
+        blackboxed call frame groups in the Sources Tab to always be expanded.
+        Drive-by: Override the tooltip to explain that clicking shows the blackboxed call frames.
+
+        * UserInterface/Views/BlackboxedGroupView.js: Added.
+        (WI.BlackboxedGroupView):
+        (WI.BlackboxedGroupView.generateTitle):
+        (WI.BlackboxedGroupView.generateSubtitle):
+        (WI.BlackboxedGroupView.generateTooltip):
+        * UserInterface/Views/BlackboxedGroupView.css: Added.
+        (.blackboxed-group):
+        (.blackboxed-group > *):
+        (.blackboxed-group .icon):
+        (.blackboxed-group .subtitle):
+        (.blackboxed-group .separator):
+        (@media (prefers-color-scheme: dark) .blackboxed-group .icon):
+        (@media (prefers-color-scheme: dark) .blackboxed-group .subtitle):
+        (@media (prefers-color-scheme: dark) .blackboxed-group .separator):
+        Add a non-tree UI class for showing blackboxed call frame groups (just like how there's
+        `WI.CallFrameTreeElement` for tree UIs and `WI.CallFrameView` for non-tree UIs). Also
+        centralize the UI strings for all blackboxed call frame group UIs as `static` methods.
+
+        * UserInterface/Views/BlackboxedGroupTreeElement.css:
+        (.tree-outline .item.blackboxed-group.selected > *): Added.
+        (.tree-outline:not(:focus-within) .item.blackboxed-group.selected > *, body:is(.window-inactive, .window-docked-inactive) .tree-outline .item.blackboxed-group.selected > *): Added.
+        (.tree-outline .item.blackboxed-group): Deleted.
+        (.tree-outline .item.blackboxed-group:not(.selected) > *, .tree-outline:not(:focus-within) .item.blackboxed-group.selected > *, body:is(.window-inactive, .window-docked-inactive) .tree-outline .item.blackboxed-group.selected > *): Deleted.
+        (.tree-outline .item.blackboxed-group .icon): Deleted.
+        (@media (prefers-color-scheme: dark) .tree-outline .item.blackboxed-group .icon): Deleted.
+        Share styles from `UserInterface/Views/BlackboxedGroupView.css` since both share `.blackboxed-group`.
+
+        * UserInterface/Views/CallFrameTreeElement.js:
+        Drive-by: Combine optional parameters into an `options = {}` for current code cleanliness
+                  and greater flexibility for future changes.
+
+        * UserInterface/Views/Variables.css:
+        (:root):
+        * UserInterface/Views/CallFrameTreeElement.css:
+        (.tree-outline .item.call-frame.blackboxed:not(.selected)):
+        * UserInterface/Views/CallFrameView.css:
+        (.call-frame.blackboxed > .title,):
+        Drive-by: Rename `--blackboxed-tree-item-opacity` since it's now also used outside trees.
+
+        * UserInterface/Main.html:
+        * Localizations/en.lproj/localizedStrings.js:
+
 2022-01-18  Alex Christensen  <achristen...@webkit.org>
 
         Use c++2a instead of gnu++2a for Cocoa builds

Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (288242 => 288243)


--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2022-01-19 22:28:13 UTC (rev 288242)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2022-01-19 22:38:19 UTC (rev 288243)
@@ -327,6 +327,10 @@
 localizedStrings["Click to show %d errors in the Console"] = "Click to show %d errors in the Console";
 localizedStrings["Click to show %d warning in the Console"] = "Click to show %d warning in the Console";
 localizedStrings["Click to show %d warnings in the Console"] = "Click to show %d warnings in the Console";
+/* Tooltip for the 'Blackboxed - %d call frame' label shown in the debugger call stack when paused instead of subsequent call frames that have been blackboxed. */
+localizedStrings["Click to show blackboxed call frame @ Debugger Call Stack"] = "Click to show %d blackboxed call frame";
+/* Tooltip for the 'Blackboxed - %d call frames' label shown in the debugger call stack when paused instead of subsequent call frames that have been blackboxed. */
+localizedStrings["Click to show blackboxed call frames @ Debugger Call Stack"] = "Click to show %d blackboxed call frames";
 /* Tooltip to show purpose of the CSS documentation button */
 localizedStrings["Click to show documentation @ CSS Documentation Button"] = "Click to show documentation";
 localizedStrings["Click to view variable value\nShift-click to replace variable with value"] = "Click to view variable value\nShift-click to replace variable with value";

Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/CallFrameTreeController.js (288242 => 288243)


--- trunk/Source/WebInspectorUI/UserInterface/Controllers/CallFrameTreeController.js	2022-01-19 22:28:13 UTC (rev 288242)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/CallFrameTreeController.js	2022-01-19 22:38:19 UTC (rev 288243)
@@ -39,6 +39,75 @@
             this._treeOutline.addEventListener(WI.TreeOutline.Event.ElementClicked, this._treeElementClicked, this);
     }
 
+    // Static
+
+    static groupBlackboxedCallFrames(parent, callFrames, {rememberBlackboxedCallFrameGroupToAutoExpand} = {})
+    {
+        let parentIsNode = parent instanceof Node;
+        console.assert(parentIsNode || parent instanceof WI.TreeOutline || parent instanceof WI.TreeElement, parent);
+        console.assert(Array.isArray(callFrames) && callFrames.length && callFrames.every((callFrame) => callFrame instanceof WI.CallFrame), callFrames);
+
+        let BlackboxedGroupUIClass = parentIsNode ? WI.BlackboxedGroupView : WI.BlackboxedGroupTreeElement;
+        let blackboxedGroupUIOptions = {rememberBlackboxedCallFrameGroupToAutoExpand};
+
+        let CallFrameUIClass = parentIsNode ? WI.CallFrameView : WI.CallFrameTreeElement;
+        let callFrameUIOptions = {showFunctionName: true, indicateIfBlackboxed: true};
+
+        let activeCallFrame = WI.debuggerManager.activeCallFrame;
+        let activeCallFrameTreeElement = null;
+
+        let blackboxedCallFrameGroupStartIndex = undefined;
+
+        function displayable(callFrame) {
+            if (parentIsNode) {
+                if (!callFrame.sourceCodeLocation && callFrame.functionName === null)
+                    return false;
+
+                if (callFrame.isConsoleEvaluation && !WI.settings.debugShowConsoleEvaluations.value)
+                    return false;
+            }
+
+            return true;
+        }
+
+        // Add one extra iteration to handle call stacks that start blackboxed.
+        for (let i = 0; i < callFrames.length + 1; ++i) {
+            let callFrame = callFrames[i];
+
+            if (callFrame) {
+                if (!displayable(callFrame))
+                    continue;
+
+                if (callFrame.blackboxed && WI.settings.experimentalCollapseBlackboxedCallFrames.value) {
+                    blackboxedCallFrameGroupStartIndex ??= i;
+                    continue;
+                }
+            }
+
+            if (blackboxedCallFrameGroupStartIndex !== undefined) {
+                let blackboxedCallFrameGroup = callFrames.slice(blackboxedCallFrameGroupStartIndex, i).filter(displayable);
+                blackboxedCallFrameGroupStartIndex = undefined;
+
+                if (!rememberBlackboxedCallFrameGroupToAutoExpand || !WI.debuggerManager.shouldAutoExpandBlackboxedCallFrameGroup(blackboxedCallFrameGroup))
+                    parent.appendChild(new BlackboxedGroupUIClass(blackboxedCallFrameGroup, blackboxedGroupUIOptions));
+                else {
+                    for (let blackboxedCallFrame of blackboxedCallFrameGroup)
+                        parent.appendChild(new CallFrameUIClass(blackboxedCallFrame, callFrameUIOptions));
+                }
+            }
+
+            if (!callFrame)
+                continue;
+
+            let callFrameTreeElement = new CallFrameUIClass(callFrame, callFrameUIOptions);
+            if (callFrame === activeCallFrame && !parentIsNode)
+                activeCallFrameTreeElement = callFrameTreeElement;
+            parent.appendChild(callFrameTreeElement);
+        }
+
+        return activeCallFrameTreeElement;
+    }
+
     // Public
 
     get treeOutline() { return this._treeOutline; }
@@ -58,8 +127,7 @@
 
         this._treeOutline.removeChildren();
 
-        for (let callFrame of this._callFrames)
-            this._treeOutline.appendChild(new WI.CallFrameTreeElement(callFrame));
+        WI.CallFrameTreeController.groupBlackboxedCallFrames(this._treeOutline, this._callFrames);
     }
 
     disconnect()

Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (288242 => 288243)


--- trunk/Source/WebInspectorUI/UserInterface/Main.html	2022-01-19 22:28:13 UTC (rev 288242)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html	2022-01-19 22:38:19 UTC (rev 288243)
@@ -47,6 +47,7 @@
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
+    <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
@@ -638,6 +639,7 @@
     <script src=""
     <script src=""
     <script src=""
+    <script src=""
     <script src=""
     <script src=""
     <script src=""

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/BlackboxedGroupTreeElement.css (288242 => 288243)


--- trunk/Source/WebInspectorUI/UserInterface/Views/BlackboxedGroupTreeElement.css	2022-01-19 22:28:13 UTC (rev 288242)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/BlackboxedGroupTreeElement.css	2022-01-19 22:38:19 UTC (rev 288243)
@@ -23,26 +23,17 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-.tree-outline .item.blackboxed-group {
-    cursor: pointer;
+/* Styles shared with `WI.BlackboxedGroupView`. */
+
+.tree-outline .item.blackboxed-group.selected > * {
+    opacity: unset;
 }
 
-.tree-outline .item.blackboxed-group:not(.selected) > *,
 .tree-outline:not(:focus-within) .item.blackboxed-group.selected > *,
 body:is(.window-inactive, .window-docked-inactive) .tree-outline .item.blackboxed-group.selected > * {
-    opacity: var(--blackboxed-tree-item-opacity);
+    opacity: var(--blackboxed-opacity);
 }
 
-.tree-outline .item.blackboxed-group .icon {
-    content: url(../Images/Hide.svg#black);
-}
-
 body:not(.window-inactive, .window-docked-inactive) .tree-outline:focus-within .item.blackboxed-group.selected .icon {
     content: url(../Images/Hide.svg#white);
 }
-
-@media (prefers-color-scheme: dark) {
-    .tree-outline .item.blackboxed-group .icon {
-        content: url(../Images/Hide.svg#white);
-    }
-}

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/BlackboxedGroupTreeElement.js (288242 => 288243)


--- trunk/Source/WebInspectorUI/UserInterface/Views/BlackboxedGroupTreeElement.js	2022-01-19 22:28:13 UTC (rev 288242)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/BlackboxedGroupTreeElement.js	2022-01-19 22:38:19 UTC (rev 288243)
@@ -25,22 +25,17 @@
 
 WI.BlackboxedGroupTreeElement = class BlackboxedGroupTreeElement extends WI.GeneralTreeElement
 {
-    constructor(callFrames)
+    constructor(callFrames, {rememberBlackboxedCallFrameGroupToAutoExpand} = {})
     {
-        console.assert(!WI.debuggerManager.shouldAutoExpandBlackboxedCallFrameGroup(callFrames), callFrames);
+        console.assert(!rememberBlackboxedCallFrameGroupToAutoExpand || !WI.debuggerManager.shouldAutoExpandBlackboxedCallFrameGroup(callFrames), callFrames);
 
         const classNames = ["blackboxed-group"];
-        const title = WI.UIString("Blackboxed", "Blackboxed @ Debugger Call Stack", "Part of the 'Blackboxed - %d call frames' label shown in the debugger call stack when paused instead of subsequent call frames that have been blackboxed.");
-        let subtitle;
-        if (callFrames.length === 1)
-            subtitle = WI.UIString("%d call frame", "call frame @ Debugger Call Stack", "Part of the 'Blackboxed - %d call frame' label shown in the debugger call stack when paused instead of subsequent call frames that have been blackboxed.").format(callFrames.length);
-        else
-            subtitle = WI.UIString("%d call frames", "call frames @ Debugger Call Stack", "Part of the 'Blackboxed - %d call frames' label shown in the debugger call stack when paused instead of subsequent call frames that have been blackboxed.").format(callFrames.length);
+        super(classNames, WI.BlackboxedGroupView.generateTitle(callFrames), WI.BlackboxedGroupView.generateSubtitle(callFrames));
 
-        super(classNames, title, subtitle);
+        this.toggleOnClick = true;
 
-        this.toggleOnClick = true;
         this._callFrames = callFrames;
+        this._rememberBlackboxedCallFrameGroupToAutoExpand = rememberBlackboxedCallFrameGroupToAutoExpand || false;
     }
 
     // Public
@@ -54,7 +49,8 @@
 
     expand()
     {
-        WI.debuggerManager.rememberBlackboxedCallFrameGroupToAutoExpand(this._callFrames);
+        if (this._rememberBlackboxedCallFrameGroupToAutoExpand)
+            WI.debuggerManager.rememberBlackboxedCallFrameGroupToAutoExpand(this._callFrames);
 
         let index = this.parent.children.indexOf(this);
         for (let i = this._callFrames.length - 1; i >= 0; --i)
@@ -74,4 +70,11 @@
         this.expand();
         return true;
     }
+
+    // Protected
+
+    customTitleTooltip()
+    {
+        return WI.BlackboxedGroupView.generateTooltip(this._callFrames);
+    }
 };

Copied: trunk/Source/WebInspectorUI/UserInterface/Views/BlackboxedGroupView.css (from rev 288241, trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameView.css) (0 => 288243)


--- trunk/Source/WebInspectorUI/UserInterface/Views/BlackboxedGroupView.css	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/BlackboxedGroupView.css	2022-01-19 22:38:19 UTC (rev 288243)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2022 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Styles shared with `WI.BlackboxedGroupTreeElement`. */
+
+.blackboxed-group {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    cursor: pointer;
+}
+
+.blackboxed-group > * {
+    opacity: var(--blackboxed-opacity);
+}
+
+.blackboxed-group .icon {
+    display: inline-block;
+    width: 16px;
+    height: 16px;
+    margin-inline-end: 3px;
+    vertical-align: top;
+    content: url(../Images/Hide.svg#black);
+}
+
+.blackboxed-group .subtitle {
+    color: hsla(0, 0%, 0%, 0.6);
+    text-decoration: none;
+}
+
+.blackboxed-group .separator {
+    white-space: nowrap;
+    color: hsla(0, 0%, 0%, 0.2);
+}
+
+@media (prefers-color-scheme: dark) {
+    .blackboxed-group .icon {
+        content: url(../Images/Hide.svg#white);
+    }
+
+    .blackboxed-group .subtitle {
+        color: hsla(0, 0%, var(--foreground-lightness), 0.6);
+    }
+
+    .blackboxed-group .separator {
+        color: hsla(0, 0%, var(--foreground-lightness), 0.2);
+    }
+}

Added: trunk/Source/WebInspectorUI/UserInterface/Views/BlackboxedGroupView.js (0 => 288243)


--- trunk/Source/WebInspectorUI/UserInterface/Views/BlackboxedGroupView.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/BlackboxedGroupView.js	2022-01-19 22:38:19 UTC (rev 288243)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2022 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WI.BlackboxedGroupView = class BlackboxedGroupView
+{
+    constructor(callFrames)
+    {
+        console.assert(Array.isArray(callFrames) && callFrames.length && callFrames.every((callFrame) => callFrame instanceof WI.CallFrame), callFrames);
+
+        let element = document.createElement("div");
+        element.className = "blackboxed-group";
+        element.title = WI.BlackboxedGroupView.generateTooltip(callFrames);
+        element.addEventListener("click", (event) => {
+            const options = {showFunctionName: true, indicateIfBlackboxed: true};
+            for (let i = callFrames.length - 1; i >= 0; --i)
+                element.parentElement.insertBefore(new WI.CallFrameView(callFrames[i], options), element);
+
+            element.remove();
+        });
+
+        let titleElement = element.appendChild(document.createElement("span"));
+        titleElement.className = "title";
+
+        let iconElement = titleElement.appendChild(document.createElement("img"));
+        iconElement.className = "icon";
+
+        titleElement.append(WI.BlackboxedGroupView.generateTitle(callFrames));
+
+        let subtitleElement = element.appendChild(document.createElement("span"));
+        subtitleElement.className = "subtitle";
+
+        let separatorElement = subtitleElement.appendChild(document.createElement("span"));
+        separatorElement.className = "separator";
+        separatorElement.textContent = " " + emDash + " ";
+
+        subtitleElement.append(WI.BlackboxedGroupView.generateSubtitle(callFrames));
+
+        return element;
+    }
+
+    // Static
+
+    static generateTitle(callFrames)
+    {
+        return WI.UIString("Blackboxed", "Blackboxed @ Debugger Call Stack", "Part of the 'Blackboxed - %d call frames' label shown in the debugger call stack when paused instead of subsequent call frames that have been blackboxed.");
+    }
+
+    static generateSubtitle(callFrames)
+    {
+        if (callFrames.length === 1)
+            return WI.UIString("%d call frame", "call frame @ Debugger Call Stack", "Part of the 'Blackboxed - %d call frame' label shown in the debugger call stack when paused instead of subsequent call frames that have been blackboxed.").format(callFrames.length);
+
+        return WI.UIString("%d call frames", "call frames @ Debugger Call Stack", "Part of the 'Blackboxed - %d call frames' label shown in the debugger call stack when paused instead of subsequent call frames that have been blackboxed.").format(callFrames.length);
+    }
+
+    static generateTooltip(callFrames)
+    {
+        if (callFrames.length === 1)
+            return WI.UIString("Click to show %d blackboxed call frame", "Click to show blackboxed call frame @ Debugger Call Stack", "Tooltip for the 'Blackboxed - %d call frame' label shown in the debugger call stack when paused instead of subsequent call frames that have been blackboxed.").format(callFrames.length);
+
+        return WI.UIString("Click to show %d blackboxed call frames", "Click to show blackboxed call frames @ Debugger Call Stack", "Tooltip for the 'Blackboxed - %d call frames' label shown in the debugger call stack when paused instead of subsequent call frames that have been blackboxed.").format(callFrames.length);
+    }
+};

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameTreeElement.css (288242 => 288243)


--- trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameTreeElement.css	2022-01-19 22:28:13 UTC (rev 288242)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameTreeElement.css	2022-01-19 22:38:19 UTC (rev 288243)
@@ -99,5 +99,5 @@
 }
 
 .tree-outline .item.call-frame.blackboxed:not(.selected) {
-    opacity: var(--blackboxed-tree-item-opacity);
+    opacity: var(--blackboxed-opacity);
 }

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameTreeElement.js (288242 => 288243)


--- trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameTreeElement.js	2022-01-19 22:28:13 UTC (rev 288242)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameTreeElement.js	2022-01-19 22:38:19 UTC (rev 288243)
@@ -25,7 +25,7 @@
 
 WI.CallFrameTreeElement = class CallFrameTreeElement extends WI.GeneralTreeElement
 {
-    constructor(callFrame, isAsyncBoundaryCallFrame)
+    constructor(callFrame, {isAsyncBoundaryCallFrame} = {})
     {
         console.assert(callFrame instanceof WI.CallFrame);
 
@@ -37,7 +37,7 @@
         this._callFrame = callFrame;
         this._isActiveCallFrame = false;
 
-        this._isAsyncBoundaryCallFrame = isAsyncBoundaryCallFrame;
+        this._isAsyncBoundaryCallFrame = isAsyncBoundaryCallFrame || false;
          if (this._isAsyncBoundaryCallFrame) {
             this.addClassName("async-boundary");
             this.selectable = false;

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameView.css (288242 => 288243)


--- trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameView.css	2022-01-19 22:28:13 UTC (rev 288242)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameView.css	2022-01-19 22:38:19 UTC (rev 288243)
@@ -32,7 +32,7 @@
 
 .call-frame.blackboxed > .title,
 .call-frame.blackboxed:not(:hover, :focus) > .subtitle {
-    opacity: var(--blackboxed-tree-item-opacity);
+    opacity: var(--blackboxed-opacity);
 }
 
 .call-frame .icon {

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/StackTraceView.js (288242 => 288243)


--- trunk/Source/WebInspectorUI/UserInterface/Views/StackTraceView.js	2022-01-19 22:28:13 UTC (rev 288242)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/StackTraceView.js	2022-01-19 22:38:19 UTC (rev 288243)
@@ -32,15 +32,7 @@
         var element = this._element = document.createElement("div");
         element.classList.add("stack-trace");
 
-        for (var callFrame of stackTrace.callFrames) {
-            if (!callFrame.sourceCodeLocation && callFrame.functionName === null)
-                continue;
-            if (callFrame.isConsoleEvaluation && !WI.settings.debugShowConsoleEvaluations.value)
-                continue;
-
-            let callFrameElement = new WI.CallFrameView(callFrame, {showFunctionName: true, indicateIfBlackboxed: true});
-            element.appendChild(callFrameElement);
-        }
+        WI.CallFrameTreeController.groupBlackboxedCallFrames(element, stackTrace.callFrames);
     }
 
     get element()

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ThreadTreeElement.js (288242 => 288243)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ThreadTreeElement.js	2022-01-19 22:28:13 UTC (rev 288242)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ThreadTreeElement.js	2022-01-19 22:38:19 UTC (rev 288243)
@@ -45,54 +45,15 @@
         this._updateStatus();
 
         let targetData = WI.debuggerManager.dataForTarget(this._target);
-        let callFrames = targetData.callFrames;
 
-        if (targetData.pausing || !callFrames.length) {
+        if (targetData.pausing || !targetData.callFrames.length) {
             this.appendChild(this._idleTreeElement);
             this.expand();
             return;
         }
 
-        let activeCallFrame = WI.debuggerManager.activeCallFrame;
-        let activeCallFrameTreeElement = null;
+        let activeCallFrameTreeElement = WI.CallFrameTreeController.groupBlackboxedCallFrames(this, targetData.callFrames, {rememberBlackboxedCallFrameGroupToAutoExpand: true});
 
-        let renderCallFrames = (callFrames, shouldSelectActiveFrame) => {
-            let blackboxedCallFrameGroupStartIndex = undefined;
-
-            // Add one extra iteration to handle call stacks that start blackboxed.
-            for (let i = 0; i < callFrames.length + 1; ++i) {
-                let callFrame = callFrames[i];
-
-                if (callFrame?.blackboxed && WI.settings.experimentalCollapseBlackboxedCallFrames.value) {
-                    blackboxedCallFrameGroupStartIndex ??= i;
-                    continue;
-                }
-
-                if (blackboxedCallFrameGroupStartIndex !== undefined) {
-                    let blackboxedCallFrameGroup = callFrames.slice(blackboxedCallFrameGroupStartIndex, i);
-                    blackboxedCallFrameGroupStartIndex = undefined;
-
-                    if (!WI.debuggerManager.shouldAutoExpandBlackboxedCallFrameGroup(blackboxedCallFrameGroup)) {
-                        this.appendChild(new WI.BlackboxedGroupTreeElement(blackboxedCallFrameGroup));
-                        continue;
-                    }
-
-                    for (let blackboxedCallFrame of blackboxedCallFrameGroup)
-                        this.appendChild(new WI.CallFrameTreeElement(blackboxedCallFrame));
-                }
-
-                if (!callFrame)
-                    continue;
-
-                let callFrameTreeElement = new WI.CallFrameTreeElement(callFrame);
-                if (shouldSelectActiveFrame && callFrame === activeCallFrame)
-                    activeCallFrameTreeElement = callFrameTreeElement;
-                this.appendChild(callFrameTreeElement);
-            }
-        };
-
-        renderCallFrames(callFrames, true);
-
         if (activeCallFrameTreeElement) {
             activeCallFrameTreeElement.select(true, true);
             activeCallFrameTreeElement.isActiveCallFrame = true;
@@ -115,11 +76,11 @@
                 boundaryCallFrame = new WI.CallFrame(null, null, null, functionName, null, null, nativeCode);
             }
 
-            const isAsyncBoundaryCallFrame = true;
-            this.appendChild(new WI.CallFrameTreeElement(boundaryCallFrame, isAsyncBoundaryCallFrame));
+            this.appendChild(new WI.CallFrameTreeElement(boundaryCallFrame, {isAsyncBoundaryCallFrame: true}));
 
             let startIndex = currentStackTrace.topCallFrameIsBoundary ? 1 : 0;
-            renderCallFrames(startIndex ? currentStackTrace.callFrames.slice(startIndex) : currentStackTrace.callFrames);
+            let currentCallFrames = startIndex ? currentStackTrace.callFrames.slice(startIndex) : currentStackTrace.callFrames;
+            WI.CallFrameTreeController.groupBlackboxedCallFrames(this, currentCallFrames, {rememberBlackboxedCallFrameGroupToAutoExpand: true});
 
             if (currentStackTrace.truncated) {
                 let truncatedTreeElement = new WI.GeneralTreeElement("truncated-call-frames", WI.UIString("Call Frames Truncated"));

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TimelineDataGrid.js (288242 => 288243)


--- trunk/Source/WebInspectorUI/UserInterface/Views/TimelineDataGrid.js	2022-01-19 22:28:13 UTC (rev 288242)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TimelineDataGrid.js	2022-01-19 22:38:19 UTC (rev 288243)
@@ -395,14 +395,11 @@
             this._popoverCallStackTreeOutline.disclosureButtons = false;
             this._popoverCallStackTreeOutline.element.classList.add("timeline-data-grid");
             this._popoverCallStackTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._popoverCallStackTreeSelectionDidChange, this);
+            this._popoverCallStackTreeOutline.addEventListener(WI.TreeOutline.Event.ElementRemoved, this._popoverCallStackTreeElementRemoved, this);
         } else
             this._popoverCallStackTreeOutline.removeChildren();
 
-        var callFrames = this.selectedNode.record.callFrames;
-        for (var i = 0; i < callFrames.length; ++i) {
-            var callFrameTreeElement = new WI.CallFrameTreeElement(callFrames[i]);
-            this._popoverCallStackTreeOutline.appendChild(callFrameTreeElement);
-        }
+        WI.CallFrameTreeController.groupBlackboxedCallFrames(this._popoverCallStackTreeOutline, this.selectedNode.record.callFrames);
 
         let content = document.createElement("div");
         content.appendChild(this._popoverCallStackTreeOutline.element);
@@ -427,6 +424,12 @@
             ignoreSearchTab: true,
         });
     }
+
+    _popoverCallStackTreeElementRemoved(event)
+    {
+        if (event.data.element instanceof WI.BlackboxedGroupTreeElement)
+            this._popover?.update();
+    }
 };
 
 WI.TimelineDataGrid.HasNonDefaultFilterStyleClassName = "has-non-default-filter";

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/Variables.css (288242 => 288243)


--- trunk/Source/WebInspectorUI/UserInterface/Views/Variables.css	2022-01-19 22:28:13 UTC (rev 288242)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/Variables.css	2022-01-19 22:38:19 UTC (rev 288243)
@@ -216,7 +216,7 @@
 
     --image-button-navigation-item-width: 26px;
 
-    --blackboxed-tree-item-opacity: 0.5;
+    --blackboxed-opacity: 0.5;
 }
 
 body.window-inactive {
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to