Changeset 116857 in webkit


Ignore:
Timestamp:
May 12, 2012 9:35:48 AM (12 years ago)
Author:
yurys@chromium.org
Message:

Web Inspector: heap profiler should allow revealing an element which is logged to the console
https://bugs.webkit.org/show_bug.cgi?id=86204

Reviewed by Pavel Feldman.

JS objects in the console have context menu item that allows to reveal them in a heap snapshot view.

  • English.lproj/localizedStrings.js:
  • inspector/front-end/ConsoleMessage.js:

(WebInspector.ConsoleMessageImpl.prototype._formatParameterAsObject):

  • inspector/front-end/ContextMenu.js:

(WebInspector.ContextMenu.prototype.isEmpty):

  • inspector/front-end/DataGrid.js:

(WebInspector.DataGridNode.prototype._detach):
(WebInspector.DataGridNode.prototype.wasDetached):

  • inspector/front-end/HeapSnapshot.js:

(WebInspector.HeapSnapshot.prototype.nodeClassName):
(WebInspector.HeapSnapshotNodesProvider.prototype.nodePosition):

  • inspector/front-end/HeapSnapshotDataGrids.js:

(WebInspector.HeapSnapshotSortableDataGrid):
(WebInspector.HeapSnapshotSortableDataGrid.prototype.highlightObjectByHeapSnapshotId):
(WebInspector.HeapSnapshotSortableDataGrid.prototype.highlightNode):
(WebInspector.HeapSnapshotSortableDataGrid.prototype.nodeWasDetached):
(WebInspector.HeapSnapshotSortableDataGrid.prototype._clearCurrentHighlight):
(WebInspector.HeapSnapshotViewportDataGrid):
(WebInspector.HeapSnapshotViewportDataGrid.prototype.highlightNode):
(WebInspector.HeapSnapshotViewportDataGrid.prototype._onScroll):
(WebInspector.HeapSnapshotConstructorsDataGrid):
(WebInspector.HeapSnapshotConstructorsDataGrid.prototype.highlightObjectByHeapSnapshotId.didGetClassName):
(WebInspector.HeapSnapshotConstructorsDataGrid.prototype.highlightObjectByHeapSnapshotId):
(WebInspector.HeapSnapshotConstructorsDataGrid.prototype.setDataSource):

  • inspector/front-end/HeapSnapshotGridNodes.js:

(WebInspector.HeapSnapshotGridNode.prototype.wasDetached):
(WebInspector.HeapSnapshotConstructorNode.prototype.revealNodeBySnapshotObjectId):
(WebInspector.HeapSnapshotConstructorNode.prototype.revealNodeBySnapshotObjectId.didPopulateChildren):

  • inspector/front-end/HeapSnapshotProxy.js:

(WebInspector.HeapSnapshotProxy.prototype.nodeClassName):
(WebInspector.HeapSnapshotProviderProxy.prototype.nodePosition):

  • inspector/front-end/ObjectPropertiesSection.js:

(WebInspector.ObjectPropertiesSection.ContextMenuProvider):
(WebInspector.ObjectPropertiesSection.ContextMenuProvider.prototype.populateContextMenu):
(WebInspector.ObjectPropertiesSection.addContextMenuProvider):
(WebInspector.ObjectPropertiesSection.prototype.enableContextMenu):
(WebInspector.ObjectPropertiesSection.prototype._contextMenuEventFired):

  • inspector/front-end/ProfilesPanel.js:

(WebInspector.ProfilesPanel.prototype.showObject):
(WebInspector.RevealInHeapSnapshotContextMenuProvider):
(WebInspector.RevealInHeapSnapshotContextMenuProvider.prototype.populateContextMenu.revealInSummaryView):
(WebInspector.RevealInHeapSnapshotContextMenuProvider.prototype.populateContextMenu.didReceiveHeapObjectId):
(WebInspector.RevealInHeapSnapshotContextMenuProvider.prototype.populateContextMenu):

  • inspector/front-end/profilesPanel.css:

(.highlighted-row):
(@-webkit-keyframes row_highlight):
(to):

