⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 259738 in webkit


Ignore:
Timestamp:
Apr 8, 2020, 11:53:10 AM (6 years ago)
Author:
Devin Rousso
Message:

Web Inspector: Sources: support copying selected call frame(s) in the Call Stack
https://bugs.webkit.org/show_bug.cgi?id=210172

Reviewed by Timothy Hatcher.

  • UserInterface/Views/SourcesTabContentView.js:

(WI.SourcesTabContentView.prototype.handleCopyEvent): Added.

  • UserInterface/Views/SourcesNavigationSidebarPanel.js:

(WI.SourcesNavigationSidebarPanel):
(WI.SourcesNavigationSidebarPanel.prototype.handleCopyEvent): Added.
Copy the function name and source location for each selected call frame. If the selected
call frames span an async boundary, include the async boundary in the form --- <name> ---
where name is the reason for the async behavior (e.g. addEventListener). If the selected
call frames span multiple threads (e.g. Worker), include the thread name and indent all
of the call frames for that thread.

  • UserInterface/Views/CallFrameTreeElement.js:

(WI.CallFrameTreeElement):
(WI.CallFrameTreeElement.prototype.get isAsyncBoundaryCallFrame): Added.

Location:
trunk/Source/WebInspectorUI
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebInspectorUI/ChangeLog

    r259666 r259738  
     12020-04-08  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: Sources: support copying selected call frame(s) in the Call Stack
     4        https://bugs.webkit.org/show_bug.cgi?id=210172
     5
     6        Reviewed by Timothy Hatcher.
     7
     8        * UserInterface/Views/SourcesTabContentView.js:
     9        (WI.SourcesTabContentView.prototype.handleCopyEvent): Added.
     10        * UserInterface/Views/SourcesNavigationSidebarPanel.js:
     11        (WI.SourcesNavigationSidebarPanel):
     12        (WI.SourcesNavigationSidebarPanel.prototype.handleCopyEvent): Added.
     13        Copy the function name and source location for each selected call frame. If the selected
     14        call frames span an async boundary, include the async boundary in the form `--- <name> ---`
     15        where name is the reason for the async behavior (e.g. `addEventListener`). If the selected
     16        call frames span multiple threads (e.g. `Worker`), include the thread name and indent all
     17        of the call frames for that thread.
     18
     19        * UserInterface/Views/CallFrameTreeElement.js:
     20        (WI.CallFrameTreeElement):
     21        (WI.CallFrameTreeElement.prototype.get isAsyncBoundaryCallFrame): Added.
     22
    1232020-04-07  Nikita Vasilyev  <nvasilyev@apple.com>
    224
  • trunk/Source/WebInspectorUI/UserInterface/Views/CallFrameTreeElement.js

    r252745 r259738  
    3838        this._isActiveCallFrame = false;
    3939
    40          if (isAsyncBoundaryCallFrame) {
     40        this._isAsyncBoundaryCallFrame = isAsyncBoundaryCallFrame;
     41         if (this._isAsyncBoundaryCallFrame) {
    4142            this.addClassName("async-boundary");
    4243            this.selectable = false;
     
    6768
    6869    get callFrame() { return this._callFrame; }
    69     get isActiveCallFrame() { return this._isActiveCallFrame; }
     70    get isAsyncBoundaryCallFrame() { return this._isAsyncBoundaryCallFrame; }
     71
     72    get isActiveCallFrame()
     73    {
     74        return this._isActiveCallFrame;
     75    }
    7076
    7177    set isActiveCallFrame(x)
  • trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.js

    r259524 r259738  
    123123
    124124        this._callStackTreeOutline = this.createContentTreeOutline({suppressFiltering: true});
     125        this._callStackTreeOutline.allowsMultipleSelection = true;
    125126        this._callStackTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._handleTreeSelectionDidChange, this);
     127        this._callStackTreeOutline.populateContextMenu = (contextMenu, event, treeElement) => {
     128            if (this._callStackTreeOutline.selectedTreeElements.length) {
     129                contextMenu.appendItem(WI.UIString("Copy"), () => {
     130                    this.handleCopyEvent(event);
     131                });
     132
     133                contextMenu.appendSeparator();
     134            }
     135
     136            WI.TreeOutline.prototype.populateContextMenu(contextMenu, event, treeElement);
     137        };
    126138
    127139        let callStackRow = new WI.DetailsSectionRow;
     
    581593        console.assert(false, "Didn't find a TreeElement for representedObject", representedObject);
    582594        return null;
     595    }
     596
     597    handleCopyEvent(event)
     598    {
     599        let selectedTreeElements = new Set(this._callStackTreeOutline.selectedTreeElements);
     600        if (!selectedTreeElements.size)
     601            return;
     602
     603        let treeElement = this._callStackTreeOutline.children[0];
     604
     605        const ignoreHidden = true;
     606        const skipUnrevealed = true;
     607        const stayWithin = null;
     608        const dontPopulate = true;
     609        while (!treeElement.revealed(ignoreHidden))
     610            treeElement = treeElement.traverseNextTreeElement(skipUnrevealed, stayWithin, dontPopulate);
     611
     612        let indentString = WI.indentString();
     613        let threads = [];
     614        let asyncBoundary = null;
     615
     616        while (treeElement) {
     617            if (treeElement instanceof WI.ThreadTreeElement) {
     618                threads.push({
     619                    name: treeElement.mainTitle,
     620                    frames: [],
     621                });
     622
     623                asyncBoundary = null;
     624            } else if (treeElement instanceof WI.CallFrameTreeElement) {
     625                if (treeElement.isAsyncBoundaryCallFrame) {
     626                    asyncBoundary = treeElement.mainTitle;
     627                } else if (selectedTreeElements.has(treeElement)) {
     628                    if (asyncBoundary) {
     629                        threads.lastValue.frames.push("--- " + asyncBoundary + " ---");
     630                        asyncBoundary = null;
     631                    }
     632
     633                    let line = treeElement.mainTitle;
     634
     635                    let sourceCodeLocation = treeElement.callFrame.sourceCodeLocation;
     636                    if (sourceCodeLocation)
     637                        line += " (" + sourceCodeLocation.displayLocationString() + ")";
     638
     639                    threads.lastValue.frames.push(line);
     640                }
     641            }
     642
     643            treeElement = treeElement.traverseNextTreeElement(skipUnrevealed, stayWithin, dontPopulate);
     644        }
     645
     646        let multipleFramesSelected = threads.filter(({frames}) => frames.length).length > 1;
     647
     648        let lines = [];
     649        for (let {name, frames} of threads) {
     650            if (multipleFramesSelected)
     651                lines.push(name);
     652
     653            for (let frame of frames) {
     654                let prefix = "";
     655                if (multipleFramesSelected)
     656                    prefix = indentString;
     657                lines.push(prefix + frame);
     658            }
     659        }
     660        if (!lines.length)
     661            return;
     662
     663        setTimeout(() => {
     664            InspectorFrontendHost.copyText(lines.join("\n"));
     665        });
     666
     667        event.stop();
    583668    }
    584669
  • trunk/Source/WebInspectorUI/UserInterface/Views/SourcesTabContentView.js

    r259101 r259738  
    109109    }
    110110
     111    handleCopyEvent(event)
     112    {
     113        if (this.navigationSidebarPanel.element.contains(WI.currentFocusElement))
     114            this.navigationSidebarPanel.handleCopyEvent(event);
     115    }
     116
    111117    // Private
    112118
Note: See TracChangeset for help on using the changeset viewer.