<!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>[201196] branches/safari-602.1.32-branch</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/201196">201196</a></dd>
<dt>Author</dt> <dd>bshafiei@apple.com</dd>
<dt>Date</dt> <dd>2016-05-19 15:58:32 -0700 (Thu, 19 May 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/201183">r201183</a>. rdar://problem/26375866</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari602132branchLayoutTestsChangeLog">branches/safari-602.1.32-branch/LayoutTests/ChangeLog</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIChangeLog">branches/safari-602.1.32-branch/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceProxiesHeapSnapshotDiffProxyjs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotDiffProxy.js</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceProxiesHeapSnapshotNodeProxyjs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotNodeProxy.js</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceProxiesHeapSnapshotProxyjs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotProxy.js</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceProxiesHeapSnapshotWorkerProxyjs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotWorkerProxy.js</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceViewsHeapAllocationsTimelineViewjs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceViewsHeapSnapshotClassDataGridNodejs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotClassDataGridNode.js</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceViewsHeapSnapshotContentViewjs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotContentView.js</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceViewsHeapSnapshotDataGridTreejs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotDataGridTree.js</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceWorkersHeapSnapshotHeapSnapshotjs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Workers/HeapSnapshot/HeapSnapshot.js</a></li>
<li><a href="#branchessafari602132branchSourceWebInspectorUIUserInterfaceWorkersHeapSnapshotHeapSnapshotWorkerjs">branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Workers/HeapSnapshot/HeapSnapshotWorker.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#branchessafari602132branchLayoutTestsinspectorunittestsheapsnapshotcollectioneventexpectedtxt">branches/safari-602.1.32-branch/LayoutTests/inspector/unit-tests/heap-snapshot-collection-event-expected.txt</a></li>
<li><a href="#branchessafari602132branchLayoutTestsinspectorunittestsheapsnapshotcollectioneventhtml">branches/safari-602.1.32-branch/LayoutTests/inspector/unit-tests/heap-snapshot-collection-event.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari602132branchLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/LayoutTests/ChangeLog (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/LayoutTests/ChangeLog        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/LayoutTests/ChangeLog        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -1,5 +1,20 @@
</span><span class="cx"> 2016-05-19  Babak Shafiei  &lt;bshafiei@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r201183. rdar://problem/26375866
+
+    2016-05-19  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+            Web Inspector: HeapSnapshot Instances view should remove dead objects
+            https://bugs.webkit.org/show_bug.cgi?id=157920
+            &lt;rdar://problem/26375866&gt;
+
+            Reviewed by Timothy Hatcher.
+
+            * inspector/unit-tests/heap-snapshot-collection-event-expected.txt: Added.
+            * inspector/unit-tests/heap-snapshot-collection-event.html: Added.
+
+2016-05-19  Babak Shafiei  &lt;bshafiei@apple.com&gt;
+
</ins><span class="cx">         Merge r200651. rdar://problem/26188642
</span><span class="cx"> 
</span><span class="cx">     2016-05-10  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari602132branchLayoutTestsinspectorunittestsheapsnapshotcollectioneventexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/safari-602.1.32-branch/LayoutTests/inspector/unit-tests/heap-snapshot-collection-event-expected.txt (0 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/LayoutTests/inspector/unit-tests/heap-snapshot-collection-event-expected.txt                                (rev 0)
+++ branches/safari-602.1.32-branch/LayoutTests/inspector/unit-tests/heap-snapshot-collection-event-expected.txt        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -0,0 +1,20 @@
</span><ins>+Testing HeapSnapshot CollectionEvent between snapshots.
+
+
+== Running test suite: HeapSnapshot.CollectionEvent
+-- Running test case: HeapSnapshot
+PASS: Should not have an error creating a snapshot.
+PASS: Should create HeapSnapshotProxy snapshot.
+
+-- Running test case: HeapSnapshotCollectionEvent
+PASS: Should not have an error creating a snapshot.
+PASS: Received HeapSnapshot.CollectionEvent.
+PASS: Collection should include at least 200 nodes (100 objects and 100 strings).
+PASS: Collection should affect the first snapshot.
+
+-- Running test case: HeapSnapshot.prototype.updateCategories
+PASS: 0 Objects were dead before.
+PASS: At least 100 Objects are dead after.
+PASS: 0 strings were dead before.
+PASS: At least 100 strings are dead after.
+
</ins></span></pre></div>
<a id="branchessafari602132branchLayoutTestsinspectorunittestsheapsnapshotcollectioneventhtml"></a>
<div class="addfile"><h4>Added: branches/safari-602.1.32-branch/LayoutTests/inspector/unit-tests/heap-snapshot-collection-event.html (0 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/LayoutTests/inspector/unit-tests/heap-snapshot-collection-event.html                                (rev 0)
+++ branches/safari-602.1.32-branch/LayoutTests/inspector/unit-tests/heap-snapshot-collection-event.html        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -0,0 +1,82 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../http/tests/inspector/resources/inspector-test.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+function triggerCreateObjects() {
+    window.list = [];
+    for (let i = 0; i &lt; 100; ++i)
+        window.list.push({key: &quot;value&quot; + i});
+}
+
+function triggerRemoveObjects() {
+    window.list = null;
+}
+
+function test()
+{
+    let suite = InspectorTest.createAsyncSuite(&quot;HeapSnapshot.CollectionEvent&quot;);
+
+    let snapshot = null;
+
+    suite.addTestCase({
+        name: &quot;HeapSnapshot&quot;,
+        test: (resolve, reject) =&gt; {
+            InspectorTest.evaluateInPage(&quot;triggerCreateObjects()&quot;);
+            HeapAgent.snapshot((error, timestamp, snapshotStringData) =&gt; {
+                InspectorTest.expectThat(!error, &quot;Should not have an error creating a snapshot.&quot;);
+                let workerProxy = WebInspector.HeapSnapshotWorkerProxy.singleton();
+                workerProxy.createSnapshot(snapshotStringData, ({objectId, snapshot: serializedSnapshot}) =&gt; {
+                    snapshot = WebInspector.HeapSnapshotProxy.deserialize(objectId, serializedSnapshot);
+                    InspectorTest.expectThat(snapshot, &quot;Should create HeapSnapshotProxy snapshot.&quot;);
+                    resolve();
+                });
+            });
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;HeapSnapshotCollectionEvent&quot;,
+        test: (resolve, reject) =&gt; {
+            InspectorTest.evaluateInPage(&quot;triggerRemoveObjects()&quot;);
+
+            let workerProxy = WebInspector.HeapSnapshotWorkerProxy.singleton();
+            HeapAgent.snapshot((error, timestamp, snapshotStringData) =&gt; {
+                InspectorTest.expectThat(!error, &quot;Should not have an error creating a snapshot.&quot;);
+                workerProxy.createSnapshot(snapshotStringData, ({objectId, snapshot: serializedSnapshot}) =&gt; {
+                    // Ignore result. This should trigger the collection event.
+                });
+            });
+
+            workerProxy.addEventListener(&quot;HeapSnapshot.CollectionEvent&quot;, (event) =&gt; {
+                InspectorTest.pass(&quot;Received HeapSnapshot.CollectionEvent.&quot;);
+                InspectorTest.expectThat(Object.keys(event.data.collectedNodes).length &gt;= 200, &quot;Collection should include at least 200 nodes (100 objects and 100 strings).&quot;);
+                InspectorTest.expectThat(event.data.affectedSnapshots.includes(snapshot.identifier), &quot;Collection should affect the first snapshot.&quot;);
+                resolve();
+            });
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;HeapSnapshot.prototype.updateCategories&quot;,
+        test: (resolve, reject) =&gt; {
+            let categoriesBefore = snapshot.categories;
+            snapshot.updateCategories(() =&gt; {
+                let categoriesAfter = snapshot.categories;
+                InspectorTest.expectThat(categoriesBefore.get(&quot;Object&quot;).deadCount === 0, &quot;0 Objects were dead before.&quot;);
+                InspectorTest.expectThat(categoriesAfter.get(&quot;Object&quot;).deadCount &gt;= 100, &quot;At least 100 Objects are dead after.&quot;);
+                InspectorTest.expectThat(categoriesBefore.get(&quot;string&quot;).deadCount === 0, &quot;0 strings were dead before.&quot;);
+                InspectorTest.expectThat(categoriesAfter.get(&quot;string&quot;).deadCount &gt;= 100, &quot;At least 100 strings are dead after.&quot;);
+                resolve();
+            });
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runTest()&quot;&gt;
+    &lt;p&gt;Testing HeapSnapshot CollectionEvent between snapshots.&lt;/p&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/ChangeLog (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/ChangeLog        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/ChangeLog        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -1,5 +1,97 @@
</span><span class="cx"> 2016-05-19  Babak Shafiei  &lt;bshafiei@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r201183. rdar://problem/26375866
+
+    2016-05-19  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+            Web Inspector: HeapSnapshot Instances view should remove dead objects
+            https://bugs.webkit.org/show_bug.cgi?id=157920
+            &lt;rdar://problem/26375866&gt;
+
+            Reviewed by Timothy Hatcher.
+
+            * UserInterface/Workers/HeapSnapshot/HeapSnapshotWorker.js:
+            (HeapSnapshotWorker):
+            (HeapSnapshotWorker.prototype.clearSnapshots):
+            (HeapSnapshotWorker.prototype.createSnapshot):
+            Preserve a list of snapshots for this page's session. When
+            new snapshots come in we can determine which nodes have died
+            and update previous snapshots. Emit a CollectionEvent
+            containing the nodes that were deleted and affected snapshots.
+
+            * UserInterface/Workers/HeapSnapshot/HeapSnapshot.js:
+            (HeapSnapshot):
+            Stash the largest node identifier.
+            Create a byte-per-node list to mark it as dead or alive.
+            All snapshots start with all live nodes.
+
+            (HeapSnapshot.prototype.updateDeadNodesAndGatherCollectionData):
+            (HeapSnapshot.prototype._markDeadNodes):
+            When we get a new snapshot we can mark dead nodes in previous
+            snapshots. Determine the nodeIdentifiers of dead nodes, and
+            mark them as dead if they existed in previous snapshots.
+
+            (HeapSnapshot.buildCategories):
+            (HeapSnapshot.prototype.updateCategories):
+            (HeapSnapshotDiff.prototype.updateCategories):
+            Include a &quot;deadCount&quot; in category data. And provide a method
+            to return an updated category list.
+
+            (HeapSnapshot.prototype.serializeNode):
+            Include a &quot;dead&quot; property on nodes when they are first fetched.
+
+            * UserInterface/Proxies/HeapSnapshotDiffProxy.js:
+            (WebInspector.HeapSnapshotDiffProxy.prototype.updateForCollectionEvent):
+            (WebInspector.HeapSnapshotDiffProxy.prototype.updateCategories):
+            * UserInterface/Proxies/HeapSnapshotNodeProxy.js:
+            (WebInspector.HeapSnapshotNodeProxy):
+            (WebInspector.HeapSnapshotNodeProxy.deserialize):
+            * UserInterface/Proxies/HeapSnapshotProxy.js:
+            (WebInspector.HeapSnapshotProxy.prototype.updateForCollectionEvent):
+            (WebInspector.HeapSnapshotProxy.prototype.updateCategories):
+            Update snapshot proxies from a collection event by updating properties
+            and dispatching an event from the model object.
+
+            * UserInterface/Proxies/HeapSnapshotWorkerProxy.js:
+            (WebInspector.HeapSnapshotWorkerProxy):
+            (WebInspector.HeapSnapshotWorkerProxy.prototype.clearSnapshots):
+            (WebInspector.HeapSnapshotWorkerProxy.prototype._mainResourceDidChange):
+            Clear the session snapshot list when the main resource changes.
+            However we can't yet clear the HeapSnapshot objects on the worker
+            because we may still have UI that interact with them.
+
+            * UserInterface/Views/HeapAllocationsTimelineView.js:
+            (WebInspector.HeapAllocationsTimelineView):
+            (WebInspector.HeapAllocationsTimelineView.prototype.closed):
+            Register and unregister for HeapSnapshot collection events.
+
+            (WebInspector.HeapAllocationsTimelineView.prototype._heapSnapshotCollectionEvent.updateHeapSnapshotForEvent):
+            (WebInspector.HeapAllocationsTimelineView.prototype._heapSnapshotCollectionEvent):
+            Update all the snapshots we know about when a collection event happens.
+
+            * UserInterface/Views/HeapSnapshotClassDataGridNode.js:
+            (WebInspector.HeapSnapshotClassDataGridNode.prototype.removeCollectedNodes):
+            (WebInspector.HeapSnapshotClassDataGridNode.prototype.updateCount):
+            (WebInspector.HeapSnapshotClassDataGridNode.prototype._populate):
+            (WebInspector.HeapSnapshotClassDataGridNode.prototype._fetchBatch):
+            * UserInterface/Views/HeapSnapshotContentView.js:
+            (WebInspector.HeapSnapshotContentView.prototype._heapSnapshotDataGridTreeDidPopulate):
+            (WebInspector.HeapSnapshotContentView):
+            * UserInterface/Views/HeapSnapshotDataGridTree.js:
+            (WebInspector.HeapSnapshotDataGridTree):
+            (WebInspector.HeapSnapshotDataGridTree.prototype.removeChild):
+            (WebInspector.HeapSnapshotDataGridTree.prototype.removeCollectedNodes):
+            (WebInspector.HeapSnapshotDataGridTree.prototype._heapSnapshotCollectedNodes):
+            (WebInspector.HeapSnapshotInstancesDataGridTree.prototype.populateTopLevel):
+            (WebInspector.HeapSnapshotInstancesDataGridTree.prototype.removeCollectedNodes):
+            (WebInspector.HeapSnapshotInstancesDataGridTree):
+            Update the Instances DataGridTree UI when a collection event happens.
+            Remove any top level InstanceDataGridNodes that may be showing for collected nodes.
+            Update the category counts on the ClassDataGridNodes.
+            Update FetchMoreDataGridNodes to have updated counts (and replace removed nodes).
+
+2016-05-19  Babak Shafiei  &lt;bshafiei@apple.com&gt;
+
</ins><span class="cx">         Merge r201177. rdar://problem/26373969
</span><span class="cx"> 
</span><span class="cx">     2016-05-19  Timothy Hatcher  &lt;timothy@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceProxiesHeapSnapshotDiffProxyjs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotDiffProxy.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotDiffProxy.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotDiffProxy.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -62,6 +62,16 @@
</span><span class="cx">     get totalObjectCount() { return this._totalObjectCount; }
</span><span class="cx">     get categories() { return this._categories; }
</span><span class="cx"> 
</span><ins>+    updateForCollectionEvent(event)
+    {
+        if (!event.data.affectedSnapshots.includes(this._snapshot2._identifier))
+            return;
+
+        this.updateCategories(() =&gt; {
+            this.dispatchEventToListeners(WebInspector.HeapSnapshotProxy.Event.CollectedNodes, event.data);
+        });
+    }
+
</ins><span class="cx">     allocationBucketCounts(bucketSizes, callback)
</span><span class="cx">     {
</span><span class="cx">         WebInspector.HeapSnapshotWorkerProxy.singleton().callMethod(this._proxyObjectId, &quot;allocationBucketCounts&quot;, bucketSizes, callback);
</span><span class="lines">@@ -74,6 +84,14 @@
</span><span class="cx">         });
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    updateCategories(callback)
+    {
+        WebInspector.HeapSnapshotWorkerProxy.singleton().callMethod(this._proxyObjectId, &quot;updateCategories&quot;, (categories) =&gt; {
+            this._categories = Map.fromObject(categories);
+            callback();
+        });
+    }
+
</ins><span class="cx">     nodeWithIdentifier(nodeIdentifier, callback)
</span><span class="cx">     {
</span><span class="cx">         WebInspector.HeapSnapshotWorkerProxy.singleton().callMethod(this._proxyObjectId, &quot;nodeWithIdentifier&quot;, nodeIdentifier, (serializedNode) =&gt; {
</span></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceProxiesHeapSnapshotNodeProxyjs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotNodeProxy.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotNodeProxy.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotNodeProxy.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -25,7 +25,7 @@
</span><span class="cx"> 
</span><span class="cx"> WebInspector.HeapSnapshotNodeProxy = class HeapSnapshotNodeProxy
</span><span class="cx"> {
</span><del>-    constructor(snapshotObjectId, identifier, className, size, retainedSize, internal, gcRoot, dominatorNodeIdentifier, hasChildren)
</del><ins>+    constructor(snapshotObjectId, identifier, className, size, retainedSize, internal, gcRoot, dead, dominatorNodeIdentifier, hasChildren)
</ins><span class="cx">     {
</span><span class="cx">         this._proxyObjectId = snapshotObjectId;
</span><span class="cx"> 
</span><span class="lines">@@ -35,6 +35,7 @@
</span><span class="cx">         this.retainedSize = retainedSize;
</span><span class="cx">         this.internal = internal;
</span><span class="cx">         this.gcRoot = gcRoot;
</span><ins>+        this.dead = dead;
</ins><span class="cx">         this.dominatorNodeIdentifier = dominatorNodeIdentifier;
</span><span class="cx">         this.hasChildren = hasChildren;
</span><span class="cx">     }
</span><span class="lines">@@ -43,8 +44,8 @@
</span><span class="cx"> 
</span><span class="cx">     static deserialize(objectId, serializedNode)
</span><span class="cx">     {
</span><del>-        let {id, className, size, retainedSize, internal, gcRoot, dominatorNodeIdentifier, hasChildren} = serializedNode;
-        return new WebInspector.HeapSnapshotNodeProxy(objectId, id, className, size, retainedSize, internal, gcRoot, dominatorNodeIdentifier, hasChildren);
</del><ins>+        let {id, className, size, retainedSize, internal, gcRoot, dead, dominatorNodeIdentifier, hasChildren} = serializedNode;
+        return new WebInspector.HeapSnapshotNodeProxy(objectId, id, className, size, retainedSize, internal, gcRoot, dead, dominatorNodeIdentifier, hasChildren);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Proxied
</span></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceProxiesHeapSnapshotProxyjs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotProxy.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotProxy.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotProxy.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -55,6 +55,16 @@
</span><span class="cx">     get totalObjectCount() { return this._totalObjectCount; }
</span><span class="cx">     get categories() { return this._categories; }
</span><span class="cx"> 
</span><ins>+    updateForCollectionEvent(event)
+    {
+        if (!event.data.affectedSnapshots.includes(this._identifier))
+            return;
+
+        this.updateCategories(() =&gt; {
+            this.dispatchEventToListeners(WebInspector.HeapSnapshotProxy.Event.CollectedNodes, event.data);
+        });
+    }
+
</ins><span class="cx">     allocationBucketCounts(bucketSizes, callback)
</span><span class="cx">     {
</span><span class="cx">         WebInspector.HeapSnapshotWorkerProxy.singleton().callMethod(this._proxyObjectId, &quot;allocationBucketCounts&quot;, bucketSizes, callback);
</span><span class="lines">@@ -67,6 +77,14 @@
</span><span class="cx">         });
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    updateCategories(callback)
+    {
+        WebInspector.HeapSnapshotWorkerProxy.singleton().callMethod(this._proxyObjectId, &quot;updateCategories&quot;, (categories) =&gt; {
+            this._categories = Map.fromObject(categories);
+            callback();
+        });
+    }
+
</ins><span class="cx">     nodeWithIdentifier(nodeIdentifier, callback)
</span><span class="cx">     {
</span><span class="cx">         WebInspector.HeapSnapshotWorkerProxy.singleton().callMethod(this._proxyObjectId, &quot;nodeWithIdentifier&quot;, nodeIdentifier, (serializedNode) =&gt; {
</span><span class="lines">@@ -74,3 +92,7 @@
</span><span class="cx">         });
</span><span class="cx">     }
</span><span class="cx"> };
</span><ins>+
+WebInspector.HeapSnapshotProxy.Event = {
+    CollectedNodes: &quot;heap-snapshot-proxy-did-collect-nodes&quot;
+};
</ins></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceProxiesHeapSnapshotWorkerProxyjs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotWorkerProxy.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotWorkerProxy.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Proxies/HeapSnapshotWorkerProxy.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -34,6 +34,8 @@
</span><span class="cx"> 
</span><span class="cx">         this._nextCallId = 1;
</span><span class="cx">         this._callbacks = new Map;
</span><ins>+
+        WebInspector.Frame.addEventListener(WebInspector.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Static
</span><span class="lines">@@ -47,6 +49,11 @@
</span><span class="cx"> 
</span><span class="cx">     // Actions
</span><span class="cx"> 
</span><ins>+    clearSnapshots(callback)
+    {
+        this.performAction(&quot;clearSnapshots&quot;, callback);
+    }
+
</ins><span class="cx">     createSnapshot(snapshotStringData, callback)
</span><span class="cx">     {
</span><span class="cx">         this.performAction(&quot;createSnapshot&quot;, ...arguments);
</span><span class="lines">@@ -88,6 +95,14 @@
</span><span class="cx"> 
</span><span class="cx">     // Private
</span><span class="cx"> 
</span><ins>+    _mainResourceDidChange(event)
+    {
+        if (!event.target.isMainFrame())
+            return;
+
+        this.clearSnapshots(function(){});
+    }
+
</ins><span class="cx">     _postMessage()
</span><span class="cx">     {
</span><span class="cx">         this._heapSnapshotWorker.postMessage(...arguments);
</span></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceViewsHeapAllocationsTimelineViewjs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapAllocationsTimelineView.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -89,6 +89,8 @@
</span><span class="cx">         this._pendingRecords = [];
</span><span class="cx"> 
</span><span class="cx">         timeline.addEventListener(WebInspector.Timeline.Event.RecordAdded, this._heapAllocationsTimelineRecordAdded, this);
</span><ins>+
+        WebInspector.HeapSnapshotWorkerProxy.singleton().addEventListener(&quot;HeapSnapshot.CollectionEvent&quot;, this._heapSnapshotCollectionEvent, this);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Public
</span><span class="lines">@@ -227,6 +229,8 @@
</span><span class="cx">         this._dataGrid.closed();
</span><span class="cx"> 
</span><span class="cx">         this._contentViewContainer.closeAllContentViews();
</span><ins>+
+        WebInspector.HeapSnapshotWorkerProxy.singleton().removeEventListener(&quot;HeapSnapshot.CollectionEvent&quot;, this._heapSnapshotCollectionEvent, this);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     layout()
</span><span class="lines">@@ -269,6 +273,22 @@
</span><span class="cx">         this.needsLayout();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    _heapSnapshotCollectionEvent(event)
+    {
+        function updateHeapSnapshotForEvent(heapSnapshot) {
+            heapSnapshot.updateForCollectionEvent(event);
+        }
+
+        for (let node of this._dataGrid.children)
+            updateHeapSnapshotForEvent(node.record.heapSnapshot);
+        for (let record of this._pendingRecords)
+            updateHeapSnapshotForEvent(record.heapSnapshot);
+        if (this._heapSnapshotDiff)
+            updateHeapSnapshotForEvent(this._heapSnapshotDiff);
+
+        // FIXME: &lt;https://webkit.org/b/157904&gt; Web Inspector: Snapshot List should show the total size and the total live size
+    }
+
</ins><span class="cx">     _snapshotListPathComponentClicked(event)
</span><span class="cx">     {
</span><span class="cx">         this.showHeapSnapshotList();
</span></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceViewsHeapSnapshotClassDataGridNodejs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotClassDataGridNode.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotClassDataGridNode.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotClassDataGridNode.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -92,6 +92,43 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    removeCollectedNodes(collectedNodes)
+    {
+        let nodesToRemove = [];
+
+        this.forEachImmediateChild((dataGridNode) =&gt; {
+            if (dataGridNode instanceof WebInspector.HeapSnapshotInstanceDataGridNode) {
+                let heapSnapshotNode = dataGridNode.node;
+                if (heapSnapshotNode.id in collectedNodes)
+                    nodesToRemove.push(dataGridNode);
+            }
+        });
+
+        if (nodesToRemove.length) {
+            for (let dataGridNode of nodesToRemove)
+                this.removeChild(dataGridNode);
+        }
+
+        if (this._instances) {
+            this._instances = this._instances.filter((instance) =&gt; !(instance.id in collectedNodes));
+            this._fetchBatch(nodesToRemove.length);
+        }
+    }
+
+    updateCount(count)
+    {
+        if (count === this._data.count)
+            return;
+
+        if (!count) {
+            this._tree.removeChild(this);
+            return;
+        }
+
+        this._data.count = count;
+        this.needsRefresh();
+    }
+
</ins><span class="cx">     // Private
</span><span class="cx"> 
</span><span class="cx">     _populate()
</span><span class="lines">@@ -99,7 +136,8 @@
</span><span class="cx">         this.removeEventListener(&quot;populate&quot;, this._populate, this);
</span><span class="cx"> 
</span><span class="cx">         this._tree.heapSnapshot.instancesWithClassName(this._data.className, (instances) =&gt; {
</span><del>-            this._instances = instances;
</del><ins>+            // FIXME: &lt;https://webkit.org/b/157905&gt; Web Inspector: Provide a way to toggle between showing only live objects and live+dead objects
+            this._instances = instances.filter((instance) =&gt; !instance.dead);
</ins><span class="cx">             this._sortInstances();
</span><span class="cx"> 
</span><span class="cx">             // Batch.
</span><span class="lines">@@ -128,9 +166,11 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         let count = newCount - oldCount;
</span><del>-        for (let i = 0; i &lt;= count; ++i) {
-            let instance = this._instances[oldCount + i];
-            this.appendChild(new WebInspector.HeapSnapshotInstanceDataGridNode(instance, this._tree));
</del><ins>+        if (count) {
+            for (let i = 0; i &lt;= count; ++i) {
+                let instance = this._instances[oldCount + i];
+                this.appendChild(new WebInspector.HeapSnapshotInstanceDataGridNode(instance, this._tree));
+            }
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (this._batched)
</span></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceViewsHeapSnapshotContentViewjs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotContentView.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotContentView.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotContentView.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -86,6 +86,7 @@
</span><span class="cx"> 
</span><span class="cx">     _heapSnapshotDataGridTreeDidPopulate()
</span><span class="cx">     {
</span><ins>+        this._dataGrid.removeChildren();
</ins><span class="cx">         for (let child of this._heapSnapshotDataGridTree.children)
</span><span class="cx">             this._dataGrid.appendChild(child);
</span><span class="cx">     }
</span></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceViewsHeapSnapshotDataGridTreejs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotDataGridTree.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotDataGridTree.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Views/HeapSnapshotDataGridTree.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx">         console.assert(heapSnapshot instanceof WebInspector.HeapSnapshotProxy || heapSnapshot instanceof WebInspector.HeapSnapshotDiffProxy);
</span><span class="cx"> 
</span><span class="cx">         this._heapSnapshot = heapSnapshot;
</span><ins>+        this._heapSnapshot.addEventListener(WebInspector.HeapSnapshotProxy.Event.CollectedNodes, this._heapSnapshotCollectedNodes, this);
</ins><span class="cx"> 
</span><span class="cx">         this._children = [];
</span><span class="cx">         this._sortComparator = sortComparator;
</span><span class="lines">@@ -106,6 +107,11 @@
</span><span class="cx">         this._children.splice(index, 0, node);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    removeChild(node)
+    {
+        this._children.remove(node, true);
+    }
+
</ins><span class="cx">     removeChildren()
</span><span class="cx">     {
</span><span class="cx">         this._children = [];
</span><span class="lines">@@ -160,12 +166,24 @@
</span><span class="cx">         // Implemented by subclasses.
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    removeCollectedNodes(collectedNodes)
+    {
+        // Implemented by subclasses.
+    }
+
</ins><span class="cx">     didPopulate()
</span><span class="cx">     {
</span><span class="cx">         this.sort();
</span><span class="cx"> 
</span><span class="cx">         this.dispatchEventToListeners(WebInspector.HeapSnapshotDataGridTree.Event.DidPopulate);
</span><span class="cx">     }
</span><ins>+
+    // Private
+
+    _heapSnapshotCollectedNodes(event)
+    {
+        this.removeCollectedNodes(event.data.collectedNodes);
+    }
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> WebInspector.HeapSnapshotDataGridTree.Event = {
</span><span class="lines">@@ -182,14 +200,33 @@
</span><span class="cx">     populateTopLevel()
</span><span class="cx">     {
</span><span class="cx">         // Populate the first level with the different non-internal classes.
</span><del>-        for (let [className, {size, retainedSize, count, internalCount}] of this.heapSnapshot.categories) {
</del><ins>+        for (let [className, {size, retainedSize, count, internalCount, deadCount}] of this.heapSnapshot.categories) {
</ins><span class="cx">             if (count === internalCount)
</span><span class="cx">                 continue;
</span><del>-            this.appendChild(new WebInspector.HeapSnapshotClassDataGridNode({className, size, retainedSize, count}, this));
</del><ins>+
+            // FIXME: &lt;https://webkit.org/b/157905&gt; Web Inspector: Provide a way to toggle between showing only live objects and live+dead objects
+            let liveCount = count - deadCount;
+            if (!liveCount)
+                continue;
+
+            this.appendChild(new WebInspector.HeapSnapshotClassDataGridNode({className, size, retainedSize, count: liveCount}, this));
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         this.didPopulate()
</span><span class="cx">     }
</span><ins>+
+    removeCollectedNodes(collectedNodes)
+    {
+        for (let classDataGridNode of this.children) {
+            let {count, deadCount} = this.heapSnapshot.categories.get(classDataGridNode.data.className);
+            let liveCount = count - deadCount;
+            classDataGridNode.updateCount(liveCount);
+            if (liveCount)
+                classDataGridNode.removeCollectedNodes(collectedNodes);
+        }
+
+        this.didPopulate();
+    }
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> WebInspector.HeapSnapshotObjectGraphDataGridTree = class HeapSnapshotInstancesDataGridTree extends WebInspector.HeapSnapshotDataGridTree
</span></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceWorkersHeapSnapshotHeapSnapshotjs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Workers/HeapSnapshot/HeapSnapshot.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Workers/HeapSnapshot/HeapSnapshot.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Workers/HeapSnapshot/HeapSnapshot.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -52,7 +52,7 @@
</span><span class="cx"> 
</span><span class="cx"> // Terminology:
</span><span class="cx"> //   - `nodeIndex` is an index into the `nodes` list.
</span><del>-//   - `nodeOrdinal` is the order of the node in the `nodes` list. (nodeIndex / nodeFieldCount)
</del><ins>+//   - `nodeOrdinal` is the order of the node in the `nodes` list. (nodeIndex / nodeFieldCount).
</ins><span class="cx"> //   - `nodeIdentifier` is the node's id value. (nodes[nodeIndex + nodeIdOffset]).
</span><span class="cx"> //   - `edgeIndex` is an index into the `edges` list.
</span><span class="cx"> //
</span><span class="lines">@@ -61,8 +61,9 @@
</span><span class="cx"> //     Iterate edges by walking `edges` (edgeFieldCount) and checking if fromIdentifier is current.
</span><span class="cx"> //   - _nodeOrdinalToFirstIncomingEdge - `nodeOrdinal` to `incomingEdgeIndex` in `incomingEdges`.
</span><span class="cx"> //     Iterate edges by walking `incomingEdges` until `nodeOrdinal+1`'s first incoming edge index.
</span><del>-//   - _nodeOrdinalToDominatorNodeOrdinal - `nodeOrdinal` to `nodeOrdinal` of dominator
-//   - _nodeOrdinalToRetainedSizes - `nodeOrdinal` to retain size value
</del><ins>+//   - _nodeOrdinalToDominatorNodeOrdinal - `nodeOrdinal` to `nodeOrdinal` of dominator.
+//   - _nodeOrdinalToRetainedSizes - `nodeOrdinal` to retain size value.
+//   - _nodeOrdinalIsDead - `nodeOrdinal` is dead or alive.
</ins><span class="cx"> //
</span><span class="cx"> // Temporary Lists:
</span><span class="cx"> //   - nodeOrdinalToPostOrderIndex - `nodeOrdinal` to a `postOrderIndex`.
</span><span class="lines">@@ -96,10 +97,14 @@
</span><span class="cx"> 
</span><span class="cx">         this._totalSize = 0;
</span><span class="cx">         this._nodeIdentifierToOrdinal = new Map; // &lt;node identifier&gt; =&gt; nodeOrdinal
</span><ins>+        this._lastNodeIdentifier = 0;
</ins><span class="cx">         for (let nodeIndex = 0; nodeIndex &lt; nodes.length; nodeIndex += nodeFieldCount) {
</span><span class="cx">             let nodeOrdinal = nodeIndex / nodeFieldCount;
</span><del>-            this._nodeIdentifierToOrdinal.set(nodes[nodeIndex + nodeIdOffset], nodeOrdinal);
</del><ins>+            let nodeIdentifier = nodes[nodeIndex + nodeIdOffset];
+            this._nodeIdentifierToOrdinal.set(nodeIdentifier, nodeOrdinal);
</ins><span class="cx">             this._totalSize += nodes[nodeIndex + nodeSizeOffset];
</span><ins>+            if (nodeIdentifier &gt; this._lastNodeIdentifier)
+                this._lastNodeIdentifier = nodeIdentifier;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // FIXME: Replace toIdentifier and fromIdentifier in edges with nodeIndex to reduce hash lookups?
</span><span class="lines">@@ -125,6 +130,8 @@
</span><span class="cx"> 
</span><span class="cx">         postOrderIndexToNodeOrdinal = null;
</span><span class="cx"> 
</span><ins>+        this._nodeOrdinalIsDead = new Uint8Array(this._nodeCount);
+
</ins><span class="cx">         this._categories = HeapSnapshot.buildCategories(this);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -137,6 +144,7 @@
</span><span class="cx">         let nodes = snapshot._nodes;
</span><span class="cx">         let nodeClassNamesTable = snapshot._nodeClassNamesTable;
</span><span class="cx">         let nodeOrdinalToRetainedSizes = snapshot._nodeOrdinalToRetainedSizes;
</span><ins>+        let nodeOrdinalIsDead = snapshot._nodeOrdinalIsDead;
</ins><span class="cx"> 
</span><span class="cx">         // Skip the &lt;root&gt; node.
</span><span class="cx">         let firstNodeIndex = nodeFieldCount;
</span><span class="lines">@@ -150,16 +158,19 @@
</span><span class="cx">             let size = nodes[nodeIndex + nodeSizeOffset];
</span><span class="cx">             let retainedSize = nodeOrdinalToRetainedSizes[nodeOrdinal];
</span><span class="cx">             let internal = nodes[nodeIndex + nodeInternalOffset] ? true : false;
</span><ins>+            let dead = nodeOrdinalIsDead[nodeOrdinal] ? true : false;
</ins><span class="cx"> 
</span><span class="cx">             let category = categories[className];
</span><span class="cx">             if (!category)
</span><del>-                category = categories[className] = {className, size: 0, retainedSize: 0, count: 0, internalCount: 0};
</del><ins>+                category = categories[className] = {className, size: 0, retainedSize: 0, count: 0, internalCount: 0, deadCount: 0};
</ins><span class="cx"> 
</span><span class="cx">             category.size += size;
</span><span class="cx">             category.retainedSize += retainedSize;
</span><span class="cx">             category.count += 1;
</span><span class="cx">             if (internal)
</span><span class="cx">                 category.internalCount += 1;
</span><ins>+            if (dead)
+                category.deadCount += 1;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return categories;
</span><span class="lines">@@ -228,6 +239,11 @@
</span><span class="cx">         return HeapSnapshot.instancesWithClassName(this, className);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    updateCategories()
+    {
+        return HeapSnapshot.buildCategories(this);
+    }
+
</ins><span class="cx">     nodeWithIdentifier(nodeIdentifier)
</span><span class="cx">     {
</span><span class="cx">         let nodeOrdinal = this._nodeIdentifierToOrdinal.get(nodeIdentifier);
</span><span class="lines">@@ -323,10 +339,60 @@
</span><span class="cx">         };
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    updateDeadNodesAndGatherCollectionData(snapshots)
+    {
+        let previousSnapshotIndex = snapshots.indexOf(this) - 1;
+        let previousSnapshot = snapshots[previousSnapshotIndex];
+        console.assert(previousSnapshot instanceof HeapSnapshot);
+        if (!previousSnapshot)
+            return;
+
+        let lastNodeIdentifier = previousSnapshot._lastNodeIdentifier;
+
+        // All of the node identifiers that could have existed prior to this snapshot.
+        let known = new Map;
+        for (let nodeIndex = 0; nodeIndex &lt; this._nodes.length; nodeIndex += nodeFieldCount) {
+            let nodeIdentifier = this._nodes[nodeIndex + nodeIdOffset];
+            if (nodeIdentifier &gt; lastNodeIdentifier)
+                continue;
+            known.set(nodeIdentifier, nodeIndex);
+        }
+
+        // Determine which node identifiers have since been deleted.
+        let collectedNodesList = [];
+        for (let nodeIndex = 0; nodeIndex &lt; previousSnapshot._nodes.length; nodeIndex += nodeFieldCount) {
+            let nodeIdentifier = previousSnapshot._nodes[nodeIndex + nodeIdOffset];
+            let wasDeleted = !known.has(nodeIdentifier);
+            if (wasDeleted)
+                collectedNodesList.push(nodeIdentifier);
+        }
+
+        // Update dead nodes in previous snapshots.
+        let affectedSnapshots = [];
+        for (let snapshot of snapshots) {
+            if (snapshot === this)
+                break;
+            if (snapshot._markDeadNodes(collectedNodesList))
+                affectedSnapshots.push(snapshot._identifier);
+        }
+
+        // Convert list to a map.
+        let collectedNodes = {};
+        for (let i = 0; i &lt; collectedNodesList.length; ++i)
+            collectedNodes[collectedNodesList[i]] = true;
+
+        return {
+            collectedNodes,
+            affectedSnapshots,
+        };
+    }
+
</ins><span class="cx">     // Public
</span><span class="cx"> 
</span><span class="cx">     serialize()
</span><span class="cx">     {
</span><ins>+        // FIXME: &lt;https://webkit.org/b/157904&gt; Web Inspector: Snapshot List should show the total size and the total live size
+
</ins><span class="cx">         return {
</span><span class="cx">             identifier: this._identifier,
</span><span class="cx">             title: this._title,
</span><span class="lines">@@ -356,6 +422,7 @@
</span><span class="cx">             retainedSize: this._nodeOrdinalToRetainedSizes[nodeOrdinal],
</span><span class="cx">             internal: this._nodes[nodeIndex + nodeInternalOffset] ? true : false,
</span><span class="cx">             gcRoot: this._nodeOrdinalIsGCRoot[nodeOrdinal] ? true : false,
</span><ins>+            dead: this._nodeOrdinalIsDead[nodeOrdinal] ? true : false,
</ins><span class="cx">             dominatorNodeIdentifier,
</span><span class="cx">             hasChildren,
</span><span class="cx">         };
</span><span class="lines">@@ -619,6 +686,22 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    _markDeadNodes(collectedNodesList)
+    {
+        let affected = false;
+
+        for (let i = 0; i &lt; collectedNodesList.length; ++i) {
+            let nodeIdentifier = collectedNodesList[i];
+            if (nodeIdentifier &gt; this._lastNodeIdentifier)
+                continue;
+            let nodeOrdinal = this._nodeIdentifierToOrdinal.get(nodeIdentifier);
+            this._nodeOrdinalIsDead[nodeOrdinal] = 1;
+            affected = true;
+        }
+
+        return affected;
+    }
+
</ins><span class="cx">     _isNodeGlobalObject(nodeIndex)
</span><span class="cx">     {
</span><span class="cx">         let className = this._nodeClassNamesTable[this._nodes[nodeIndex + nodeClassNameOffset]];
</span><span class="lines">@@ -725,6 +808,11 @@
</span><span class="cx">         return HeapSnapshot.instancesWithClassName(this._snapshot2, className, (nodeIdentifier) =&gt; this._addedNodeIdentifiers.has(nodeIdentifier));
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    updateCategories()
+    {
+        return HeapSnapshot.buildCategories(this._snapshot2, (nodeIdentifier) =&gt; this._addedNodeIdentifiers.has(nodeIdentifier));
+    }
+
</ins><span class="cx">     nodeWithIdentifier(nodeIdentifier) { return this._snapshot2.nodeWithIdentifier(nodeIdentifier); }
</span><span class="cx">     shortestGCRootPath(nodeIdentifier) { return this._snapshot2.shortestGCRootPath(nodeIdentifier); }
</span><span class="cx">     dominatedNodes(nodeIdentifier) { return this._snapshot2.dominatedNodes(nodeIdentifier); }
</span></span></pre></div>
<a id="branchessafari602132branchSourceWebInspectorUIUserInterfaceWorkersHeapSnapshotHeapSnapshotWorkerjs"></a>
<div class="modfile"><h4>Modified: branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Workers/HeapSnapshot/HeapSnapshotWorker.js (201195 => 201196)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Workers/HeapSnapshot/HeapSnapshotWorker.js        2016-05-19 22:58:13 UTC (rev 201195)
+++ branches/safari-602.1.32-branch/Source/WebInspectorUI/UserInterface/Workers/HeapSnapshot/HeapSnapshotWorker.js        2016-05-19 22:58:32 UTC (rev 201196)
</span><span class="lines">@@ -33,17 +33,37 @@
</span><span class="cx">     {
</span><span class="cx">         this._nextObjectId = 1;
</span><span class="cx">         this._objects = new Map;
</span><ins>+        this._snapshots = [];
</ins><span class="cx"> 
</span><span class="cx">         self.addEventListener(&quot;message&quot;, this._handleMessage.bind(this));
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Actions
</span><span class="cx"> 
</span><ins>+    clearSnapshots()
+    {
+        // FIXME: &lt;https://webkit.org/b/157907&gt; Web Inspector: Snapshots should be cleared at some point
+        // this._objects.clear();
+
+        this._snapshots = [];
+    }
+
</ins><span class="cx">     createSnapshot(snapshotString, title)
</span><span class="cx">     {
</span><span class="cx">         let objectId = this._nextObjectId++;
</span><span class="cx">         let snapshot = new HeapSnapshot(objectId, snapshotString, title);
</span><ins>+        this._snapshots.push(snapshot);
</ins><span class="cx">         this._objects.set(objectId, snapshot);
</span><ins>+
+        if (this._snapshots.length &gt; 1) {
+            setTimeout(() =&gt; {
+                let collectionData = snapshot.updateDeadNodesAndGatherCollectionData(this._snapshots);
+                if (!collectionData.affectedSnapshots.length)
+                    return;
+                this.sendEvent(&quot;HeapSnapshot.CollectionEvent&quot;, collectionData);
+            }, 0);
+        }
+
</ins><span class="cx">         return {objectId, snapshot: snapshot.serialize()};
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>