<!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>[179493] trunk/Source</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/179493">179493</a></dd>
<dt>Author</dt> <dd>joepeck@webkit.org</dd>
<dt>Date</dt> <dd>2015-02-02 13:07:39 -0800 (Mon, 02 Feb 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: Support console.table
https://bugs.webkit.org/show_bug.cgi?id=141058

Reviewed by Timothy Hatcher.

Source/JavaScriptCore:

* inspector/InjectedScriptSource.js:
Include the firstLevelKeys filter when generating previews.

* runtime/ConsoleClient.cpp:
(JSC::appendMessagePrefix):
Differentiate console.table logs to system log.

Source/WebCore:

* inspector/CommandLineAPIModuleSource.js:
Include &quot;table(foo)&quot; as an alias of &quot;console.table(foo)&quot; on
the command line.

Source/WebInspectorUI:

* Localizations/en.lproj/localizedStrings.js:
New &quot;Index&quot;, &quot;(Index)&quot;, &quot;Value&quot;, table header strings.

* UserInterface/Views/ConsoleMessage.js:
Add &quot;Table&quot;, but add FIXMEs to consider using the protocol generated enums.

* UserInterface/Views/ConsoleMessageImpl.js:
(WebInspector.ConsoleMessageImpl.prototype._format):
Special case console.table messages.

(WebInspector.ConsoleMessageImpl.prototype._appendPropertyPreviews):
(WebInspector.ConsoleMessageImpl.prototype._propertyPreviewElement):
Factor out ProjectPreview printing. Also, replace newlines in strings
with return characters, like we did elsewhere.

(WebInspector.ConsoleMessageImpl.prototype._formatParameterAsTable):
Ultimately try to create a DataGrid from the output. Search first
for rich object data in the list. If no rich object data is found
just check for simple values. If the table is lossy, also do
a log of the object in case the user wants to see more data.

* UserInterface/Views/DataGrid.js:
(WebInspector.DataGrid):
The for..in enumeration is unordered and may not give us the
column ordering we wanted. So include an optional preferred
column names list to get the preferred order.

(WebInspector.DataGrid.createSortableDataGrid):
Numerous bug fixes here. Accidental globals, typos, and sorting failures.

(WebInspector.DataGrid.prototype.autoSizeColumns):
(WebInspector.DataGrid.prototype.textForDataGridNodeColumn):
(WebInspector.DataGrid.prototype._copyTextForDataGridNode):
Create a generic method to get the text for a datagrid node in a column.
This is important for getting the text from console.table previews which
contains Nodes.

* UserInterface/Views/LogContentView.css:
(.console-messages:focus .console-item.selected .data-grid tr.selected):
(.console-item .data-grid tr.selected):
DataGrid selection colors while in the console which may or may
not have selected console items.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorInjectedScriptSourcejs">trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeConsoleClientcpp">trunk/Source/JavaScriptCore/runtime/ConsoleClient.cpp</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreinspectorCommandLineAPIModuleSourcejs">trunk/Source/WebCore/inspector/CommandLineAPIModuleSource.js</a></li>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs">trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsConsoleMessagejs">trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleMessage.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsConsoleMessageImpljs">trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleMessageImpl.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsDataGridjs">trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsLogContentViewcss">trunk/Source/WebInspectorUI/UserInterface/Views/LogContentView.css</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (179492 => 179493)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-02-02 21:04:08 UTC (rev 179492)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-02-02 21:07:39 UTC (rev 179493)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2015-02-02  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+        Web Inspector: Support console.table
+        https://bugs.webkit.org/show_bug.cgi?id=141058
+
+        Reviewed by Timothy Hatcher.
+
+        * inspector/InjectedScriptSource.js:
+        Include the firstLevelKeys filter when generating previews.
+
+        * runtime/ConsoleClient.cpp:
+        (JSC::appendMessagePrefix):
+        Differentiate console.table logs to system log.
+
</ins><span class="cx"> 2015-01-31  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         BinarySwitch should be faster on average
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorInjectedScriptSourcejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js (179492 => 179493)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js        2015-02-02 21:04:08 UTC (rev 179492)
+++ trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js        2015-02-02 21:07:39 UTC (rev 179493)
</span><span class="lines">@@ -101,14 +101,17 @@
</span><span class="cx">     {
</span><span class="cx">         if (!canAccessInspectedGlobalObject)
</span><span class="cx">             return this._fallbackWrapper(table);
</span><ins>+
</ins><span class="cx">         var columnNames = null;
</span><span class="cx">         if (typeof columns === &quot;string&quot;)
</span><span class="cx">             columns = [columns];
</span><ins>+
</ins><span class="cx">         if (InjectedScriptHost.subtype(columns) === &quot;array&quot;) {
</span><span class="cx">             columnNames = [];
</span><span class="cx">             for (var i = 0; i &lt; columns.length; ++i)
</span><del>-                columnNames.push(String(columns[i]));
</del><ins>+                columnNames.push(toString(columns[i]));
</ins><span class="cx">         }
</span><ins>+
</ins><span class="cx">         return this._wrapObject(table, &quot;console&quot;, false, true, columnNames);
</span><span class="cx">     },
</span><span class="cx"> 
</span><span class="lines">@@ -847,7 +850,7 @@
</span><span class="cx">             // Properties.
</span><span class="cx">             preview.properties = [];
</span><span class="cx">             var descriptors = injectedScript._propertyDescriptors(object);
</span><del>-            this._appendPropertyPreviews(preview, descriptors, propertiesThreshold, secondLevelKeys);
</del><ins>+            this._appendPropertyPreviews(preview, descriptors, propertiesThreshold, firstLevelKeys, secondLevelKeys);
</ins><span class="cx">             if (propertiesThreshold.indexes &lt; 0 || propertiesThreshold.properties &lt; 0)
</span><span class="cx">                 return preview;
</span><span class="cx"> 
</span><span class="lines">@@ -860,7 +863,7 @@
</span><span class="cx">         return preview;
</span><span class="cx">     },
</span><span class="cx"> 
</span><del>-    _appendPropertyPreviews: function(preview, descriptors, propertiesThreshold, secondLevelKeys)
</del><ins>+    _appendPropertyPreviews: function(preview, descriptors, propertiesThreshold, firstLevelKeys, secondLevelKeys)
</ins><span class="cx">     {
</span><span class="cx">         for (var descriptor of descriptors) {
</span><span class="cx">             // Seen enough.
</span><span class="lines">@@ -886,6 +889,10 @@
</span><span class="cx">             if (!descriptor.enumerable &amp;&amp; !descriptor.isOwn &amp;&amp; !(this.subtype === &quot;array&quot; &amp;&amp; isUInt32(name)))
</span><span class="cx">                 continue;
</span><span class="cx"> 
</span><ins>+            // If we have a filter, only show properties in the filter.
+            if (firstLevelKeys &amp;&amp; firstLevelKeys.indexOf(name) === -1)
+                continue;
+
</ins><span class="cx">             // Getter/setter.
</span><span class="cx">             if (!(&quot;value&quot; in descriptor)) {
</span><span class="cx">                 preview.lossless = false;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeConsoleClientcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ConsoleClient.cpp (179492 => 179493)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ConsoleClient.cpp        2015-02-02 21:04:08 UTC (rev 179492)
+++ trunk/Source/JavaScriptCore/runtime/ConsoleClient.cpp        2015-02-02 21:07:39 UTC (rev 179493)
</span><span class="lines">@@ -119,6 +119,8 @@
</span><span class="cx"> 
</span><span class="cx">     if (type == MessageType::Trace)
</span><span class="cx">         levelString = &quot;TRACE&quot;;
</span><ins>+    else if (type == MessageType::Table)
+        levelString = &quot;TABLE&quot;;
</ins><span class="cx"> 
</span><span class="cx">     builder.append(sourceString);
</span><span class="cx">     builder.append(' ');
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (179492 => 179493)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-02-02 21:04:08 UTC (rev 179492)
+++ trunk/Source/WebCore/ChangeLog        2015-02-02 21:07:39 UTC (rev 179493)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2015-02-02  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+        Web Inspector: Support console.table
+        https://bugs.webkit.org/show_bug.cgi?id=141058
+
+        Reviewed by Timothy Hatcher.
+
+        * inspector/CommandLineAPIModuleSource.js:
+        Include &quot;table(foo)&quot; as an alias of &quot;console.table(foo)&quot; on
+        the command line.
+
</ins><span class="cx"> 2015-02-02  Roger Fong  &lt;roger_fong@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Win] Build fix following r179482.
</span></span></pre></div>
<a id="trunkSourceWebCoreinspectorCommandLineAPIModuleSourcejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/inspector/CommandLineAPIModuleSource.js (179492 => 179493)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/inspector/CommandLineAPIModuleSource.js        2015-02-02 21:04:08 UTC (rev 179492)
+++ trunk/Source/WebCore/inspector/CommandLineAPIModuleSource.js        2015-02-02 21:07:39 UTC (rev 179493)
</span><span class="lines">@@ -132,7 +132,7 @@
</span><span class="cx">  * @const
</span><span class="cx">  */
</span><span class="cx"> CommandLineAPI.members_ = [
</span><del>-    &quot;$&quot;, &quot;$$&quot;, &quot;$x&quot;, &quot;dir&quot;, &quot;dirxml&quot;, &quot;keys&quot;, &quot;values&quot;, &quot;profile&quot;, &quot;profileEnd&quot;,
</del><ins>+    &quot;$&quot;, &quot;$$&quot;, &quot;$x&quot;, &quot;dir&quot;, &quot;dirxml&quot;, &quot;keys&quot;, &quot;values&quot;, &quot;profile&quot;, &quot;profileEnd&quot;, &quot;table&quot;,
</ins><span class="cx">     &quot;monitorEvents&quot;, &quot;unmonitorEvents&quot;, &quot;inspect&quot;, &quot;copy&quot;, &quot;clear&quot;, &quot;getEventListeners&quot;
</span><span class="cx"> ];
</span><span class="cx"> 
</span><span class="lines">@@ -243,6 +243,11 @@
</span><span class="cx">         return inspectedWindow.console.profileEnd.apply(inspectedWindow.console, arguments)
</span><span class="cx">     },
</span><span class="cx"> 
</span><ins>+    table: function()
+    {
+        return inspectedWindow.console.table.apply(inspectedWindow.console, arguments)
+    },
+
</ins><span class="cx">     /**
</span><span class="cx">      * @param {Object} object
</span><span class="cx">      * @param {Array.&lt;string&gt;|string=} types
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (179492 => 179493)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2015-02-02 21:04:08 UTC (rev 179492)
+++ trunk/Source/WebInspectorUI/ChangeLog        2015-02-02 21:07:39 UTC (rev 179493)
</span><span class="lines">@@ -1,5 +1,56 @@
</span><span class="cx"> 2015-02-02  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Web Inspector: Support console.table
+        https://bugs.webkit.org/show_bug.cgi?id=141058
+
+        Reviewed by Timothy Hatcher.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        New &quot;Index&quot;, &quot;(Index)&quot;, &quot;Value&quot;, table header strings.
+
+        * UserInterface/Views/ConsoleMessage.js:
+        Add &quot;Table&quot;, but add FIXMEs to consider using the protocol generated enums.
+
+        * UserInterface/Views/ConsoleMessageImpl.js:
+        (WebInspector.ConsoleMessageImpl.prototype._format):
+        Special case console.table messages.
+
+        (WebInspector.ConsoleMessageImpl.prototype._appendPropertyPreviews):
+        (WebInspector.ConsoleMessageImpl.prototype._propertyPreviewElement):
+        Factor out ProjectPreview printing. Also, replace newlines in strings
+        with return characters, like we did elsewhere.
+
+        (WebInspector.ConsoleMessageImpl.prototype._formatParameterAsTable):
+        Ultimately try to create a DataGrid from the output. Search first
+        for rich object data in the list. If no rich object data is found
+        just check for simple values. If the table is lossy, also do
+        a log of the object in case the user wants to see more data.
+
+
+        * UserInterface/Views/DataGrid.js:
+        (WebInspector.DataGrid):
+        The for..in enumeration is unordered and may not give us the
+        column ordering we wanted. So include an optional preferred
+        column names list to get the preferred order.
+
+        (WebInspector.DataGrid.createSortableDataGrid):
+        Numerous bug fixes here. Accidental globals, typos, and sorting failures.
+
+        (WebInspector.DataGrid.prototype.autoSizeColumns):
+        (WebInspector.DataGrid.prototype.textForDataGridNodeColumn):
+        (WebInspector.DataGrid.prototype._copyTextForDataGridNode):
+        Create a generic method to get the text for a datagrid node in a column.
+        This is important for getting the text from console.table previews which
+        contains Nodes.
+
+        * UserInterface/Views/LogContentView.css:
+        (.console-messages:focus .console-item.selected .data-grid tr.selected):
+        (.console-item .data-grid tr.selected):
+        DataGrid selection colors while in the console which may or may
+        not have selected console items.
+
+2015-02-02  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
</ins><span class="cx">         Web Inspector: Extend CSS.getSupportedCSSProperties to provide values for properties for CSS Augmented JSContext
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=141064
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (179492 => 179493)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js        2015-02-02 21:04:08 UTC (rev 179492)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js        2015-02-02 21:07:39 UTC (rev 179493)
</span><span class="lines">@@ -25,6 +25,7 @@
</span><span class="cx"> localizedStrings[&quot;%s (default)&quot;] = &quot;%s (default)&quot;;
</span><span class="cx"> localizedStrings[&quot;%s (hidden)&quot;] = &quot;%s (hidden)&quot;;
</span><span class="cx"> localizedStrings[&quot;%s Event Dispatched&quot;] = &quot;%s Event Dispatched&quot;;
</span><ins>+localizedStrings[&quot;(Index)&quot;] = &quot;(Index)&quot;;
</ins><span class="cx"> localizedStrings[&quot;(anonymous function)&quot;] = &quot;(anonymous function)&quot;;
</span><span class="cx"> localizedStrings[&quot;(many)&quot;] = &quot;(many)&quot;;
</span><span class="cx"> localizedStrings[&quot;(program)&quot;] = &quot;(program)&quot;;
</span><span class="lines">@@ -248,6 +249,7 @@
</span><span class="cx"> localizedStrings[&quot;Image Size&quot;] = &quot;Image Size&quot;;
</span><span class="cx"> localizedStrings[&quot;Images&quot;] = &quot;Images&quot;;
</span><span class="cx"> localizedStrings[&quot;Immediate Pause Requested&quot;] = &quot;Immediate Pause Requested&quot;;
</span><ins>+localizedStrings[&quot;Index&quot;] = &quot;Index&quot;;
</ins><span class="cx"> localizedStrings[&quot;Index Key \u2014 %s&quot;] = &quot;Index Key \u2014 %s&quot;;
</span><span class="cx"> localizedStrings[&quot;Indexed Databases&quot;] = &quot;Indexed Databases&quot;;
</span><span class="cx"> localizedStrings[&quot;Inherited From: &quot;] = &quot;Inherited From: &quot;;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsConsoleMessagejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleMessage.js (179492 => 179493)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleMessage.js        2015-02-02 21:04:08 UTC (rev 179492)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleMessage.js        2015-02-02 21:07:39 UTC (rev 179493)
</span><span class="lines">@@ -64,7 +64,7 @@
</span><span class="cx">     return new WebInspector.ConsoleMessageImpl(source, level, message, null, type, url, line, column, repeatCount, parameters, stackTrace, request);
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-// Note: Keep these constants in sync with the ones in Console.h
</del><ins>+// FIXME: Switch to ConsoleAgent.ConsoleMessageSource.
</ins><span class="cx"> WebInspector.ConsoleMessage.MessageSource = {
</span><span class="cx">     HTML: &quot;html&quot;,
</span><span class="cx">     XML: &quot;xml&quot;,
</span><span class="lines">@@ -74,10 +74,12 @@
</span><span class="cx">     Other: &quot;other&quot;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+// FIXME: Switch to ConsoleAgent.ConsoleMessageType.
</ins><span class="cx"> WebInspector.ConsoleMessage.MessageType = {
</span><span class="cx">     Log: &quot;log&quot;,
</span><span class="cx">     Dir: &quot;dir&quot;,
</span><span class="cx">     DirXML: &quot;dirxml&quot;,
</span><ins>+    Table: &quot;table&quot;,
</ins><span class="cx">     Trace: &quot;trace&quot;,
</span><span class="cx">     StartGroup: &quot;startGroup&quot;,
</span><span class="cx">     StartGroupCollapsed: &quot;startGroupCollapsed&quot;,
</span><span class="lines">@@ -86,6 +88,7 @@
</span><span class="cx">     Result: &quot;result&quot;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+// FIXME: Switch to ConsoleAgent.ConsoleMessageLevel.
</ins><span class="cx"> WebInspector.ConsoleMessage.MessageLevel = {
</span><span class="cx">     Tip: &quot;tip&quot;,
</span><span class="cx">     Log: &quot;log&quot;,
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsConsoleMessageImpljs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleMessageImpl.js (179492 => 179493)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleMessageImpl.js        2015-02-02 21:04:08 UTC (rev 179492)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleMessageImpl.js        2015-02-02 21:07:39 UTC (rev 179493)
</span><span class="lines">@@ -234,6 +234,11 @@
</span><span class="cx">                 formattedResult.appendChild(document.createTextNode(&quot; &quot;));
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        if (this.type === WebInspector.ConsoleMessage.MessageType.Table) {
+            formattedResult.appendChild(this._formatParameterAsTable(parameters));
+            return formattedResult;
+        }
+
</ins><span class="cx">         // Single parameter, or unused substitutions from above.
</span><span class="cx">         for (var i = 0; i &lt; parameters.length; ++i) {
</span><span class="cx">             // Inline strings when formatting.
</span><span class="lines">@@ -373,20 +378,7 @@
</span><span class="cx">                 element.appendChild(document.createTextNode(&quot;: &quot;));
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            var span = element.createChild(&quot;span&quot;, &quot;console-formatted-&quot; + property.type);
-            if (property.type === &quot;object&quot;) {
-                if (property.subtype === &quot;node&quot;)
-                    span.classList.add(&quot;console-formatted-preview-node&quot;);
-                else if (property.subtype === &quot;regexp&quot;)
-                    span.classList.add(&quot;console-formatted-regexp&quot;);
-            }
-
-            if (property.type === &quot;string&quot;)
-                span.textContent = &quot;\&quot;&quot; + property.value + &quot;\&quot;&quot;;
-            else if (property.type === &quot;function&quot;)
-                span.textContent = &quot;function&quot;;
-            else
-                span.textContent = property.value;
</del><ins>+            element.appendChild(this._propertyPreviewElement(property));
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (preview.overflow)
</span><span class="lines">@@ -397,6 +389,32 @@
</span><span class="cx">         return preview.lossless;
</span><span class="cx">     },
</span><span class="cx"> 
</span><ins>+    _propertyPreviewElement: function(property)
+    {
+        var span = document.createElement(&quot;span&quot;);
+        span.classList.add(&quot;console-formatted-&quot; + property.type);
+
+        if (property.type === &quot;string&quot;) {
+            span.textContent = &quot;\&quot;&quot; + property.value.replace(/\n/g, &quot;\u21B5&quot;) + &quot;\&quot;&quot;;
+            return span;
+        }
+
+        if (property.type === &quot;function&quot;) {
+            span.textContent = &quot;function&quot;;
+            return span;
+        }
+
+        if (property.type === &quot;object&quot;) {
+            if (property.subtype === &quot;node&quot;)
+                span.classList.add(&quot;console-formatted-preview-node&quot;);
+            else if (property.subtype === &quot;regexp&quot;)
+                span.classList.add(&quot;console-formatted-regexp&quot;);
+        }
+
+        span.textContent = property.value;
+        return span;
+    },
+
</ins><span class="cx">     _appendValuePreview: function(element, preview)
</span><span class="cx">     {
</span><span class="cx">         element.appendChild(document.createTextNode(preview.description));
</span><span class="lines">@@ -429,6 +447,86 @@
</span><span class="cx">         arr.getOwnProperties(this._printArray.bind(this, arr, elem));
</span><span class="cx">     },
</span><span class="cx"> 
</span><ins>+    _formatParameterAsTable: function(parameters)
+    {
+        var element = document.createElement(&quot;span&quot;);
+        var table = parameters[0];
+        if (!table || !table.preview)
+            return element;
+
+        var rows = [];
+        var columnNames = [];
+        var flatValues = [];
+        var preview = table.preview;
+
+        // Check first for valuePreviews in the properties meaning this was an array of objects.
+        for (var i = 0; i &lt; preview.properties.length; ++i) {
+            var rowProperty = preview.properties[i];
+            var rowPreview = rowProperty.valuePreview;
+            if (!rowPreview)
+                continue;
+
+            var rowValue = {};
+            const maxColumnsToRender = 10;
+            for (var j = 0; j &lt; rowPreview.properties.length; ++j) {
+                var cellProperty = rowPreview.properties[j];
+                var columnRendered = columnNames.contains(cellProperty.name);
+                if (!columnRendered) {
+                    if (columnNames.length === maxColumnsToRender)
+                        continue;
+                    columnRendered = true;
+                    columnNames.push(cellProperty.name);
+                }
+
+                rowValue[cellProperty.name] = this._propertyPreviewElement(cellProperty);
+            }
+            rows.push([rowProperty.name, rowValue]);
+        }
+
+        // If there were valuePreviews, convert to a flat list.
+        if (rows.length) {
+            columnNames.unshift(WebInspector.UIString(&quot;(Index)&quot;));
+            for (var i = 0; i &lt; rows.length; ++i) {
+                var rowName = rows[i][0];
+                var rowValue = rows[i][1];
+                flatValues.push(rowName);
+                for (var j = 1; j &lt; columnNames.length; ++j)
+                    flatValues.push(rowValue[columnNames[j]]);
+            }
+        }
+
+        // If there were no value Previews, then check for an array of values.
+        if (!flatValues.length) {
+            for (var i = 0; i &lt; preview.properties.length; ++i) {
+                var rowProperty = preview.properties[i];
+                if (!(&quot;value&quot; in rowProperty))
+                    continue;
+
+                if (!columnNames.length) {
+                    columnNames.push(WebInspector.UIString(&quot;Index&quot;));
+                    columnNames.push(WebInspector.UIString(&quot;Value&quot;));
+                }
+
+                flatValues.push(rowProperty.name);
+                flatValues.push(this._propertyPreviewElement(rowProperty));
+            }
+        }
+
+        // If lossless or not table data, output the object so full data can be gotten.
+        if (!preview.lossless || !flatValues.length) {
+            element.appendChild(this._formatParameter(table, true, false));
+            if (!flatValues.length)
+                return element;
+        }
+
+        var dataGridContainer = element.createChild(&quot;span&quot;);
+        var dataGrid = WebInspector.DataGrid.createSortableDataGrid(columnNames, flatValues);
+        dataGrid.element.classList.add(&quot;inline&quot;);
+        dataGridContainer.appendChild(dataGrid.element);
+
+        return element;
+    },
+
</ins><span class="cx">     _formatParameterAsString: function(output, elem)
</span><span class="cx">     {
</span><span class="cx">         var span = document.createElement(&quot;span&quot;);
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsDataGridjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js (179492 => 179493)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js        2015-02-02 21:04:08 UTC (rev 179492)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js        2015-02-02 21:07:39 UTC (rev 179493)
</span><span class="lines">@@ -23,7 +23,7 @@
</span><span class="cx">  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-WebInspector.DataGrid = function(columnsData, editCallback, deleteCallback)
</del><ins>+WebInspector.DataGrid = function(columnsData, editCallback, deleteCallback, preferredColumnOrder)
</ins><span class="cx"> {
</span><span class="cx">     this.columns = new Map;
</span><span class="cx">     this.orderedColumns = [];
</span><span class="lines">@@ -87,8 +87,13 @@
</span><span class="cx">     this.element.appendChild(this._headerTableElement);
</span><span class="cx">     this.element.appendChild(this._scrollContainerElement);
</span><span class="cx"> 
</span><del>-    for (var columnIdentifier in columnsData)
-        this.insertColumn(columnIdentifier, columnsData[columnIdentifier]);
</del><ins>+    if (preferredColumnOrder) {
+        for (var columnIdentifier of preferredColumnOrder)
+            this.insertColumn(columnIdentifier, columnsData[columnIdentifier]);
+    } else {
+        for (var columnIdentifier in columnsData)
+            this.insertColumn(columnIdentifier, columnsData[columnIdentifier]);
+    }
</ins><span class="cx"> 
</span><span class="cx">     this._generateSortIndicatorImagesIfNeeded();
</span><span class="cx"> }
</span><span class="lines">@@ -118,17 +123,15 @@
</span><span class="cx">         return null;
</span><span class="cx"> 
</span><span class="cx">     var columnsData = {};
</span><del>-
</del><span class="cx">     for (var columnName of columnNames) {
</span><del>-        var column = {};
-        column[&quot;width&quot;] = columnName.length;
-        column[&quot;title&quot;] = columnName;
-        column[&quot;sortable&quot;] = true;
-
-        columnsData[columnName] = column;
</del><ins>+        columnsData[columnName] = {
+            width: columnName.length,
+            title: columnName,
+            sortable: true,
+        };
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    var dataGrid = new WebInspector.DataGrid(columnsData);
</del><ins>+    var dataGrid = new WebInspector.DataGrid(columnsData, undefined, undefined, columnNames);
</ins><span class="cx">     for (var i = 0; i &lt; values.length / numColumns; ++i) {
</span><span class="cx">         var data = {};
</span><span class="cx">         for (var j = 0; j &lt; columnNames.length; ++j)
</span><span class="lines">@@ -142,34 +145,38 @@
</span><span class="cx">     function sortDataGrid()
</span><span class="cx">     {
</span><span class="cx">         var sortColumnIdentifier = dataGrid.sortColumnIdentifier;
</span><del>-        var sortAscending = dataGrid.sortOrder === WebInspector.DataGrid.SortOrder.Ascending ? 1 : -1;
</del><span class="cx"> 
</span><ins>+        var columnIsNumeric = true;
</ins><span class="cx">         for (var node of dataGrid.children) {
</span><del>-            if (isNaN(Number(node.data[sortColumnIdentifier] || &quot;&quot;)))
</del><ins>+            var value = dataGrid.textForDataGridNodeColumn(node, sortColumnIdentifier);
+            if (isNaN(Number(value)))
</ins><span class="cx">                 columnIsNumeric = false;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         function comparator(dataGridNode1, dataGridNode2)
</span><span class="cx">         {
</span><del>-            var item1 = dataGridNode1.data[sortColumnIdentifier] || &quot;&quot;;
-            var item2 = dataGridNode2.data[sortColumnIdentifier] || &quot;&quot;;
</del><ins>+            var item1 = dataGrid.textForDataGridNodeColumn(dataGridNode1, sortColumnIdentifier);
+            var item2 = dataGrid.textForDataGridNodeColumn(dataGridNode2, sortColumnIdentifier);
</ins><span class="cx"> 
</span><span class="cx">             var comparison;
</span><span class="cx">             if (columnIsNumeric) {
</span><del>-                // Sort numbers based on comparing their values rather than a lexicographical comparison.
</del><span class="cx">                 var number1 = parseFloat(item1);
</span><span class="cx">                 var number2 = parseFloat(item2);
</span><span class="cx">                 comparison = number1 &lt; number2 ? -1 : (number1 &gt; number2 ? 1 : 0);
</span><span class="cx">             } else
</span><span class="cx">                 comparison = item1 &lt; item2 ? -1 : (item1 &gt; item2 ? 1 : 0);
</span><span class="cx"> 
</span><del>-            return sortDirection * comparison;
</del><ins>+            return comparison;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         dataGrid.sortNodes(comparator);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     dataGrid.addEventListener(WebInspector.DataGrid.Event.SortChanged, sortDataGrid, this);
</span><ins>+
+    dataGrid.sortOrder = WebInspector.DataGrid.SortOrder.Ascending;
+    dataGrid.sortColumnIdentifier = columnNames[0];
+
</ins><span class="cx">     return dataGrid;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -360,7 +367,7 @@
</span><span class="cx">         var children = maxDescentLevel ? this._enumerateChildren(this, [], maxDescentLevel + 1) : this.children;
</span><span class="cx">         for (var node of children) {
</span><span class="cx">             for (var identifier of this.columns.keys()) {
</span><del>-                var text = node.data[identifier] || &quot;&quot;;
</del><ins>+                var text = this.textForDataGridNodeColumn(node, identifier);
</ins><span class="cx">                 if (text.length &gt; widths[identifier])
</span><span class="cx">                     widths[identifier] = text.length;
</span><span class="cx">             }
</span><span class="lines">@@ -414,7 +421,8 @@
</span><span class="cx">         this.updateLayout();
</span><span class="cx">     },
</span><span class="cx"> 
</span><del>-    insertColumn: function(columnIdentifier, columnData, insertionIndex) {
</del><ins>+    insertColumn: function(columnIdentifier, columnData, insertionIndex)
+    {
</ins><span class="cx">         if (insertionIndex === undefined)
</span><span class="cx">             insertionIndex = this.orderedColumns.length;
</span><span class="cx">         insertionIndex = Number.constrain(insertionIndex, 0, this.orderedColumns.length);
</span><span class="lines">@@ -1179,11 +1187,17 @@
</span><span class="cx">         }
</span><span class="cx">     },
</span><span class="cx"> 
</span><ins>+    textForDataGridNodeColumn: function(node, columnIdentifier)
+    {
+        var data = node.data[columnIdentifier];
+        return (data instanceof Node ? data.textContent : data) || &quot;&quot;;
+    },
+
</ins><span class="cx">     _copyTextForDataGridNode: function(node)
</span><span class="cx">     {
</span><span class="cx">         var fields = [];
</span><span class="cx">         for (var identifier of node.dataGrid.orderedColumns)
</span><del>-            fields.push(node.data[identifier] || &quot;&quot;);
</del><ins>+            fields.push(this.textForDataGridNodeColumn(node, identifier));
</ins><span class="cx"> 
</span><span class="cx">         var tabSeparatedValues = fields.join(&quot;\t&quot;);
</span><span class="cx">         return tabSeparatedValues;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsLogContentViewcss"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/LogContentView.css (179492 => 179493)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/LogContentView.css        2015-02-02 21:04:08 UTC (rev 179492)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/LogContentView.css        2015-02-02 21:07:39 UTC (rev 179493)
</span><span class="lines">@@ -72,6 +72,14 @@
</span><span class="cx">     width: 2px;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+.console-messages:focus .console-item.selected .data-grid tr.selected {
+    background-color: hsl(210, 90%, 90%) !important;
+}
+
+.console-item .data-grid tr.selected {
+    background-color: hsl(210, 0%, 90%) !important;
+}
+
</ins><span class="cx"> .console-messages:focus .console-item.selected .console-user-command::after,
</span><span class="cx"> .console-messages:focus .console-item.selected .console-message::after {
</span><span class="cx">     background: hsl(210, 100%, 49%);
</span></span></pre>
</div>
</div>

</body>
</html>