<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[198196] trunk/Source/WebInspectorUI</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/198196">198196</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2016-03-14 22:02:28 -0700 (Mon, 14 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: Show path from root to instances in the Heap Snapshot content view
https://bugs.webkit.org/show_bug.cgi?id=155478
&lt;rdar://problem/25157408&gt;

Patch by Joseph Pecoraro &lt;pecoraro@apple.com&gt; on 2016-03-14
Reviewed by Timothy Hatcher.

* Localizations/en.lproj/localizedStrings.js:
* UserInterface/Main.html:
New strings and resources.

* UserInterface/Models/HeapSnapshotNode.js:
(WebInspector.HeapSnapshotNode.prototype.get shortestGCRootPath):
(WebInspector.HeapSnapshotNode.prototype._gcRootPaths.visitNode):
(WebInspector.HeapSnapshotNode.prototype._gcRootPaths):
Helper to get the shortest path from a GC root to the node.

* UserInterface/Models/HeapSnapshotRootPath.js: Added.
(WebInspector.HeapSnapshotRootPath):
(WebInspector.HeapSnapshotRootPath.emptyPath):
(WebInspector.HeapSnapshotRootPath.prototype.get node):
(WebInspector.HeapSnapshotRootPath.prototype.get parent):
(WebInspector.HeapSnapshotRootPath.prototype.get pathComponent):
(WebInspector.HeapSnapshotRootPath.prototype.get rootNode):
(WebInspector.HeapSnapshotRootPath.prototype.get fullPath):
(WebInspector.HeapSnapshotRootPath.prototype.isRoot):
(WebInspector.HeapSnapshotRootPath.prototype.isEmpty):
(WebInspector.HeapSnapshotRootPath.prototype.isGlobalScope):
(WebInspector.HeapSnapshotRootPath.prototype.isPathComponentImpossible):
(WebInspector.HeapSnapshotRootPath.prototype.isFullPathImpossible):
(WebInspector.HeapSnapshotRootPath.prototype.appendInternal):
(WebInspector.HeapSnapshotRootPath.prototype.appendArrayIndex):
(WebInspector.HeapSnapshotRootPath.prototype.appendPropertyName):
(WebInspector.HeapSnapshotRootPath.prototype.appendVariableName):
(WebInspector.HeapSnapshotRootPath.prototype.appendGlobalScopeName):
(WebInspector.HeapSnapshotRootPath.prototype.appendEdge):
(WebInspector.HeapSnapshotRootPath.prototype._canPropertyNameBeDotAccess):
Helper class, like PropertyPath, for building a string path to
a HeapSnapshotNode. Typically the path is built up with
HeapSnapshotEdges and so you can build a string such as:
`window.foo[0][&quot;prop erty&quot;]._foo`.

* UserInterface/Views/HeapAllocationsTimelineView.js:
(WebInspector.HeapAllocationsTimelineView.prototype.showHeapSnapshotList):
(WebInspector.HeapAllocationsTimelineView.prototype.showHeapSnapshotTimelineRecord):
(WebInspector.HeapAllocationsTimelineView.prototype.showHeapSnapshotDiff):
(WebInspector.HeapAllocationsTimelineView.prototype.shown):
(WebInspector.HeapAllocationsTimelineView.prototype.hidden):
(WebInspector.HeapAllocationsTimelineView.prototype.closed):
Propogate shown/hidden to the contentViewContainer.
Cleanup the contentViewContainer when closing.

* UserInterface/Views/HeapSnapshotInstanceDataGridNode.js:
(WebInspector.HeapSnapshotInstanceDataGridNode.logHeapSnapshotNode):
Helper for logging a HeapSnapshotNode value to the console. If the
path is possible from the root, just output the path in the console
otherwise use a synthetic &quot;Heap Snapshot Object (@1234)&quot; like string.
For strings, just get the preview as we won't get a real RemoteObject.

(WebInspector.HeapSnapshotInstanceDataGridNode.prototype.createCellContent):
(WebInspector.HeapSnapshotInstanceDataGridNode.prototype._mouseoverHandler.appendPath):
(WebInspector.HeapSnapshotInstanceDataGridNode.prototype._mouseoverHandler.appendPathRow):
(WebInspector.HeapSnapshotInstanceDataGridNode.prototype._mouseoverHandler.sanitizeClassName):
(WebInspector.HeapSnapshotInstanceDataGridNode.prototype._mouseoverHandler.stringifyEdge):
(WebInspector.HeapSnapshotInstanceDataGridNode.prototype._mouseoverHandler):
Give the @1234 id element a mouseover handler to display a popover
with the path from a root. Stop the path at &quot;Window&quot; if possible
to avoid displaying internals like &quot;JSDOMWindowShell&quot;.

* UserInterface/Views/HeapSnapshotInstancesContentView.css:
(.heap-snapshot .object-id):
(.heap-snapshot .object-id:hover):
(.heap-snapshot &gt; .data-grid tr:not(.selected) td .object-id): Deleted.
(.heap-snapshot .icon):
(.heap-snapshot-instance-popover-content):
(.heap-snapshot-instance-popover-content table):
(.heap-snapshot-instance-popover-content tr):
(.heap-snapshot-instance-popover-content td):
(.heap-snapshot-instance-popover-content td.edge-name):
(.heap-snapshot-instance-popover-content td.object-data):
(.heap-snapshot-instance-popover-content .node):
(.heap-snapshot-instance-popover-content .node *):
Styles for contents of the popover.