Location:
trunk/Source/WebCore
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r116855 r116857  
     12012-05-12  Yury Semikhatsky  <yurys@chromium.org>
     2
     3        Web Inspector: heap profiler should allow revealing an element which is logged to the console
     4        https://bugs.webkit.org/show_bug.cgi?id=86204
     5
     6        Reviewed by Pavel Feldman.
     7
     8        JS objects in the console have context menu item that allows to reveal them in a heap snapshot view.
     9
     10        * English.lproj/localizedStrings.js:
     11        * inspector/front-end/ConsoleMessage.js:
     12        (WebInspector.ConsoleMessageImpl.prototype._formatParameterAsObject):
     13        * inspector/front-end/ContextMenu.js:
     14        (WebInspector.ContextMenu.prototype.isEmpty):
     15        * inspector/front-end/DataGrid.js:
     16        (WebInspector.DataGridNode.prototype._detach):
     17        (WebInspector.DataGridNode.prototype.wasDetached):
     18        * inspector/front-end/HeapSnapshot.js:
     19        (WebInspector.HeapSnapshot.prototype.nodeClassName):
     20        (WebInspector.HeapSnapshotNodesProvider.prototype.nodePosition):
     21        * inspector/front-end/HeapSnapshotDataGrids.js:
     22        (WebInspector.HeapSnapshotSortableDataGrid):
     23        (WebInspector.HeapSnapshotSortableDataGrid.prototype.highlightObjectByHeapSnapshotId):
     24        (WebInspector.HeapSnapshotSortableDataGrid.prototype.highlightNode):
     25        (WebInspector.HeapSnapshotSortableDataGrid.prototype.nodeWasDetached):
     26        (WebInspector.HeapSnapshotSortableDataGrid.prototype._clearCurrentHighlight):
     27        (WebInspector.HeapSnapshotViewportDataGrid):
     28        (WebInspector.HeapSnapshotViewportDataGrid.prototype.highlightNode):
     29        (WebInspector.HeapSnapshotViewportDataGrid.prototype._onScroll):
     30        (WebInspector.HeapSnapshotConstructorsDataGrid):
     31        (WebInspector.HeapSnapshotConstructorsDataGrid.prototype.highlightObjectByHeapSnapshotId.didGetClassName):
     32        (WebInspector.HeapSnapshotConstructorsDataGrid.prototype.highlightObjectByHeapSnapshotId):
     33        (WebInspector.HeapSnapshotConstructorsDataGrid.prototype.setDataSource):
     34        * inspector/front-end/HeapSnapshotGridNodes.js:
     35        (WebInspector.HeapSnapshotGridNode.prototype.wasDetached):
     36        (WebInspector.HeapSnapshotConstructorNode.prototype.revealNodeBySnapshotObjectId):
     37        (WebInspector.HeapSnapshotConstructorNode.prototype.revealNodeBySnapshotObjectId.didPopulateChildren):
     38        * inspector/front-end/HeapSnapshotProxy.js:
     39        (WebInspector.HeapSnapshotProxy.prototype.nodeClassName):
     40        (WebInspector.HeapSnapshotProviderProxy.prototype.nodePosition):
     41        * inspector/front-end/ObjectPropertiesSection.js:
     42        (WebInspector.ObjectPropertiesSection.ContextMenuProvider):
     43        (WebInspector.ObjectPropertiesSection.ContextMenuProvider.prototype.populateContextMenu):
     44        (WebInspector.ObjectPropertiesSection.addContextMenuProvider):
     45        (WebInspector.ObjectPropertiesSection.prototype.enableContextMenu):
     46        (WebInspector.ObjectPropertiesSection.prototype._contextMenuEventFired):
     47        * inspector/front-end/ProfilesPanel.js:
     48        (WebInspector.ProfilesPanel.prototype.showObject):
     49        (WebInspector.RevealInHeapSnapshotContextMenuProvider):
     50        (WebInspector.RevealInHeapSnapshotContextMenuProvider.prototype.populateContextMenu.revealInSummaryView):
     51        (WebInspector.RevealInHeapSnapshotContextMenuProvider.prototype.populateContextMenu.didReceiveHeapObjectId):
     52        (WebInspector.RevealInHeapSnapshotContextMenuProvider.prototype.populateContextMenu):
     53        * inspector/front-end/profilesPanel.css:
     54        (.highlighted-row):
     55        (@-webkit-keyframes row_highlight):
     56        (to):
     57
    1582012-05-12  Ilya Tikhonovsky  <loislo@chromium.org>
    259
  • trunk/Source/WebCore/inspector/front-end/ConsoleMessage.js

    r115317 r116857  
    265265    _formatParameterAsObject: function(obj, elem)
    266266    {
    267         elem.appendChild(new WebInspector.ObjectPropertiesSection(obj, obj.description).element);
     267        var section = new WebInspector.ObjectPropertiesSection(obj, obj.description);
     268        section.enableContextMenu();
     269        elem.appendChild(section.element);
    268270    },
    269271
  • trunk/Source/WebCore/inspector/front-end/ContextMenu.js

    r111551 r116857  
    8181    },
    8282
     83    /**
     84     * @return {boolean}
     85     */
     86    isEmpty: function()
     87    {
     88        return !this._items.length;
     89    },
     90
    8391    _itemSelected: function(id)
    8492    {
  • trunk/Source/WebCore/inspector/front-end/DataGrid.js

    r114662 r116857  
    16071607        for (var i = 0; i < this.children.length; ++i)
    16081608            this.children[i]._detach();
     1609
     1610        this.wasDetached();
     1611    },
     1612
     1613    wasDetached: function()
     1614    {
    16091615    },
    16101616
  • trunk/Source/WebCore/inspector/front-end/HeapSnapshot.js

    r116847 r116857  
    12871287    },
    12881288
     1289    nodeClassName: function(snapshotObjectId)
     1290    {
     1291        for (var it = this._allNodes; it.hasNext(); it.next()) {
     1292            if (it.node.id === snapshotObjectId)
     1293                return it.node.className;
     1294        }
     1295        return null;
     1296    },
     1297
    12891298    _parseFilter: function(filter)
    12901299    {
     
    15941603
    15951604WebInspector.HeapSnapshotNodesProvider.prototype = {
     1605    nodePosition: function(snapshotObjectId)
     1606    {
     1607        this._createIterationOrder();
     1608        if (this.isEmpty)
     1609            return -1;
     1610        this.sortAll();
     1611
     1612        var node = new WebInspector.HeapSnapshotNode(this.snapshot);
     1613        for (var i = 0; i < this._iterationOrder.length; i++) {
     1614            node.nodeIndex = this._iterationOrder[i];
     1615            if (node.id === snapshotObjectId)
     1616                return i;
     1617        }
     1618        return -1;
     1619    },
     1620
    15961621    serializeItem: function(node)
    15971622    {
  • trunk/Source/WebCore/inspector/front-end/HeapSnapshotDataGrids.js

    r115063 r116857  
    4141     */
    4242    this._recursiveSortingDepth = 0;
     43    /**
     44     * @type {WebInspector.HeapSnapshotGridNode}
     45     */
     46    this._highlightedNode = null;
    4347    this.addEventListener("sorting changed", this.sortingChanged, this);
    4448}
     
    6973    {
    7074        return this.rootNode().children;
     75    },
     76
     77    /**
     78     * @param {ProfilerAgent.HeapSnapshotObjectId} heapSnapshotObjectId
     79     */
     80    highlightObjectByHeapSnapshotId: function(heapSnapshotObjectId)
     81    {
     82    },
     83
     84    /**
     85     * @param {WebInspector.HeapSnapshotGridNode} node
     86     */
     87    highlightNode: function(node)
     88    {
     89        this._clearCurrentHighlight();
     90        this._highlightedNode = node;
     91        this._highlightedNode.element.addStyleClass("highlighted-row");
     92    },
     93
     94    nodeWasDetached: function(node)
     95    {
     96        if (this._highlightedNode === node)
     97            this._clearCurrentHighlight();
     98    },
     99
     100    _clearCurrentHighlight: function()
     101    {
     102        if (!this._highlightedNode)
     103            return
     104        this._highlightedNode.element.removeStyleClass("highlighted-row");
     105        this._highlightedNode = null;
    71106    },
    72107
     
    167202    this._topPadding = new WebInspector.HeapSnapshotPaddingNode();
    168203    this._bottomPadding = new WebInspector.HeapSnapshotPaddingNode();
     204    /**
     205     * @type {WebInspector.HeapSnapshotGridNode}
     206     */
     207    this._nodeToHighlightAfterScroll = null;
    169208}
    170209
     
    234273    },
    235274
     275    /**
     276     * @override
     277     * @param {WebInspector.HeapSnapshotGridNode} node
     278     */
     279    highlightNode: function(node)
     280    {
     281        node.element.scrollIntoViewIfNeeded(true);
     282        this._nodeToHighlightAfterScroll = node;
     283    },
     284
    236285    _addPaddingRows: function(top, bottom)
    237286    {
     
    258307    {
    259308        this.updateVisibleNodes();
     309
     310        if (this._nodeToHighlightAfterScroll) {
     311            WebInspector.HeapSnapshotSortableDataGrid.prototype.highlightNode.call(this, this._nodeToHighlightAfterScroll);
     312            this._nodeToHighlightAfterScroll = null;
     313        }
    260314    }
    261315}
     
    372426    this._profileIndex = -1;
    373427    this._topLevelNodes = [];
     428
     429    this._objectIdToSelect = null;
    374430}
    375431
     
    386442    },
    387443
     444    /**
     445     * @override
     446     * @param {ProfilerAgent.HeapSnapshotObjectId} id
     447     */
     448    highlightObjectByHeapSnapshotId: function(id)
     449    {
     450        if (!this.snapshot) {
     451            this._objectIdToSelect = id;
     452            return;
     453        }
     454
     455        function didGetClassName(className)
     456        {
     457            var constructorNodes = this.topLevelNodes();
     458            for (var i = 0; i < constructorNodes.length; i++) {
     459                var parent = constructorNodes[i];
     460                if (parent._name === className) {
     461                    parent.revealNodeBySnapshotObjectId(parseInt(id, 10));
     462                    return;
     463                }
     464            }
     465        }
     466        this.snapshot.nodeClassName(parseInt(id, 10), didGetClassName.bind(this));
     467    },
     468
    388469    setDataSource: function(snapshotView, snapshot)
    389470    {
     
    392473        if (this._profileIndex === -1)
    393474            this._populateChildren();
     475
     476        if (this._objectIdToSelect) {
     477            this.highlightObjectByHeapSnapshotId(this._objectIdToSelect);
     478            this._objectIdToSelect = null;
     479        }
    394480    },
    395481
  • trunk/Source/WebCore/inspector/front-end/HeapSnapshotGridNodes.js

    r116847 r116857  
    8383    queryObjectContent: function(callback)
    8484    {
     85    },
     86
     87    /**
     88     * @override
     89     */
     90    wasDetached: function()
     91    {
     92        this._dataGrid.nodeWasDetached(this);
    8593    },
    8694
     
    690698
    691699WebInspector.HeapSnapshotConstructorNode.prototype = {
     700    /**
     701     * @param {number} snapshotObjectId
     702     */
     703    revealNodeBySnapshotObjectId: function(snapshotObjectId)
     704    {
     705        function didGetNodePosition(nodePosition)
     706        {
     707            if (nodePosition !== -1)
     708                this._populateChildren(nodePosition, null, didPopulateChildren.bind(this, nodePosition));
     709        }
     710
     711        function didPopulateChildren(nodePosition)
     712        {
     713            var indexOfFirsChildInRange = 0;
     714            for (var i = 0; i < this._retrievedChildrenRanges.length; i++) {
     715               var range = this._retrievedChildrenRanges[i];
     716               if (range.from <= nodePosition && nodePosition < range.to) {
     717                   var childIndex = indexOfFirsChildInRange + nodePosition - range.from;
     718                   var instanceNode = this.children[childIndex];
     719                   this._dataGrid.highlightNode(instanceNode);
     720                   return;
     721               }
     722               indexOfFirsChildInRange += range.to - range.from + 1;
     723            }
     724        }
     725
     726        this.expand();
     727        this._provider.nodePosition(snapshotObjectId, didGetNodePosition.bind(this));
     728    },
     729
    692730    createCell: function(columnIdentifier)
    693731    {
  • trunk/Source/WebCore/inspector/front-end/HeapSnapshotProxy.js

    r116851 r116857  
    383383    },
    384384
     385    nodeClassName: function(snapshotObjectId, callback)
     386    {
     387        this.callMethod(callback, "nodeClassName", snapshotObjectId);
     388    },
     389
    385390    createEdgesProvider: function(nodeIndex, filter)
    386391    {
     
    487492
    488493WebInspector.HeapSnapshotProviderProxy.prototype = {
     494    nodePosition: function(snapshotObjectId, callback)
     495    {
     496        this.callMethod(callback, "nodePosition", snapshotObjectId);
     497    },
     498
    489499    isEmpty: function(callback)
    490500    {
  • trunk/Source/WebCore/inspector/front-end/ObjectPropertiesSection.js

    r113707 r116857  
    5151WebInspector.ObjectPropertiesSection._arrayLoadThreshold = 100;
    5252
     53
     54/**
     55 * @interface
     56 */
     57WebInspector.ObjectPropertiesSection.ContextMenuProvider = function()
     58{
     59}
     60
     61WebInspector.ObjectPropertiesSection.ContextMenuProvider.prototype = {
     62    /**
     63     * @param {WebInspector.ObjectPropertiesSection} section
     64     * @param {WebInspector.ContextMenu} contextMenu
     65     */
     66    populateContextMenu: function(section, contextMenu)
     67    {
     68    }
     69}
     70
     71
     72/**
     73 * @type {Array.<WebInspector.ObjectPropertiesSection.ContextMenuProvider>}
     74 */
     75WebInspector.ObjectPropertiesSection._contextMenuProviers = [];
     76
     77/**
     78 * @param {WebInspector.ObjectPropertiesSection.ContextMenuProvider} provider
     79 */
     80WebInspector.ObjectPropertiesSection.addContextMenuProvider = function(provider)
     81{
     82    WebInspector.ObjectPropertiesSection._contextMenuProviers.push(provider);
     83}
     84
    5385WebInspector.ObjectPropertiesSection.prototype = {
     86    enableContextMenu: function()
     87    {
     88        this.element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true);
     89    },
     90
     91    _contextMenuEventFired: function(event)
     92    {
     93        var contextMenu = new WebInspector.ContextMenu();
     94        var providers = WebInspector.ObjectPropertiesSection._contextMenuProviers;
     95        for (var i = 0; i < providers.length; i++)
     96            providers[i].populateContextMenu(this, contextMenu);
     97        if (!contextMenu.isEmpty())
     98            contextMenu.show(event);
     99    },
     100
    54101    onpopulate: function()
    55102    {
  • trunk/Source/WebCore/inspector/front-end/ProfilesPanel.js

    r116855 r116857  
    230230    this.element.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), true);
    231231
     232    WebInspector.ObjectPropertiesSection.addContextMenuProvider(new WebInspector.RevealInHeapSnapshotContextMenuProvider());
    232233}
    233234
     
    574575        }
    575576        return result;
     577    },
     578
     579    /**
     580     * @param {ProfilerAgent.HeapSnapshotObjectId} snapshotObjectId
     581     */
     582    showObject: function(snapshotObjectId)
     583    {
     584        var heapProfiles = this.getProfiles(WebInspector.HeapSnapshotProfileType.TypeId);
     585        for (var i = 0; i < heapProfiles.length; i++) {
     586            var profile = heapProfiles[i];
     587            // TODO: allow to choose snapshot if there are several options.
     588            if (profile.maxJSObjectId >= snapshotObjectId) {
     589                this.showProfile(profile);
     590                profile._profileView.changeView("Summary", function() {
     591                    if (profile._profileView.dataGrid !==  profile._profileView.constructorsDataGrid)
     592                        return;
     593                    profile._profileView.dataGrid.highlightObjectByHeapSnapshotId(snapshotObjectId);
     594                });
     595                break;
     596            }
     597        }
    576598    },
    577599
     
    10421064WebInspector.ProfilesPanel.prototype.__proto__ = WebInspector.Panel.prototype;
    10431065
     1066
     1067/**
     1068 * @implements {WebInspector.ObjectPropertiesSection.ContextMenuProvider}
     1069 * @constructor
     1070 */
     1071WebInspector.RevealInHeapSnapshotContextMenuProvider = function()
     1072{
     1073}
     1074
     1075WebInspector.RevealInHeapSnapshotContextMenuProvider.prototype = {
     1076    /**
     1077     * @override
     1078     * @param {WebInspector.ObjectPropertiesSection} section
     1079     * @param {WebInspector.ContextMenu} contextMenu
     1080     */
     1081    populateContextMenu: function(section, contextMenu)
     1082    {
     1083        if (WebInspector.inspectorView.currentPanel() !== WebInspector.panels.profiles)
     1084            return;
     1085
     1086        var objectId = section.object.objectId;
     1087        if (!objectId)
     1088            return;
     1089
     1090        var heapProfiles = WebInspector.panels.profiles.getProfiles(WebInspector.HeapSnapshotProfileType.TypeId);
     1091        if (!heapProfiles.length)
     1092            return;
     1093
     1094        function revealInSummaryView()
     1095        {
     1096            ProfilerAgent.getHeapObjectId(objectId, didReceiveHeapObjectId.bind(this));
     1097        }
     1098
     1099        function didReceiveHeapObjectId(error, result)
     1100        {
     1101            if (WebInspector.inspectorView.currentPanel() !== WebInspector.panels.profiles)
     1102                return;
     1103            if (!error)
     1104                WebInspector.panels.profiles.showObject(result);
     1105        }
     1106
     1107        contextMenu.appendItem(WebInspector.UIString("Reveal in Summary View"), revealInSummaryView.bind(this));
     1108    }
     1109}
     1110
     1111
    10441112/**
    10451113 * @constructor
  • trunk/Source/WebCore/inspector/front-end/profilesPanel.css

    r106755 r116857  
    187187    color: rgb(220, 130, 130);
    188188}
     189
     190.highlighted-row {
     191    -webkit-animation: "row_highlight" 2s 0s;
     192}
     193
     194@-webkit-keyframes row_highlight {
     195    from {background-color: rgb(255, 255, 120); }
     196    to { background-color: white; }
     197}
Note: See TracChangeset for help on using the changeset viewer.