<!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>[197822] trunk</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/197822">197822</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2016-03-08 17:38:41 -0800 (Tue, 08 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: Add a way to create a Heap Snapshot
https://bugs.webkit.org/show_bug.cgi?id=155188

Patch by Joseph Pecoraro &lt;pecoraro@apple.com&gt; on 2016-03-08
Reviewed by Brian Burg.

Source/JavaScriptCore:

* inspector/agents/InspectorHeapAgent.h:
* inspector/protocol/Heap.json:
* inspector/agents/InspectorHeapAgent.cpp:
(Inspector::InspectorHeapAgent::snapshot):
Take a heap snapshot and return the JSON string result.

* inspector/protocol/Debugger.json:
Remove unused optional inferredName. Our displayName would be inferred.

Source/WebInspectorUI:

* UserInterface/Main.html:
* UserInterface/Test.html:
Add new Model resources.

* UserInterface/Models/HeapSnapshot.js: Added.
(WebInspector.HeapSnapshotClassCategory):
(WebInspector.HeapSnapshot):
(WebInspector.HeapSnapshot.fromPayload):
(WebInspector.HeapSnapshot.prototype.get rootNode):
(WebInspector.HeapSnapshot.prototype.get nodes):
(WebInspector.HeapSnapshot.prototype.get identifier):
(WebInspector.HeapSnapshot.prototype.get instances):
(WebInspector.HeapSnapshot.prototype.get categories):
(WebInspector.HeapSnapshot.prototype.get totalSize):
(WebInspector.HeapSnapshot.prototype.get totalObjectCount):
(WebInspector.HeapSnapshot.prototype.instancesWithClassName):
(WebInspector.HeapSnapshot.prototype.nodeWithObjectIdentifier):
* UserInterface/Models/HeapSnapshotEdge.js: Added.
(WebInspector.HeapSnapshotEdge):
(WebInspector.HeapSnapshotEdge.prototype.stringify):
* UserInterface/Models/HeapSnapshotNode.js: Added.
(WebInspector.HeapSnapshotNode):
Data structures for a HeapSnapshot.

LayoutTests:

* inspector/heap/snapshot-expected.txt: Added.
* inspector/heap/snapshot.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectoragentsInspectorHeapAgentcpp">trunk/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectoragentsInspectorHeapAgenth">trunk/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorprotocolDebuggerjson">trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorprotocolHeapjson">trunk/Source/JavaScriptCore/inspector/protocol/Heap.json</a></li>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceBaseUtilitiesjs">trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceMainhtml">trunk/Source/WebInspectorUI/UserInterface/Main.html</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceTesthtml">trunk/Source/WebInspectorUI/UserInterface/Test.html</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsinspectorheapsnapshotexpectedtxt">trunk/LayoutTests/inspector/heap/snapshot-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectorheapsnapshothtml">trunk/LayoutTests/inspector/heap/snapshot.html</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsHeapSnapshotjs">trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshot.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsHeapSnapshotEdgejs">trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshotEdge.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsHeapSnapshotNodejs">trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshotNode.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (197821 => 197822)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-03-09 01:05:53 UTC (rev 197821)
+++ trunk/LayoutTests/ChangeLog        2016-03-09 01:38:41 UTC (rev 197822)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2016-03-08  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+        Web Inspector: Add a way to create a Heap Snapshot
+        https://bugs.webkit.org/show_bug.cgi?id=155188
+
+        Reviewed by Brian Burg.
+
+        * inspector/heap/snapshot-expected.txt: Added.
+        * inspector/heap/snapshot.html: Added.
+
</ins><span class="cx"> 2016-03-08  Ryan Haddad  &lt;ryanhaddad@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Move two indexeddb test skips out of wk2/TestExpectations and in to TestExpectations.
</span></span></pre></div>
<a id="trunkLayoutTestsinspectorheapsnapshotexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/heap/snapshot-expected.txt (0 => 197822)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/heap/snapshot-expected.txt                                (rev 0)
+++ trunk/LayoutTests/inspector/heap/snapshot-expected.txt        2016-03-09 01:38:41 UTC (rev 197822)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+Test for the Heap.snapshot command.
+
+
+== Running test suite: Heap.snapshot
+-- Running test case: TriggerSnapshot
+PASS: Should not have an error creating a snapshot.
+PASS: Snapshot size should be greater than 1kb.
+PASS: Snapshot object count should be greater than 100.
+PASS: Snapshot should include a class category for 'Window'.
+PASS: Snapshow should include at least one 'Window' instance.
+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectorheapsnapshothtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/heap/snapshot.html (0 => 197822)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/heap/snapshot.html                                (rev 0)
+++ trunk/LayoutTests/inspector/heap/snapshot.html        2016-03-09 01:38:41 UTC (rev 197822)
</span><span class="lines">@@ -0,0 +1,34 @@
</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 test()
+{
+    let suite = InspectorTest.createAsyncSuite(&quot;Heap.snapshot&quot;);
+
+    suite.addTestCase({
+        name: &quot;TriggerSnapshot&quot;,
+        description: &quot;Calling Heap.snapshot should create a heap snapshot.&quot;,
+        test: (resolve, reject) =&gt; {
+            HeapAgent.snapshot((error, timestamp, snapshotStringData) =&gt; {
+                InspectorTest.expectThat(!error, &quot;Should not have an error creating a snapshot.&quot;);
+                let payload = JSON.parse(snapshotStringData);
+                let snapshot = WebInspector.HeapSnapshot.fromPayload(payload);
+                InspectorTest.expectThat(snapshot.totalSize &gt; 1024, &quot;Snapshot size should be greater than 1kb.&quot;);
+                InspectorTest.expectThat(snapshot.totalObjectCount &gt; 100, &quot;Snapshot object count should be greater than 100.&quot;);
+                InspectorTest.expectThat(snapshot.categories.get(&quot;Window&quot;), &quot;Snapshot should include a class category for 'Window'.&quot;);
+                InspectorTest.expectThat(snapshot.instancesWithClassName(&quot;Window&quot;).length &gt; 0, &quot;Snapshow should include at least one 'Window' instance.&quot;);
+                resolve();
+            });
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runTest()&quot;&gt;
+&lt;p&gt;Test for the Heap.snapshot command.&lt;/p&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (197821 => 197822)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-03-09 01:05:53 UTC (rev 197821)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-03-09 01:38:41 UTC (rev 197822)
</span><span class="lines">@@ -1,3 +1,19 @@
</span><ins>+2016-03-08  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+        Web Inspector: Add a way to create a Heap Snapshot
+        https://bugs.webkit.org/show_bug.cgi?id=155188
+
+        Reviewed by Brian Burg.
+
+        * inspector/agents/InspectorHeapAgent.h:
+        * inspector/protocol/Heap.json:
+        * inspector/agents/InspectorHeapAgent.cpp:
+        (Inspector::InspectorHeapAgent::snapshot):
+        Take a heap snapshot and return the JSON string result.
+
+        * inspector/protocol/Debugger.json:
+        Remove unused optional inferredName. Our displayName would be inferred.
+
</ins><span class="cx"> 2016-03-08  Oliver Hunt  &lt;oliver@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Fix ios bot build.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectoragentsInspectorHeapAgentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.cpp (197821 => 197822)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.cpp        2016-03-09 01:05:53 UTC (rev 197821)
+++ trunk/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.cpp        2016-03-09 01:38:41 UTC (rev 197822)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -26,7 +26,9 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;InspectorHeapAgent.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;HeapProfiler.h&quot;
</ins><span class="cx"> #include &quot;InspectorEnvironment.h&quot;
</span><ins>+#include &quot;JSCInlines.h&quot;
</ins><span class="cx"> #include &quot;VM.h&quot;
</span><span class="cx"> #include &lt;wtf/RunLoop.h&gt;
</span><span class="cx"> #include &lt;wtf/Stopwatch.h&gt;
</span><span class="lines">@@ -75,6 +77,8 @@
</span><span class="cx">     m_enabled = false;
</span><span class="cx"> 
</span><span class="cx">     m_environment.vm().heap.removeObserver(this);
</span><ins>+
+    clearHeapSnapshots();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void InspectorHeapAgent::gc(ErrorString&amp;)
</span><span class="lines">@@ -85,6 +89,26 @@
</span><span class="cx">     vm.heap.collectAllGarbage();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void InspectorHeapAgent::snapshot(ErrorString&amp;, double* timestamp, String* snapshotData)
+{
+    VM&amp; vm = m_environment.vm();
+    JSLockHolder lock(vm);
+
+    HeapSnapshotBuilder snapshotBuilder(vm.ensureHeapProfiler());
+    snapshotBuilder.buildSnapshot();
+
+    *timestamp = m_environment.executionStopwatch()-&gt;elapsedTime();
+    *snapshotData = snapshotBuilder.json([&amp;] (const HeapSnapshotNode&amp; node) {
+        if (Structure* structure = node.cell-&gt;structure(vm)) {
+            if (JSGlobalObject* globalObject = structure-&gt;globalObject()) {
+                if (!m_environment.canAccessInspectedScriptState(globalObject-&gt;globalExec()))
+                    return false;
+            }
+        }
+        return true;
+    });
+}
+
</ins><span class="cx"> static Inspector::Protocol::Heap::GarbageCollection::Type protocolTypeForHeapOperation(HeapOperation operation)
</span><span class="cx"> {
</span><span class="cx">     switch (operation) {
</span><span class="lines">@@ -136,4 +160,10 @@
</span><span class="cx">     m_gcStartTime = NAN;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void InspectorHeapAgent::clearHeapSnapshots()
+{
+    if (HeapProfiler* heapProfiler = m_environment.vm().heapProfiler())
+        heapProfiler-&gt;clearSnapshots();
+}
+
</ins><span class="cx"> } // namespace Inspector
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectoragentsInspectorHeapAgenth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.h (197821 => 197822)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.h        2016-03-09 01:05:53 UTC (rev 197821)
+++ trunk/Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.h        2016-03-09 01:38:41 UTC (rev 197822)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #ifndef InspectorHeapAgent_h
</span><span class="cx"> #define InspectorHeapAgent_h
</span><span class="cx"> 
</span><ins>+#include &quot;HeapSnapshot.h&quot;
</ins><span class="cx"> #include &quot;InspectorBackendDispatchers.h&quot;
</span><span class="cx"> #include &quot;InspectorFrontendDispatchers.h&quot;
</span><span class="cx"> #include &quot;heap/HeapObserver.h&quot;
</span><span class="lines">@@ -50,15 +51,19 @@
</span><span class="cx">     void enable(ErrorString&amp;) override;
</span><span class="cx">     void disable(ErrorString&amp;) override;
</span><span class="cx">     void gc(ErrorString&amp;) override;
</span><ins>+    void snapshot(ErrorString&amp;, double* timestamp, String* snapshotData) override;
</ins><span class="cx"> 
</span><span class="cx">     // HeapObserver
</span><span class="cx">     void willGarbageCollect() override;
</span><span class="cx">     void didGarbageCollect(JSC::HeapOperation) override;
</span><span class="cx"> 
</span><span class="cx"> private:
</span><ins>+    void clearHeapSnapshots();
+
</ins><span class="cx">     std::unique_ptr&lt;HeapFrontendDispatcher&gt; m_frontendDispatcher;
</span><span class="cx">     RefPtr&lt;HeapBackendDispatcher&gt; m_backendDispatcher;
</span><span class="cx">     InspectorEnvironment&amp; m_environment;
</span><ins>+
</ins><span class="cx">     bool m_enabled { false };
</span><span class="cx">     double m_gcStartTime { NAN };
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorprotocolDebuggerjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json (197821 => 197822)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json        2016-03-09 01:05:53 UTC (rev 197821)
+++ trunk/Source/JavaScriptCore/inspector/protocol/Debugger.json        2016-03-09 01:38:41 UTC (rev 197822)
</span><span class="lines">@@ -60,7 +60,6 @@
</span><span class="cx">                 { &quot;name&quot;: &quot;location&quot;, &quot;$ref&quot;: &quot;Location&quot;, &quot;description&quot;: &quot;Location of the function.&quot; },
</span><span class="cx">                 { &quot;name&quot;: &quot;name&quot;, &quot;type&quot;: &quot;string&quot;, &quot;optional&quot;: true, &quot;description&quot;: &quot;Name of the function. Not present for anonymous functions.&quot; },
</span><span class="cx">                 { &quot;name&quot;: &quot;displayName&quot;, &quot;type&quot;: &quot;string&quot;, &quot;optional&quot;: true, &quot;description&quot;: &quot;Display name of the function(specified in 'displayName' property on the function object).&quot; },
</span><del>-                { &quot;name&quot;: &quot;inferredName&quot;, &quot;type&quot;: &quot;string&quot;, &quot;optional&quot;: true, &quot;description&quot;: &quot;Name of the function inferred from its initial assignment.&quot; },
</del><span class="cx">                 { &quot;name&quot;: &quot;scopeChain&quot;, &quot;type&quot;: &quot;array&quot;, &quot;optional&quot;: true, &quot;items&quot;: { &quot;$ref&quot;: &quot;Scope&quot; }, &quot;description&quot;: &quot;Scope chain for this closure.&quot; }
</span><span class="cx">             ],
</span><span class="cx">             &quot;description&quot;: &quot;Information about the function.&quot;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorprotocolHeapjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/protocol/Heap.json (197821 => 197822)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/protocol/Heap.json        2016-03-09 01:05:53 UTC (rev 197821)
+++ trunk/Source/JavaScriptCore/inspector/protocol/Heap.json        2016-03-09 01:38:41 UTC (rev 197822)
</span><span class="lines">@@ -11,6 +11,11 @@
</span><span class="cx">                 { &quot;name&quot;: &quot;startTime&quot;, &quot;type&quot;: &quot;number&quot; },
</span><span class="cx">                 { &quot;name&quot;: &quot;endTime&quot;, &quot;type&quot;: &quot;number&quot; }
</span><span class="cx">             ]
</span><ins>+        },
+        {
+            &quot;id&quot;: &quot;HeapSnapshotData&quot;,
+            &quot;description&quot;: &quot;JavaScriptCore HeapSnapshot JSON data.&quot;,
+            &quot;type&quot;: &quot;string&quot;
</ins><span class="cx">         }
</span><span class="cx">     ],
</span><span class="cx">     &quot;commands&quot;: [
</span><span class="lines">@@ -25,6 +30,14 @@
</span><span class="cx">         {
</span><span class="cx">             &quot;name&quot;: &quot;gc&quot;,
</span><span class="cx">             &quot;description&quot;: &quot;Trigger a full garbage collection.&quot;
</span><ins>+        },
+        {
+            &quot;name&quot;: &quot;snapshot&quot;,
+            &quot;description&quot;: &quot;Take a heap snapshot.&quot;,
+            &quot;returns&quot;: [
+                { &quot;name&quot;: &quot;timestamp&quot;, &quot;type&quot;: &quot;number&quot; },
+                { &quot;name&quot;: &quot;snapshotData&quot;, &quot;$ref&quot;: &quot;HeapSnapshotData&quot; }
+            ]
</ins><span class="cx">         }
</span><span class="cx">     ],
</span><span class="cx">     &quot;events&quot;: [
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (197821 => 197822)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2016-03-09 01:05:53 UTC (rev 197821)
+++ trunk/Source/WebInspectorUI/ChangeLog        2016-03-09 01:38:41 UTC (rev 197822)
</span><span class="lines">@@ -1,5 +1,36 @@
</span><span class="cx"> 2016-03-08  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Web Inspector: Add a way to create a Heap Snapshot
+        https://bugs.webkit.org/show_bug.cgi?id=155188
+
+        Reviewed by Brian Burg.
+
+        * UserInterface/Main.html:
+        * UserInterface/Test.html:
+        Add new Model resources.
+
+        * UserInterface/Models/HeapSnapshot.js: Added.
+        (WebInspector.HeapSnapshotClassCategory):
+        (WebInspector.HeapSnapshot):
+        (WebInspector.HeapSnapshot.fromPayload):
+        (WebInspector.HeapSnapshot.prototype.get rootNode):
+        (WebInspector.HeapSnapshot.prototype.get nodes):
+        (WebInspector.HeapSnapshot.prototype.get identifier):
+        (WebInspector.HeapSnapshot.prototype.get instances):
+        (WebInspector.HeapSnapshot.prototype.get categories):
+        (WebInspector.HeapSnapshot.prototype.get totalSize):
+        (WebInspector.HeapSnapshot.prototype.get totalObjectCount):
+        (WebInspector.HeapSnapshot.prototype.instancesWithClassName):
+        (WebInspector.HeapSnapshot.prototype.nodeWithObjectIdentifier):
+        * UserInterface/Models/HeapSnapshotEdge.js: Added.
+        (WebInspector.HeapSnapshotEdge):
+        (WebInspector.HeapSnapshotEdge.prototype.stringify):
+        * UserInterface/Models/HeapSnapshotNode.js: Added.
+        (WebInspector.HeapSnapshotNode):
+        Data structures for a HeapSnapshot.
+
+2016-03-08  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
</ins><span class="cx">         Web Inspector: Miscellaneous inspector fixes for typos / stale code
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=155193
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceBaseUtilitiesjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js (197821 => 197822)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js        2016-03-09 01:05:53 UTC (rev 197821)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js        2016-03-09 01:38:41 UTC (rev 197822)
</span><span class="lines">@@ -94,6 +94,17 @@
</span><span class="cx">     }
</span><span class="cx"> });
</span><span class="cx"> 
</span><ins>+Object.defineProperty(Map, &quot;fromObject&quot;,
+{
+    value: function(object)
+    {
+        let map = new Map;
+        for (let key in object)
+            map.set(key, object[key]);
+        return map;
+    }
+});
+
</ins><span class="cx"> Object.defineProperty(Map.prototype, &quot;take&quot;,
</span><span class="cx"> {
</span><span class="cx">     value: function(key)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceMainhtml"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (197821 => 197822)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Main.html        2016-03-09 01:05:53 UTC (rev 197821)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html        2016-03-09 01:38:41 UTC (rev 197822)
</span><span class="lines">@@ -308,6 +308,9 @@
</span><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><ins>+    &lt;script src=&quot;Models/HeapSnapshot.js&quot;&gt;&lt;/script&gt;
+    &lt;script src=&quot;Models/HeapSnapshotEdge.js&quot;&gt;&lt;/script&gt;
+    &lt;script src=&quot;Models/HeapSnapshotNode.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="trunkSourceWebInspectorUIUserInterfaceModelsHeapSnapshotjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshot.js (0 => 197822)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshot.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshot.js        2016-03-09 01:38:41 UTC (rev 197822)
</span><span class="lines">@@ -0,0 +1,155 @@
</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.HeapSnapshotClassCategory = class HeapSnapshotClassCategory
+{
+    constructor(className)
+    {
+        this.className = className;
+        this.size = 0;
+        this.count = 0;
+        this.internalCount = 0;
+    }
+};
+
+WebInspector.HeapSnapshot = class HeapSnapshot extends WebInspector.Object
+{
+    constructor(rootNode, nodes, nodeMap)
+    {
+        super();
+
+        console.assert(!rootNode || rootNode instanceof WebInspector.HeapSnapshotNode);
+        console.assert(nodes instanceof Array);
+
+        this._rootNode = rootNode;
+        this._nodes = nodes;
+        this._nodeMap = nodeMap;
+
+        this._identifier = WebInspector.HeapSnapshot._nextAvailableSnapshotIdentifier++;
+        this._instances = nodes;
+
+        let categories = {};
+        for (let i = 0; i &lt; nodes.length; ++i) {
+            let {className, size, internal} = nodes[i];
+
+            let category = categories[className];
+            if (!category)
+                category = categories[className] = new WebInspector.HeapSnapshotClassCategory(className);
+
+            category.size += size;
+            category.count++;
+            if (internal)
+                category.internalCount++;
+        }
+        this._categories = Map.fromObject(categories);
+
+        this._totalSize = 0;
+        this._totalObjectCount = 0;
+        for (let {count, size} of this._categories.values()) {
+            this._totalSize += size;
+            this._totalObjectCount += count;
+        }
+    }
+
+    // Static
+
+    static fromPayload(payload)
+    {
+        let {version, nodes, nodeClassNames, edges, edgeTypes} = payload;
+        console.assert(version === 1, &quot;Only know how to handle JavaScriptCore Heap Snapshot Format Version 1&quot;);
+        console.assert(edgeTypes.every((type) =&gt; type in WebInspector.HeapSnapshotEdge.EdgeType), &quot;Unexpected edge type&quot;, edgeTypes);
+
+        let nodeMap = new Map;
+
+        // Turn nodes into real nodes.
+        for (let i = 0, length = nodes.length; i &lt; length; ++i) {
+            let nodePayload = nodes[i];
+            let id = nodePayload[0];
+            let size = nodePayload[1];
+            let classNameIndex = nodePayload[2];
+            let internal = nodePayload[3];
+
+            let node = new WebInspector.HeapSnapshotNode(id, nodeClassNames[classNameIndex], size, !!internal);
+            nodeMap.set(id, node);
+            nodes[i] = node;
+        }
+
+        // Turn edges into real edges and set them on the nodes.
+        for (let i = 0, length = edges.length; i &lt; length; ++i) {
+            let edgePayload = edges[i];
+            let fromIdentifier = edgePayload[0];
+            let toIdentifier = edgePayload[1];
+            let edgeTypeIndex = edgePayload[2];
+            let data = edgePayload[3];
+
+            let from = nodeMap.get(fromIdentifier);
+            let to = nodeMap.get(toIdentifier);
+            let edge = new WebInspector.HeapSnapshotEdge(from, to, edgeTypes[edgeTypeIndex], data);
+            from.outgoingEdges.push(edge);
+            to.incomingEdges.push(edge);
+        }
+
+        // Root node.
+        let rootNode = nodeMap.get(0);
+        console.assert(rootNode, &quot;Node with identifier 0 is the synthetic &lt;root&gt; node.&quot;);
+        console.assert(rootNode.outgoingEdges.length &gt; 0, &quot;This had better have children!&quot;);
+        console.assert(rootNode.incomingEdges.length === 0, &quot;This had better not have back references!&quot;);
+
+        // Mark GC roots.
+        let rootNodeEdges = rootNode.outgoingEdges;
+        for (let i = 0, length = rootNodeEdges.length; i &lt; length; ++i)
+            rootNodeEdges[i].to.gcRoot = true;
+
+        return new WebInspector.HeapSnapshot(rootNode, nodes, nodeMap);
+    }
+
+    // Public
+
+    get rootNode() { return this._rootNode; }
+    get nodes() { return this._nodes; }
+    get identifier() { return this._identifier; }
+    get instances() { return this._instances; }
+    get categories() { return this._categories; }
+    get totalSize() { return this._totalSize; }
+    get totalObjectCount() { return this._totalObjectCount; }
+
+    instancesWithClassName(className)
+    {
+        let results = [];
+        for (let i = 0; i &lt; this._instances.length; ++i) {
+            let cell = this._instances[i];
+            if (cell.className === className)
+                results.push(cell);
+        }
+        return results;
+    }
+
+    nodeWithObjectIdentifier(id)
+    {
+        return this._nodeMap.get(id);
+    }
+};
+
+WebInspector.HeapSnapshot._nextAvailableSnapshotIdentifier = 1;
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsHeapSnapshotEdgejs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshotEdge.js (0 => 197822)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshotEdge.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshotEdge.js        2016-03-09 01:38:41 UTC (rev 197822)
</span><span class="lines">@@ -0,0 +1,44 @@
</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.
+ */
+
+// Directed edge between two HeapSnapshotNodes 'from' and 'to'.
+
+WebInspector.HeapSnapshotEdge = class HeapSnapshotEdge
+{
+    constructor(from, to, type, data)
+    {
+        this.from = from;
+        this.to = to;
+        this.type = type;
+        this.data = data;
+    }
+};
+
+WebInspector.HeapSnapshotEdge.EdgeType = {
+    Internal: &quot;Internal&quot;,       // No data.
+    Property: &quot;Property&quot;,       // data is string property name.
+    Index: &quot;Index&quot;,             // data is numeric index.
+    Variable: &quot;Variable&quot;,       // data is string variable name.
+};
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsHeapSnapshotNodejs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshotNode.js (0 => 197822)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshotNode.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/HeapSnapshotNode.js        2016-03-09 01:38:41 UTC (rev 197822)
</span><span class="lines">@@ -0,0 +1,38 @@
</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.HeapSnapshotNode = class HeapSnapshotNode
+{
+    constructor(identifier, className, size, internal)
+    {
+        this.id = identifier;
+        this.className = className;
+        this.size = size; 
+        this.internal = internal;
+        this.gcRoot = false;
+        this.outgoingEdges = [];
+        this.incomingEdges = [];
+    }
+};
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceTesthtml"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Test.html (197821 => 197822)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Test.html        2016-03-09 01:05:53 UTC (rev 197821)
+++ trunk/Source/WebInspectorUI/UserInterface/Test.html        2016-03-09 01:38:41 UTC (rev 197822)
</span><span class="lines">@@ -112,6 +112,9 @@
</span><span class="cx">     &lt;script src=&quot;Models/Frame.js&quot;&gt;&lt;/script&gt;
</span><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><ins>+    &lt;script src=&quot;Models/HeapSnapshot.js&quot;&gt;&lt;/script&gt;
+    &lt;script src=&quot;Models/HeapSnapshotEdge.js&quot;&gt;&lt;/script&gt;
+    &lt;script src=&quot;Models/HeapSnapshotNode.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 class="lines">@@ -119,6 +122,9 @@
</span><span class="cx">     &lt;script src=&quot;Models/LayoutInstrument.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/LayoutTimelineRecord.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/LazySourceCodeLocation.js&quot;&gt;&lt;/script&gt;
</span><ins>+    &lt;script src=&quot;Models/MemoryCategory.js&quot;&gt;&lt;/script&gt;
+    &lt;script src=&quot;Models/MemoryInstrument.js&quot;&gt;&lt;/script&gt;
+    &lt;script src=&quot;Models/MemoryTimelineRecord.js&quot;&gt;&lt;/script&gt;
</ins><span class="cx">     &lt;script src=&quot;Models/NetworkInstrument.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/NetworkTimeline.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/ObjectPreview.js&quot;&gt;&lt;/script&gt;
</span></span></pre>
</div>
</div>

</body>
</html>