* UserInterface/Views/HeapSnapshotInstancesContentView.js:
(WebInspector.HeapSnapshotInstancesContentView.prototype.hidden):
* UserInterface/Views/HeapSnapshotInstancesDataGridTree.js:
(WebInspector.HeapSnapshotInstancesDataGridTree):
(WebInspector.HeapSnapshotInstancesDataGridTree.prototype.get popover):
(WebInspector.HeapSnapshotInstancesDataGridTree.prototype.get popoverNode):
(WebInspector.HeapSnapshotInstancesDataGridTree.prototype.set popoverNode):
(WebInspector.HeapSnapshotInstancesDataGridTree.prototype.hidden):
(WebInspector.HeapSnapshotInstancesDataGridTree.prototype.willDismissPopover):
Have a single popover for the entire tree. Cache and clear
contents of the popover when appropriate.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs">trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceMainhtml">trunk/Source/WebInspectorUI/UserInterface/Main.html</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsHeapSnapshotNodejs">trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshotNode.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsHeapAllocationsTimelineViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsHeapSnapshotInstanceDataGridNodejs">trunk/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotInstanceDataGridNode.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsHeapSnapshotInstancesContentViewcss">trunk/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotInstancesContentView.css</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsHeapSnapshotInstancesContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotInstancesContentView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsHeapSnapshotInstancesDataGridTreejs">trunk/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotInstancesDataGridTree.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsHeapSnapshotRootPathjs">trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshotRootPath.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (198195 => 198196)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2016-03-15 04:59:39 UTC (rev 198195)
+++ trunk/Source/WebInspectorUI/ChangeLog        2016-03-15 05:02:28 UTC (rev 198196)
</span><span class="lines">@@ -1,3 +1,100 @@
</span><ins>+2016-03-14  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+        Web Inspector: Show path from root to instances in the Heap Snapshot content view
+        https://bugs.webkit.org/show_bug.cgi?id=155478
+        &lt;rdar://problem/25157408&gt;
+
+        Reviewed by Timothy Hatcher.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        * UserInterface/Main.html:
+        New strings and resources.
+
+        * UserInterface/Models/HeapSnapshotNode.js:
+        (WebInspector.HeapSnapshotNode.prototype.get shortestGCRootPath):
+        (WebInspector.HeapSnapshotNode.prototype._gcRootPaths.visitNode):
+        (WebInspector.HeapSnapshotNode.prototype._gcRootPaths):
+        Helper to get the shortest path from a GC root to the node.
+
+        * UserInterface/Models/HeapSnapshotRootPath.js: Added.
+        (WebInspector.HeapSnapshotRootPath):
+        (WebInspector.HeapSnapshotRootPath.emptyPath):
+        (WebInspector.HeapSnapshotRootPath.prototype.get node):
+        (WebInspector.HeapSnapshotRootPath.prototype.get parent):
+        (WebInspector.HeapSnapshotRootPath.prototype.get pathComponent):
+        (WebInspector.HeapSnapshotRootPath.prototype.get rootNode):
+        (WebInspector.HeapSnapshotRootPath.prototype.get fullPath):
+        (WebInspector.HeapSnapshotRootPath.prototype.isRoot):
+        (WebInspector.HeapSnapshotRootPath.prototype.isEmpty):
+        (WebInspector.HeapSnapshotRootPath.prototype.isGlobalScope):
+        (WebInspector.HeapSnapshotRootPath.prototype.isPathComponentImpossible):
+        (WebInspector.HeapSnapshotRootPath.prototype.isFullPathImpossible):
+        (WebInspector.HeapSnapshotRootPath.prototype.appendInternal):
+        (WebInspector.HeapSnapshotRootPath.prototype.appendArrayIndex):
+        (WebInspector.HeapSnapshotRootPath.prototype.appendPropertyName):
+        (WebInspector.HeapSnapshotRootPath.prototype.appendVariableName):
+        (WebInspector.HeapSnapshotRootPath.prototype.appendGlobalScopeName):
+        (WebInspector.HeapSnapshotRootPath.prototype.appendEdge):
+        (WebInspector.HeapSnapshotRootPath.prototype._canPropertyNameBeDotAccess):
+        Helper class, like PropertyPath, for building a string path to
+        a HeapSnapshotNode. Typically the path is built up with
+        HeapSnapshotEdges and so you can build a string such as:
+        `window.foo[0][&quot;prop erty&quot;]._foo`.
+
+        * UserInterface/Views/HeapAllocationsTimelineView.js:
+        (WebInspector.HeapAllocationsTimelineView.prototype.showHeapSnapshotList):
+        (WebInspector.HeapAllocationsTimelineView.prototype.showHeapSnapshotTimelineRecord):
+        (WebInspector.HeapAllocationsTimelineView.prototype.showHeapSnapshotDiff):
+        (WebInspector.HeapAllocationsTimelineView.prototype.shown):
+        (WebInspector.HeapAllocationsTimelineView.prototype.hidden):
+        (WebInspector.HeapAllocationsTimelineView.prototype.closed):
+        Propogate shown/hidden to the contentViewContainer.
+        Cleanup the contentViewContainer when closing.
+
+        * UserInterface/Views/HeapSnapshotInstanceDataGridNode.js:
+        (WebInspector.HeapSnapshotInstanceDataGridNode.logHeapSnapshotNode):
+        Helper for logging a HeapSnapshotNode value to the console. If the
+        path is possible from the root, just output the path in the console
+        otherwise use a synthetic &quot;Heap Snapshot Object (@1234)&quot; like string.
+        For strings, just get the preview as we won't get a real RemoteObject.
+
+        (WebInspector.HeapSnapshotInstanceDataGridNode.prototype.createCellContent):
+        (WebInspector.HeapSnapshotInstanceDataGridNode.prototype._mouseoverHandler.appendPath):
+        (WebInspector.HeapSnapshotInstanceDataGridNode.prototype._mouseoverHandler.appendPathRow):
+        (WebInspector.HeapSnapshotInstanceDataGridNode.prototype._mouseoverHandler.sanitizeClassName):
+        (WebInspector.HeapSnapshotInstanceDataGridNode.prototype._mouseoverHandler.stringifyEdge):
+        (WebInspector.HeapSnapshotInstanceDataGridNode.prototype._mouseoverHandler):
+        Give the @1234 id element a mouseover handler to display a popover
+        with the path from a root. Stop the path at &quot;Window&quot; if possible
+        to avoid displaying internals like &quot;JSDOMWindowShell&quot;.
+
+        * UserInterface/Views/HeapSnapshotInstancesContentView.css:
+        (.heap-snapshot .object-id):
+        (.heap-snapshot .object-id:hover):
+        (.heap-snapshot &gt; .data-grid tr:not(.selected) td .object-id): Deleted.
+        (.heap-snapshot .icon):
+        (.heap-snapshot-instance-popover-content):
+        (.heap-snapshot-instance-popover-content table):
+        (.heap-snapshot-instance-popover-content tr):
+        (.heap-snapshot-instance-popover-content td):
+        (.heap-snapshot-instance-popover-content td.edge-name):
+        (.heap-snapshot-instance-popover-content td.object-data):
+        (.heap-snapshot-instance-popover-content .node):
+        (.heap-snapshot-instance-popover-content .node *):
+        Styles for contents of the popover.
+
+        * UserInterface/Views/HeapSnapshotInstancesContentView.js:
+        (WebInspector.HeapSnapshotInstancesContentView.prototype.hidden):
+        * UserInterface/Views/HeapSnapshotInstancesDataGridTree.js:
+        (WebInspector.HeapSnapshotInstancesDataGridTree):
+        (WebInspector.HeapSnapshotInstancesDataGridTree.prototype.get popover):
+        (WebInspector.HeapSnapshotInstancesDataGridTree.prototype.get popoverNode):
+        (WebInspector.HeapSnapshotInstancesDataGridTree.prototype.set popoverNode):
+        (WebInspector.HeapSnapshotInstancesDataGridTree.prototype.hidden):
+        (WebInspector.HeapSnapshotInstancesDataGridTree.prototype.willDismissPopover):
+        Have a single popover for the entire tree. Cache and clear
+        contents of the popover when appropriate.
+
</ins><span class="cx"> 2016-03-14  Daniel Bates  &lt;dabates@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Display Content Security Policy hash in details sidebar for script and style elements
</span></span></pre></div>
<a id="trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (198195 => 198196)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js        2016-03-15 04:59:39 UTC (rev 198195)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js        2016-03-15 05:02:28 UTC (rev 198196)
</span><span class="lines">@@ -20,7 +20,6 @@
</span><span class="cx"> localizedStrings[&quot;%d Errors, %d Warnings&quot;] = &quot;%d Errors, %d Warnings&quot;;
</span><span class="cx"> localizedStrings[&quot;%d More\u2026&quot;] = &quot;%d More\u2026&quot;;
</span><span class="cx"> localizedStrings[&quot;%d Warnings&quot;] = &quot;%d Warnings&quot;;
</span><del>-localizedStrings[&quot;%d \u2A09 %d&quot;] = &quot;%d \u2A09 %d&quot;;
</del><span class="cx"> localizedStrings[&quot;%d \xd7 %d pixels&quot;] = &quot;%d \xd7 %d pixels&quot;;
</span><span class="cx"> localizedStrings[&quot;%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)&quot;] = &quot;%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)&quot;;
</span><span class="cx"> localizedStrings[&quot;%d matches&quot;] = &quot;%d matches&quot;;
</span><span class="lines">@@ -118,6 +117,7 @@
</span><span class="cx"> localizedStrings[&quot;Breakdown of total allocation size by class&quot;] = &quot;Breakdown of total allocation size by class&quot;;
</span><span class="cx"> localizedStrings[&quot;Bubbling&quot;] = &quot;Bubbling&quot;;
</span><span class="cx"> localizedStrings[&quot;Busy&quot;] = &quot;Busy&quot;;
</span><ins>+localizedStrings[&quot;CSP Hash&quot;] = &quot;CSP Hash&quot;;
</ins><span class="cx"> localizedStrings[&quot;Cached&quot;] = &quot;Cached&quot;;
</span><span class="cx"> localizedStrings[&quot;Call Stack&quot;] = &quot;Call Stack&quot;;
</span><span class="cx"> localizedStrings[&quot;Call Trees&quot;] = &quot;Call Trees&quot;;
</span><span class="lines">@@ -188,7 +188,6 @@
</span><span class="cx"> localizedStrings[&quot;Container Regions&quot;] = &quot;Container Regions&quot;;
</span><span class="cx"> localizedStrings[&quot;Content&quot;] = &quot;Content&quot;;
</span><span class="cx"> localizedStrings[&quot;Content Flow&quot;] = &quot;Content Flow&quot;;
</span><del>-localizedStrings[&quot;CSP Hash&quot;] = &quot;CSP Hash&quot;;
</del><span class="cx"> localizedStrings[&quot;Content Security Policy violation of directive: %s&quot;] = &quot;Content Security Policy violation of directive: %s&quot;;
</span><span class="cx"> localizedStrings[&quot;Continue script execution (%s or %s)&quot;] = &quot;Continue script execution (%s or %s)&quot;;
</span><span class="cx"> localizedStrings[&quot;Continue to Here&quot;] = &quot;Continue to Here&quot;;
</span><span class="lines">@@ -566,7 +565,6 @@
</span><span class="cx"> localizedStrings[&quot;Readonly&quot;] = &quot;Readonly&quot;;
</span><span class="cx"> localizedStrings[&quot;Reasons for compositing:&quot;] = &quot;Reasons for compositing:&quot;;
</span><span class="cx"> localizedStrings[&quot;Recording&quot;] = &quot;Recording&quot;;
</span><del>-localizedStrings[&quot;Records&quot;] = &quot;Records&quot;;
</del><span class="cx"> localizedStrings[&quot;Reference Issue&quot;] = &quot;Reference Issue&quot;;
</span><span class="cx"> localizedStrings[&quot;Reflection&quot;] = &quot;Reflection&quot;;
</span><span class="cx"> localizedStrings[&quot;Refresh&quot;] = &quot;Refresh&quot;;
</span><span class="lines">@@ -603,6 +601,7 @@
</span><span class="cx"> localizedStrings[&quot;Role&quot;] = &quot;Role&quot;;
</span><span class="cx"> localizedStrings[&quot;Samples&quot;] = &quot;Samples&quot;;
</span><span class="cx"> localizedStrings[&quot;Scheme&quot;] = &quot;Scheme&quot;;
</span><ins>+localizedStrings[&quot;Scope&quot;] = &quot;Scope&quot;;
</ins><span class="cx"> localizedStrings[&quot;Scope Chain&quot;] = &quot;Scope Chain&quot;;
</span><span class="cx"> localizedStrings[&quot;Script&quot;] = &quot;Script&quot;;
</span><span class="cx"> localizedStrings[&quot;Script Evaluated&quot;] = &quot;Script Evaluated&quot;;
</span><span class="lines">@@ -657,7 +656,6 @@
</span><span class="cx"> localizedStrings[&quot;Snapshot %d&quot;] = &quot;Snapshot %d&quot;;
</span><span class="cx"> localizedStrings[&quot;Snapshot Comparison (%d and %d)&quot;] = &quot;Snapshot Comparison (%d and %d)&quot;;
</span><span class="cx"> localizedStrings[&quot;Snapshot List&quot;] = &quot;Snapshot List&quot;;
</span><del>-localizedStrings[&quot;Snapshots&quot;] = &quot;Snapshots&quot;;
</del><span class="cx"> localizedStrings[&quot;Socket&quot;] = &quot;Socket&quot;;
</span><span class="cx"> localizedStrings[&quot;Sockets&quot;] = &quot;Sockets&quot;;
</span><span class="cx"> localizedStrings[&quot;Sort Ascending&quot;] = &quot;Sort Ascending&quot;;
</span><span class="lines">@@ -705,6 +703,8 @@
</span><span class="cx"> localizedStrings[&quot;The  webkit  prefix is needed for this property.\nClick to insert a duplicate with the prefix.&quot;] = &quot;The  webkit  prefix is needed for this property.\nClick to insert a duplicate with the prefix.&quot;;
</span><span class="cx"> localizedStrings[&quot;The  webkit  prefix is not necessary.\nClick to insert a duplicate without the prefix.&quot;] = &quot;The  webkit  prefix is not necessary.\nClick to insert a duplicate without the prefix.&quot;;
</span><span class="cx"> localizedStrings[&quot;This Element&quot;] = &quot;This Element&quot;;
</span><ins>+localizedStrings[&quot;This object is a root&quot;] = &quot;This object is a root&quot;;
+localizedStrings[&quot;This object is referenced by internal objects&quot;] = &quot;This object is referenced by internal objects&quot;;
</ins><span class="cx"> localizedStrings[&quot;This property needs a value.\nClick to open autocomplete.&quot;] = &quot;This property needs a value.\nClick to open autocomplete.&quot;;
</span><span class="cx"> localizedStrings[&quot;Time&quot;] = &quot;Time&quot;;
</span><span class="cx"> localizedStrings[&quot;Time until the load event fired, click to show the Network Requests timeline&quot;] = &quot;Time until the load event fired, click to show the Network Requests timeline&quot;;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceMainhtml"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (198195 => 198196)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Main.html        2016-03-15 04:59:39 UTC (rev 198195)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html        2016-03-15 05:02:28 UTC (rev 198196)
</span><span class="lines">@@ -308,8 +308,8 @@
</span><span class="cx">     &lt;script src=&quot;Models/DefaultDashboard.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/ExecutionContext.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/ExecutionContextList.js&quot;&gt;&lt;/script&gt;
</span><ins>+    &lt;script src=&quot;Models/FPSInstrument.js&quot;&gt;&lt;/script&gt;
</ins><span class="cx">     &lt;script src=&quot;Models/Frame.js&quot;&gt;&lt;/script&gt;
</span><del>-    &lt;script src=&quot;Models/FPSInstrument.js&quot;&gt;&lt;/script&gt;
</del><span class="cx">     &lt;script src=&quot;Models/GarbageCollection.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/Geometry.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/Gradient.js&quot;&gt;&lt;/script&gt;
</span><span class="lines">@@ -319,6 +319,7 @@
</span><span class="cx">     &lt;script src=&quot;Models/HeapSnapshotDiff.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/HeapSnapshotEdge.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/HeapSnapshotNode.js&quot;&gt;&lt;/script&gt;
</span><ins>+    &lt;script src=&quot;Models/HeapSnapshotRootPath.js&quot;&gt;&lt;/script&gt;
</ins><span class="cx">     &lt;script src=&quot;Models/IndexedDatabase.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/IndexedDatabaseObjectStore.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/IndexedDatabaseObjectStoreIndex.js&quot;&gt;&lt;/script&gt;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsHeapSnapshotNodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshotNode.js (198195 => 198196)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshotNode.js        2016-03-15 04:59:39 UTC (rev 198195)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshotNode.js        2016-03-15 05:02:28 UTC (rev 198196)
</span><span class="lines">@@ -35,4 +35,62 @@
</span><span class="cx">         this.outgoingEdges = [];
</span><span class="cx">         this.incomingEdges = [];
</span><span class="cx">     }
</span><ins>+
+    // Public
+
+    get shortestGCRootPath()
+    {
+        // Returns an array from this node to a gcRoot node.
+        // E.g. [Node, Edge, Node, Edge, Node].
+        // Internal nodes are avoided, so if the path is empty this
+        // node is either a gcRoot or only reachable via Internal nodes.
+
+        if (this._shortestGCRootPath !== undefined)
+            return this._shortestGCRootPath;
+
+        let paths = this._gcRootPaths();
+        paths.sort((a, b) =&gt; a.length - b.length);
+        this._shortestGCRootPath = paths[0] || null;
+
+        return this._shortestGCRootPath;
+    }
+
+    // Private
+
+    _gcRootPaths()
+    {
+        if (this.gcRoot)
+            return [];
+
+        let paths = [];
+        let currentPath = [];
+        let visitedSet = new Set;
+
+        function visitNode(node) {
+            if (node.gcRoot) {
+                let fullPath = currentPath.slice();
+                fullPath.push(node);
+                paths.push(fullPath);
+                return;
+            }
+
+            if (visitedSet.has(node))
+                return;
+            visitedSet.add(node);
+
+            currentPath.push(node);
+            for (let parentEdge of node.incomingEdges) {
+                if (parentEdge.from.internal)
+                    continue;
+                currentPath.push(parentEdge);
+                visitNode(parentEdge.from);
+                currentPath.pop();
+            }
+            currentPath.pop();
+        }
+
+        visitNode(this);
+
+        return paths;
+    }
</ins><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsHeapSnapshotRootPathjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshotRootPath.js (0 => 198196)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshotRootPath.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshotRootPath.js        2016-03-15 05:02:28 UTC (rev 198196)
</span><span class="lines">@@ -0,0 +1,165 @@
</span><ins>+/*
+ * Copyright (C) 2016 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.
+ */
+
+WebInspector.HeapSnapshotRootPath = class HeapSnapshotRootPath extends WebInspector.Object
+{
+    constructor(node, pathComponent, parent, isGlobalScope)
+    {
+        super();
+
+        console.assert(!node || node instanceof WebInspector.HeapSnapshotNode);
+        console.assert(!pathComponent || typeof pathComponent === &quot;string&quot;);
+        console.assert(!parent || parent instanceof WebInspector.HeapSnapshotRootPath);
+
+        this._node = node || null;
+        this._parent = parent || null;
+        this._pathComponent = typeof pathComponent === &quot;string&quot; ? pathComponent : null;
+        this._isGlobalScope = isGlobalScope || false;
+
+        // Become the new root when appended to an empty path.
+        if (this._parent &amp;&amp; this._parent.isEmpty())
+            this._parent = null;
+    }
+
+    // Static
+
+    static emptyPath()
+    {
+        return new WebInspector.HeapSnapshotRootPath(null);
+    }
+
+    // Public
+
+    get node() { return this._node; }
+    get parent() { return this._parent; }
+    get pathComponent() { return this._pathComponent; }
+
+    get rootNode()
+    {
+        return this._parent ? this._parent.rootNode : this._node;
+    }
+
+    get fullPath()
+    {
+        let components = [];
+        for (let p = this; p &amp;&amp; p.pathComponent; p = p.parent)
+            components.push(p.pathComponent);
+        components.reverse();
+        return components.join(&quot;&quot;);
+    }
+
+    isRoot()
+    {
+        return !this._parent;
+    }
+
+    isEmpty()
+    {
+        return !this._node;
+    }
+
+    isGlobalScope()
+    {
+        return this._isGlobalScope;
+    }
+
+    isPathComponentImpossible()
+    {
+        return this._pathComponent &amp;&amp; this._pathComponent.startsWith(&quot;@&quot;);
+    }
+
+    isFullPathImpossible()
+    {
+        if (this.isEmpty())
+            return true;
+
+        if (this.isPathComponentImpossible())
+            return true;
+
+        if (this._parent)
+            return this._parent.isFullPathImpossible();
+
+        return false;
+    }
+
+    appendInternal(node)
+    {
+        return new WebInspector.HeapSnapshotRootPath(node, WebInspector.HeapSnapshotRootPath.SpecialPathComponent.InternalPropertyName, this);
+    }
+
+    appendArrayIndex(node, index)
+    {
+        let component = &quot;[&quot; + index + &quot;]&quot;;
+        return new WebInspector.HeapSnapshotRootPath(node, component, this);
+    }
+
+    appendPropertyName(node, propertyName)
+    {
+        let component = this._canPropertyNameBeDotAccess(propertyName) ? &quot;.&quot; + propertyName : &quot;[&quot; + doubleQuotedString(propertyName) + &quot;]&quot;;
+        return new WebInspector.HeapSnapshotRootPath(node, component, this);
+    }
+
+    appendVariableName(node, variableName)
+    {
+        // Treat as a property of the global object, e.g. &quot;window.foo&quot;.
+        if (this._isGlobalScope)
+            return this.appendPropertyName(node, variableName);
+        return new WebInspector.HeapSnapshotRootPath(node, variableName, this);
+    }
+
+    appendGlobalScopeName(node, globalScopeName)
+    {
+        return new WebInspector.HeapSnapshotRootPath(node, globalScopeName, this, true);
+    }
+
+    appendEdge(edge)
+    {
+        console.assert(edge instanceof WebInspector.HeapSnapshotEdge);
+
+        switch (edge.type) {
+        case WebInspector.HeapSnapshotEdge.EdgeType.Internal:
+            return this.appendInternal(edge.to);
+        case WebInspector.HeapSnapshotEdge.EdgeType.Index:
+            return this.appendArrayIndex(edge.to, edge.data);
+        case WebInspector.HeapSnapshotEdge.EdgeType.Property:
+            return this.appendPropertyName(edge.to, edge.data);
+        case WebInspector.HeapSnapshotEdge.EdgeType.Variable:
+            return this.appendVariableName(edge.to, edge.data);
+        }
+
+        console.error(&quot;Unexpected edge type&quot;, edge.type);
+    }
+
+    // Private
+
+    _canPropertyNameBeDotAccess(propertyName)
+    {
+        return /^(?![0-9])\w+$/.test(propertyName);
+    }
+};
+
+WebInspector.HeapSnapshotRootPath.SpecialPathComponent = {
+    InternalPropertyName: &quot;@internal&quot;,
+};
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsHeapAllocationsTimelineViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js (198195 => 198196)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js        2016-03-15 04:59:39 UTC (rev 198195)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js        2016-03-15 05:02:28 UTC (rev 198196)
</span><span class="lines">@@ -101,6 +101,7 @@
</span><span class="cx">         this._heapSnapshotDiff = null;
</span><span class="cx">         this._cancelSelectComparisonHeapSnapshots();
</span><span class="cx"> 
</span><ins>+        this._contentViewContainer.hidden();
</ins><span class="cx">         this.removeSubview(this._contentViewContainer);
</span><span class="cx">         this.addSubview(this._dataGrid);
</span><span class="cx"> 
</span><span class="lines">@@ -113,6 +114,7 @@
</span><span class="cx">         if (this._showingSnapshotList) {
</span><span class="cx">             this.removeSubview(this._dataGrid);
</span><span class="cx">             this.addSubview(this._contentViewContainer);
</span><ins>+            this._contentViewContainer.shown();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         this._showingSnapshotList = false;
</span><span class="lines">@@ -139,6 +141,7 @@
</span><span class="cx">         if (this._showingSnapshotList) {
</span><span class="cx">             this.removeSubview(this._dataGrid);
</span><span class="cx">             this.addSubview(this._contentViewContainer);
</span><ins>+            this._contentViewContainer.shown();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         this._showingSnapshotList = false;
</span><span class="lines">@@ -189,10 +192,28 @@
</span><span class="cx">         this.showHeapSnapshotTimelineRecord(timelineRecord);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    shown()
+    {
+        super.shown();
+
+        if (!this._showingSnapshotList)
+            this._contentViewContainer.shown();
+    }
+
+    hidden()
+    {
+        super.hidden();
+
+        if (!this._showingSnapshotList)
+            this._contentViewContainer.hidden();
+    }
+
</ins><span class="cx">     closed()
</span><span class="cx">     {
</span><span class="cx">         console.assert(this.representedObject instanceof WebInspector.Timeline);
</span><span class="cx">         this.representedObject.removeEventListener(null, null, this);
</span><ins>+
+        this._contentViewContainer.closeAllContentViews();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     layout()
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsHeapSnapshotInstanceDataGridNodejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotInstanceDataGridNode.js (198195 => 198196)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotInstanceDataGridNode.js        2016-03-15 04:59:39 UTC (rev 198195)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotInstanceDataGridNode.js        2016-03-15 05:02:28 UTC (rev 198196)
</span><span class="lines">@@ -40,6 +40,51 @@
</span><span class="cx">         this._percent = (this._node.size / this._tree._heapSnapshot.totalSize) * 100;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // Static
+
+    static logHeapSnapshotNode(node)
+    {
+        let heapObjectIdentifier = node.id;
+
+        let synthetic = true;
+        let text = WebInspector.UIString(&quot;Heap Snapshot Object (@%d)&quot;).format(heapObjectIdentifier);
+
+        let gcRootPath = node.shortestGCRootPath;
+        if (gcRootPath) {
+            gcRootPath = gcRootPath.slice().reverse();
+            let windowIndex = gcRootPath.findIndex((x) =&gt; {
+                return x instanceof WebInspector.HeapSnapshotNode &amp;&amp; x.className === &quot;Window&quot;;
+            });
+
+            let heapSnapshotRootPath = WebInspector.HeapSnapshotRootPath.emptyPath();
+            for (let i = windowIndex === -1 ? 0 : windowIndex; i &lt; gcRootPath.length; ++i) {
+                let component = gcRootPath[i];
+                if (component instanceof WebInspector.HeapSnapshotNode) {
+                    if (component.className === &quot;Window&quot;)
+                        heapSnapshotRootPath = heapSnapshotRootPath.appendGlobalScopeName(component, &quot;window&quot;);
+                } else if (component instanceof WebInspector.HeapSnapshotEdge)
+                    heapSnapshotRootPath = heapSnapshotRootPath.appendEdge(component);
+            }
+
+            if (!heapSnapshotRootPath.isFullPathImpossible()) {
+                synthetic = false;
+                text = heapSnapshotRootPath.fullPath;
+            }
+        }
+
+        if (node.className === &quot;string&quot;) {
+            HeapAgent.getPreview(heapObjectIdentifier, function(error, string, functionDetails, objectPreviewPayload) {
+                let remoteObject = error ? WebInspector.RemoteObject.fromPrimitiveValue(undefined) : WebInspector.RemoteObject.fromPrimitiveValue(string);
+                WebInspector.consoleLogViewController.appendImmediateExecutionWithResult(text, remoteObject, synthetic);                
+            });
+        } else {
+            HeapAgent.getRemoteObject(heapObjectIdentifier, WebInspector.RuntimeManager.ConsoleObjectGroup, function(error, remoteObjectPayload) {
+                let remoteObject = error ? WebInspector.RemoteObject.fromPrimitiveValue(undefined) : WebInspector.RemoteObject.fromPayload(remoteObjectPayload);
+                WebInspector.consoleLogViewController.appendImmediateExecutionWithResult(text, remoteObject, synthetic);
+            });
+        }
+    }
+
</ins><span class="cx">     // Protected
</span><span class="cx"> 
</span><span class="cx">     get data() { return this._node; }
</span><span class="lines">@@ -77,8 +122,13 @@
</span><span class="cx"> 
</span><span class="cx">             let idElement = containerElement.appendChild(document.createElement(&quot;span&quot;));
</span><span class="cx">             idElement.classList.add(&quot;object-id&quot;);
</span><del>-            idElement.textContent = &quot;@&quot; + id + &quot; &quot;;
</del><ins>+            idElement.textContent = &quot;@&quot; + id;
+            idElement.addEventListener(&quot;click&quot;, WebInspector.HeapSnapshotInstanceDataGridNode.logHeapSnapshotNode.bind(null, this._node));
+            idElement.addEventListener(&quot;mouseover&quot;, this._mouseoverHandler.bind(this));
</ins><span class="cx"> 
</span><ins>+            let spacerElement = containerElement.appendChild(document.createElement(&quot;span&quot;));
+            spacerElement.textContent = &quot; &quot;;
+
</ins><span class="cx">             HeapAgent.getPreview(id, (error, string, functionDetails, objectPreviewPayload) =&gt; {
</span><span class="cx">                 if (error) {
</span><span class="cx">                     let previewErrorElement = containerElement.appendChild(document.createElement(&quot;span&quot;));
</span><span class="lines">@@ -137,17 +187,116 @@
</span><span class="cx">     _contextMenuHandler(event)
</span><span class="cx">     {
</span><span class="cx">         let contextMenu = WebInspector.ContextMenu.createFromEvent(event);
</span><del>-
</del><span class="cx">         contextMenu.appendSeparator();
</span><ins>+        contextMenu.appendItem(WebInspector.UIString(&quot;Log Value&quot;), WebInspector.HeapSnapshotInstanceDataGridNode.logHeapSnapshotNode.bind(null, this._node));
+    }
</ins><span class="cx"> 
</span><del>-        contextMenu.appendItem(WebInspector.UIString(&quot;Log Value&quot;), () =&gt; {
-            let heapObjectIdentifier = this._node.id;
-            HeapAgent.getRemoteObject(heapObjectIdentifier, WebInspector.RuntimeManager.ConsoleObjectGroup, function(error, remoteObjectPayload) {
-                const synthetic = true;
-                let remoteObject = error ? WebInspector.RemoteObject.fromPrimitive(undefined) : WebInspector.RemoteObject.fromPayload(remoteObjectPayload);
-                let text = WebInspector.UIString(&quot;Heap Snapshot Object (@%d)&quot;).format(heapObjectIdentifier);
-                WebInspector.consoleLogViewController.appendImmediateExecutionWithResult(text, remoteObject, synthetic);
</del><ins>+    _mouseoverHandler(event)
+    {
+        let targetFrame = WebInspector.Rect.rectFromClientRect(event.target.getBoundingClientRect());
+        if (!targetFrame.size.width &amp;&amp; !targetFrame.size.height)
+            return;
+
+        if (this._tree.popoverNode === this._node)
+            return;
+
+        this._tree.popoverNode = this._node;
+
+        let popoverContentElement = document.createElement(&quot;div&quot;);
+        popoverContentElement.classList.add(&quot;heap-snapshot&quot;, &quot;heap-snapshot-instance-popover-content&quot;);
+
+        function appendPath(path) {
+            let tableElement = popoverContentElement.appendChild(document.createElement(&quot;table&quot;));
+            tableElement.classList.add(&quot;table&quot;);
+
+            path = path.slice().reverse();
+            let windowIndex = path.findIndex((x) =&gt; {
+                return x instanceof WebInspector.HeapSnapshotNode &amp;&amp; x.className === &quot;Window&quot;;
</ins><span class="cx">             });
</span><del>-        });
</del><ins>+
+            let edge = null;
+            for (let i = windowIndex === -1 ? 0 : windowIndex; i &lt; path.length; ++i) {
+                let component = path[i];
+                if (component instanceof WebInspector.HeapSnapshotEdge) {
+                    edge = component;
+                    continue;
+                }
+                appendPathRow(tableElement, edge, component);
+                edge = null;
+            }
+        }
+
+        function appendPathRow(tableElement, edge, node) {
+            let tableRow = tableElement.appendChild(document.createElement(&quot;tr&quot;));
+
+            // Edge name.
+            let pathDataElement = tableRow.appendChild(document.createElement(&quot;td&quot;));
+            pathDataElement.classList.add(&quot;edge-name&quot;);
+
+            if (node.className === &quot;Window&quot;)
+                pathDataElement.textContent = &quot;window&quot;;
+            else if (edge) {
+                let edgeString = stringifyEdge(edge);
+                pathDataElement.textContent = typeof edgeString === &quot;string&quot; ? edgeString : emDash;
+            } else
+                pathDataElement.textContent = emDash;
+
+            if (pathDataElement.textContent.length &gt; 10)
+                pathDataElement.title = pathDataElement.textContent;
+
+            // Object.
+            let objectDataElement = tableRow.appendChild(document.createElement(&quot;td&quot;));
+            objectDataElement.classList.add(&quot;object-data&quot;);
+
+            let containerElement = objectDataElement.appendChild(document.createElement(&quot;div&quot;));
+            containerElement.classList.add(&quot;node&quot;);
+
+            let iconElement = containerElement.appendChild(document.createElement(&quot;img&quot;));
+            iconElement.classList.add(&quot;icon&quot;, WebInspector.HeapSnapshotClusterContentView.iconStyleClassNameForClassName(node.className, node.internal));
+
+            let classNameElement = containerElement.appendChild(document.createElement(&quot;span&quot;));
+            classNameElement.textContent = sanitizeClassName(node.className);
+
+            let idElement = containerElement.appendChild(document.createElement(&quot;span&quot;));
+            idElement.classList.add(&quot;object-id&quot;);
+            idElement.textContent = &quot; @&quot; + node.id;
+            idElement.addEventListener(&quot;click&quot;, WebInspector.HeapSnapshotInstanceDataGridNode.logHeapSnapshotNode.bind(null, node));
+        }
+
+        function sanitizeClassName(className) {
+            if (className.endsWith(&quot;LexicalEnvironment&quot;))
+                return WebInspector.UIString(&quot;Scope&quot;);
+            return className;
+        }
+
+        function stringifyEdge(edge) {
+            switch(edge.type) {
+            case WebInspector.HeapSnapshotEdge.EdgeType.Property:
+            case WebInspector.HeapSnapshotEdge.EdgeType.Variable:
+                if (/^(?![0-9])\w+$/.test(edge.data))
+                    return edge.data;
+                return &quot;[&quot; + doubleQuotedString(edge.data) + &quot;]&quot;;
+            case WebInspector.HeapSnapshotEdge.EdgeType.Index:
+                return &quot;[&quot; + edge.data + &quot;]&quot;;
+            case WebInspector.HeapSnapshotEdge.EdgeType.Internal:
+            default:
+                return null;
+            }
+        }
+
+        if (this._node.gcRoot) {
+            let textElement = popoverContentElement.appendChild(document.createElement(&quot;div&quot;));
+            textElement.textContent = WebInspector.UIString(&quot;This object is a root&quot;);
+        } else {
+            let path = this._node.shortestGCRootPath;
+            if (path)
+                appendPath(path);
+            else {
+                let emptyElement = popoverContentElement.appendChild(document.createElement(&quot;div&quot;));
+                emptyElement.textContent = WebInspector.UIString(&quot;This object is referenced by internal objects&quot;);
+            }
+        }
+
+        this._tree.popover.presentNewContentWithFrame(popoverContentElement, targetFrame.pad(2), [WebInspector.RectEdge.MAX_Y, WebInspector.RectEdge.MIN_Y, WebInspector.RectEdge.MAX_X]);
</ins><span class="cx">     }
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsHeapSnapshotInstancesContentViewcss"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotInstancesContentView.css (198195 => 198196)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotInstancesContentView.css        2016-03-15 04:59:39 UTC (rev 198195)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotInstancesContentView.css        2016-03-15 05:02:28 UTC (rev 198196)
</span><span class="lines">@@ -37,10 +37,14 @@
</span><span class="cx">     display: inline-block;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.heap-snapshot &gt; .data-grid tr:not(.selected) td .object-id {
</del><ins>+.heap-snapshot .object-id {
</ins><span class="cx">     color: gray;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+.heap-snapshot .object-id:hover {
+    text-decoration: underline;
+}
+
</ins><span class="cx"> .heap-snapshot &gt; .data-grid tr:not(.selected) td .preview-error {
</span><span class="cx">     color: red;
</span><span class="cx"> }
</span><span class="lines">@@ -75,7 +79,7 @@
</span><span class="cx">     width: 16px;
</span><span class="cx">     height: 16px;
</span><span class="cx">     margin-top: 1px;
</span><del>-    margin-right: 3px;
</del><ins>+    margin-right: 4px;
</ins><span class="cx">     content: url(../Images/TypeUndefined.svg);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -121,3 +125,46 @@
</span><span class="cx">     display: inline-block;
</span><span class="cx">     height: 16px;
</span><span class="cx"> }
</span><ins>+
+.heap-snapshot-instance-popover-content {
+    white-space: pre;
+    padding: 5px 10px;
+}
+
+.heap-snapshot-instance-popover-content table {
+    border-collapse: collapse;
+}
+
+.heap-snapshot-instance-popover-content tr {
+    margin: 0;
+    padding: 1px 0;
+}
+
+.heap-snapshot-instance-popover-content td {
+    margin: 0;
+    padding: 0;
+}
+
+.heap-snapshot-instance-popover-content td.edge-name {
+    text-align: right;
+    max-width: 110px;
+    text-overflow: ellipsis;
+    overflow: hidden;
+
+    border-right: 1px solid var(--border-color);
+    padding-right: 5px;
+}
+
+.heap-snapshot-instance-popover-content td.object-data {
+    padding-left: 5px;
+}
+
+.heap-snapshot-instance-popover-content .node {
+    height: 17px;
+    line-height: 17px;
+}
+
+.heap-snapshot-instance-popover-content .node * {
+    display: inline-block;
+    vertical-align: top;
+}
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsHeapSnapshotInstancesContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotInstancesContentView.js (198195 => 198196)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotInstancesContentView.js        2016-03-15 04:59:39 UTC (rev 198195)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotInstancesContentView.js        2016-03-15 05:02:28 UTC (rev 198196)
</span><span class="lines">@@ -87,6 +87,15 @@
</span><span class="cx">         this._sortDataGrid();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // Protected
+
+    hidden()
+    {
+        super.hidden();
+
+        this._heapSnapshotDataGridTree.hidden();
+    }
+
</ins><span class="cx">     // Private
</span><span class="cx"> 
</span><span class="cx">     _sortDataGrid()
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsHeapSnapshotInstancesDataGridTreejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotInstancesDataGridTree.js (198195 => 198196)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotInstancesDataGridTree.js        2016-03-15 04:59:39 UTC (rev 198195)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotInstancesDataGridTree.js        2016-03-15 05:02:28 UTC (rev 198196)
</span><span class="lines">@@ -37,6 +37,9 @@
</span><span class="cx">         this._sortComparator = sortComparator;
</span><span class="cx">         this._includeInternalObjects = includeInternalObjects;
</span><span class="cx"> 
</span><ins>+        this._popover = null;
+        this._popoverNode = null;
+
</ins><span class="cx">         this._populateTopLevel();
</span><span class="cx">         this.sort();
</span><span class="cx">     }
</span><span class="lines">@@ -80,6 +83,24 @@
</span><span class="cx">         this.sort();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    get popover()
+    {
+        if (!this._popover)
+            this._popover = new WebInspector.Popover(this);
+
+        return this._popover;
+    }
+
+    get popoverNode()
+    {
+        return this._popoverNode;
+    }
+
+    set popoverNode(x)
+    {
+        this._popoverNode = x;
+    }
+
</ins><span class="cx">     get children()
</span><span class="cx">     {
</span><span class="cx">         return this._children;
</span><span class="lines">@@ -117,6 +138,19 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    hidden()
+    {
+        if (this._popover &amp;&amp; this._popover.visible)
+            this._popover.dismiss();
+    }
+
+    // Popover delegate
+
+    willDismissPopover(popover)
+    {
+        this._popoverNode = null;
+    }
+
</ins><span class="cx">     // Private
</span><span class="cx"> 
</span><span class="cx">     _populateTopLevel()
</span></span></pre>
</div>
</div>

</body>
</html>