<!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>[179019] 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/179019">179019</a></dd>
<dt>Author</dt> <dd>joepeck@webkit.org</dd>
<dt>Date</dt> <dd>2015-01-23 12:05:44 -0800 (Fri, 23 Jan 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>Web Inspector: Object Previews in the Console
https://bugs.webkit.org/show_bug.cgi?id=129204
Reviewed by Timothy Hatcher.
Source/JavaScriptCore:
Update the very old, unused object preview code. Part of this comes from
the earlier WebKit legacy implementation, and the Blink implementation.
A RemoteObject may include a preview, if it is asked for, and if the
RemoteObject is an object. Previews are a shallow (single level) list
of a limited number of properties on the object. The previewed
properties are always stringified (even if primatives). Previews are
limited to just 5 properties or 100 indices. Previews are marked
as lossless if they are a complete snapshot of the object.
There is a path to make previews two levels deep, that is currently
unused but should soon be used for tables (e.g. IndexedDB).
* inspector/InjectedScriptSource.js:
- Move some code off of InjectedScript to be generic functions
usable by RemoteObject as well.
- Update preview generation to use
* inspector/protocol/Runtime.json:
- Add a new type, "accessor" for preview objects. This represents
a getter / setter. We currently don't get the value.
Source/WebInspectorUI:
* UserInterface/Controllers/JavaScriptLogViewController.js:
(WebInspector.JavaScriptLogViewController.prototype.consolePromptTextCommitted):
* UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js:
(get WebInspector.JavaScriptRuntimeCompletionProvider.prototype.):
Update RuntimeManager callsites that do not need object previews.
* UserInterface/Controllers/RuntimeManager.js:
(WebInspector.RuntimeManager.prototype.evalCallback):
(WebInspector.RuntimeManager.prototype.evaluateInInspectedWindow):
Update the main evaluate method to include a boolean parameter for
object previews. Most callers do not need them. Also, since previews
were not available on iOS 6, switch to invoke, to conditionally
include the command parameter.
* UserInterface/Protocol/RemoteObject.js:
(WebInspector.RemoteObject):
(WebInspector.RemoteObject.fromPayload):
(WebInspector.RemoteObject.prototype.get preview):
Store the preview from the payload.
* UserInterface/Views/ConsoleMessageImpl.js:
(WebInspector.ConsoleMessageImpl.prototype._format):
(WebInspector.ConsoleMessageImpl.prototype._formatParameter):
(WebInspector.ConsoleMessageImpl.prototype._formatParameterAsNode):
(WebInspector.ConsoleMessageImpl.prototype._formatParameterAsString):
(WebInspector.ConsoleMessageImpl.prototype._formatAsArrayEntry):
Pass an explicit false for most formatters to not use a preview if available.
(WebInspector.ConsoleMessageImpl.prototype._formatParameterAsArray):
(WebInspector.ConsoleMessageImpl.prototype._formatParameterAsObject):
Currently only object types are previewed. Though we request previews
for arrays, we don't use the preview because we show a better preview
by just immediately requesting for a full non-preview property list.
(WebInspector.ConsoleMessageImpl.prototype._appendObjectPreview):
Quickly output an object preview into the title element. The format
is "ClassName {prop: value...}". Elide the class name if it is "Object".
Also skip over certain preview properties that may not be useful
at a glance (like constructor, or accessors without values).
* UserInterface/Views/LogContentView.css:
(.console-object-preview):
(.console-formatted-array .console-object-preview):
(.console-object-preview-lossless):
(.expanded .console-object-preview):
Show lossy previews in italics.
Show lossless previews and array previews without italics.
Do not show the class name in the preview in italics when expanded.
(.console-object-preview .name):
Give preview property names the same color as ObjectPropertiesSection property names.
(.expanded .console-object-preview > .console-object-preview-body):
When expanding an object, hide the preview.
(.console-object-preview > .console-object-preview-name.console-object-preview-name-Object):
(.expanded .console-object-preview > .console-object-preview-name.console-object-preview-name-Object):
For "Object" previews, hide the name "Object" when not expanded, and show it when expanded.
LayoutTests:
* inspector/debugger/command-line-api-exception-nested-catch.html:
* inspector/debugger/command-line-api-exception.html:
* inspector/model/remote-object-get-properties.html:
Update RuntimeManager callsites to not ask for previews when evaluating.
* inspector/model/remote-object-expected.txt: Added.
* inspector/model/remote-object.html: Added.
Add a test specifically for Remote Object. This test can also be
opened in a browser. It attempts to run the gamut of all different
types of objects and shows the RemoteObject constructed for it.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsTestExpectations">trunk/LayoutTests/TestExpectations</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggercommandlineapiexceptionnestedcatchhtml">trunk/LayoutTests/inspector/debugger/command-line-api-exception-nested-catch.html</a></li>
<li><a href="#trunkLayoutTestsinspectordebuggercommandlineapiexceptionhtml">trunk/LayoutTests/inspector/debugger/command-line-api-exception.html</a></li>
<li><a href="#trunkLayoutTestsinspectormodelremoteobjectgetpropertieshtml">trunk/LayoutTests/inspector/model/remote-object-get-properties.html</a></li>
<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="#trunkSourceJavaScriptCoreinspectorprotocolRuntimejson">trunk/Source/JavaScriptCore/inspector/protocol/Runtime.json</a></li>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceControllersJavaScriptLogViewControllerjs">trunk/Source/WebInspectorUI/UserInterface/Controllers/JavaScriptLogViewController.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceControllersJavaScriptRuntimeCompletionProviderjs">trunk/Source/WebInspectorUI/UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceControllersRuntimeManagerjs">trunk/Source/WebInspectorUI/UserInterface/Controllers/RuntimeManager.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceProtocolRemoteObjectjs">trunk/Source/WebInspectorUI/UserInterface/Protocol/RemoteObject.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsConsoleMessageImpljs">trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleMessageImpl.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsLogContentViewcss">trunk/Source/WebInspectorUI/UserInterface/Views/LogContentView.css</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsinspectormodelremoteobjectexpectedtxt">trunk/LayoutTests/inspector/model/remote-object-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectormodelremoteobjecthtml">trunk/LayoutTests/inspector/model/remote-object.html</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (179018 => 179019)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-01-23 20:03:41 UTC (rev 179018)
+++ trunk/LayoutTests/ChangeLog        2015-01-23 20:05:44 UTC (rev 179019)
</span><span class="lines">@@ -1,3 +1,21 @@
</span><ins>+2015-01-23 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Object Previews in the Console
+ https://bugs.webkit.org/show_bug.cgi?id=129204
+
+ Reviewed by Timothy Hatcher.
+
+ * inspector/debugger/command-line-api-exception-nested-catch.html:
+ * inspector/debugger/command-line-api-exception.html:
+ * inspector/model/remote-object-get-properties.html:
+ Update RuntimeManager callsites to not ask for previews when evaluating.
+
+ * inspector/model/remote-object-expected.txt: Added.
+ * inspector/model/remote-object.html: Added.
+ Add a test specifically for Remote Object. This test can also be
+ opened in a browser. It attempts to run the gamut of all different
+ types of objects and shows the RemoteObject constructed for it.
+
</ins><span class="cx"> 2015-01-23 Eric Carlson <eric.carlson@apple.com>
</span><span class="cx">
</span><span class="cx"> Create a "load and stall" cgi that support byte ranges.
</span></span></pre></div>
<a id="trunkLayoutTestsTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/TestExpectations (179018 => 179019)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/TestExpectations        2015-01-23 20:03:41 UTC (rev 179018)
+++ trunk/LayoutTests/TestExpectations        2015-01-23 20:05:44 UTC (rev 179019)
</span><span class="lines">@@ -95,6 +95,7 @@
</span><span class="cx"> webkit.org/b/137130 inspector/replay [ Skip ]
</span><span class="cx"> webkit.org/b/137131 inspector/timeline [ Skip ]
</span><span class="cx"> inspector/model/remote-object-get-properties.html [ Skip ]
</span><ins>+inspector/model/remote-object.html [ Skip ]
</ins><span class="cx">
</span><span class="cx"> # Doesn't work yet, relies on network replay functionality (webkit.org/b/130728, webkit.org/b/129391)
</span><span class="cx"> webkit.org/b/131318 http/tests/inspector/replay/document-last-modified-fallback-value.html [ Skip ]
</span></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggercommandlineapiexceptionnestedcatchhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/debugger/command-line-api-exception-nested-catch.html (179018 => 179019)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/command-line-api-exception-nested-catch.html        2015-01-23 20:03:41 UTC (rev 179018)
+++ trunk/LayoutTests/inspector/debugger/command-line-api-exception-nested-catch.html        2015-01-23 20:05:44 UTC (rev 179019)
</span><span class="lines">@@ -16,13 +16,13 @@
</span><span class="cx"> WebInspector.debuggerManager.allExceptionsBreakpoint.disabled = false;
</span><span class="cx">
</span><span class="cx"> function dumpCommandLineAPIValue(prefix) {
</span><del>- WebInspector.runtimeManager.evaluateInInspectedWindow("$exception", "test", true, true, false, function(result, wasThrown) {
</del><ins>+ WebInspector.runtimeManager.evaluateInInspectedWindow("$exception", "test", true, true, false, false, function(result, wasThrown) {
</ins><span class="cx"> InspectorTest.log(prefix + ": $exception => " + result.description);
</span><span class="cx"> });
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> function checkIfExceptionValueMatchesVariable(varName) {
</span><del>- WebInspector.runtimeManager.evaluateInInspectedWindow("$exception === " + varName, "test", true, true, false, function(result, wasThrown) {
</del><ins>+ WebInspector.runtimeManager.evaluateInInspectedWindow("$exception === " + varName, "test", true, true, false, false, function(result, wasThrown) {
</ins><span class="cx"> InspectorTest.log(" CATCH: $exception === " + varName + " ? " + result.description);
</span><span class="cx"> });
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkLayoutTestsinspectordebuggercommandlineapiexceptionhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/debugger/command-line-api-exception.html (179018 => 179019)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/debugger/command-line-api-exception.html        2015-01-23 20:03:41 UTC (rev 179018)
+++ trunk/LayoutTests/inspector/debugger/command-line-api-exception.html        2015-01-23 20:05:44 UTC (rev 179019)
</span><span class="lines">@@ -40,13 +40,13 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> function dumpCommandLineAPIValue(prefix) {
</span><del>- WebInspector.runtimeManager.evaluateInInspectedWindow("$exception", "test", true, true, false, function(result, wasThrown) {
</del><ins>+ WebInspector.runtimeManager.evaluateInInspectedWindow("$exception", "test", true, true, false, false, function(result, wasThrown) {
</ins><span class="cx"> InspectorTest.log(prefix + ": $exception => " + result.description);
</span><span class="cx"> });
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> function checkIfExceptionValueMatchesCatchVariable() {
</span><del>- WebInspector.runtimeManager.evaluateInInspectedWindow("$exception === e", "test", true, true, false, function(result, wasThrown) {
</del><ins>+ WebInspector.runtimeManager.evaluateInInspectedWindow("$exception === e", "test", true, true, false, false, function(result, wasThrown) {
</ins><span class="cx"> InspectorTest.log("STEPPED OUT TO CATCH BLOCK: $exception === e ? " + result.description);
</span><span class="cx"> });
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkLayoutTestsinspectormodelremoteobjectexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/model/remote-object-expected.txt (0 => 179019)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/model/remote-object-expected.txt         (rev 0)
+++ trunk/LayoutTests/inspector/model/remote-object-expected.txt        2015-01-23 20:05:44 UTC (rev 179019)
</span><span class="lines">@@ -0,0 +1,2062 @@
</span><ins>+
+-----------------------------------------------------
+EXPRESSION: null
+{
+ "_type": "object",
+ "_subtype": "null",
+ "_description": "null",
+ "value": null
+}
+
+-----------------------------------------------------
+EXPRESSION: undefined
+{
+ "_type": "undefined",
+ "_description": "undefined"
+}
+
+-----------------------------------------------------
+EXPRESSION: true
+{
+ "_type": "boolean",
+ "_description": "true",
+ "value": true
+}
+
+-----------------------------------------------------
+EXPRESSION: false
+{
+ "_type": "boolean",
+ "_description": "false",
+ "value": false
+}
+
+-----------------------------------------------------
+EXPRESSION: 0
+{
+ "_type": "number",
+ "_description": "0",
+ "value": 0
+}
+
+-----------------------------------------------------
+EXPRESSION: -0
+{
+ "_type": "number",
+ "_description": "0",
+ "value": 0
+}
+
+-----------------------------------------------------
+EXPRESSION: 1
+{
+ "_type": "number",
+ "_description": "1",
+ "value": 1
+}
+
+-----------------------------------------------------
+EXPRESSION: -1
+{
+ "_type": "number",
+ "_description": "-1",
+ "value": -1
+}
+
+-----------------------------------------------------
+EXPRESSION: 1.234
+{
+ "_type": "number",
+ "_description": "1.234",
+ "value": 1.234
+}
+
+-----------------------------------------------------
+EXPRESSION: -1.234
+{
+ "_type": "number",
+ "_description": "-1.234",
+ "value": -1.234
+}
+
+-----------------------------------------------------
+EXPRESSION: 1e3
+{
+ "_type": "number",
+ "_description": "1000",
+ "value": 1000
+}
+
+-----------------------------------------------------
+EXPRESSION: Number.MAX_VALUE
+{
+ "_type": "number",
+ "_description": "1.7976931348623157e+308",
+ "value": 1.7976931348623157e+308
+}
+
+-----------------------------------------------------
+EXPRESSION: Number.MIN_VALUE
+{
+ "_type": "number",
+ "_description": "5e-324",
+ "value": 5e-324
+}
+
+-----------------------------------------------------
+EXPRESSION: NaN
+{
+ "_type": "number",
+ "_description": "NaN",
+ "value": null
+}
+
+-----------------------------------------------------
+EXPRESSION: Infinity
+{
+ "_type": "number",
+ "_description": "Infinity",
+ "value": null
+}
+
+-----------------------------------------------------
+EXPRESSION: ''
+{
+ "_type": "string",
+ "_description": "",
+ "value": ""
+}
+
+-----------------------------------------------------
+EXPRESSION: '"'
+{
+ "_type": "string",
+ "_description": "\"",
+ "value": "\""
+}
+
+-----------------------------------------------------
+EXPRESSION: "'"
+{
+ "_type": "string",
+ "_description": "'",
+ "value": "'"
+}
+
+-----------------------------------------------------
+EXPRESSION: 'string'
+{
+ "_type": "string",
+ "_description": "string",
+ "value": "string"
+}
+
+-----------------------------------------------------
+EXPRESSION: 'Unicode…'
+{
+ "_type": "string",
+ "_description": "Unicode…",
+ "value": "Unicode…"
+}
+
+-----------------------------------------------------
+EXPRESSION: 'I wish I had something to put here.'
+{
+ "_type": "string",
+ "_description": "I wish I had something to put here.",
+ "value": "I wish I had something to put here."
+}
+
+-----------------------------------------------------
+EXPRESSION: (function(){})
+{
+ "_type": "function",
+ "_objectId": "<filtered>",
+ "_description": "function () {}"
+}
+
+-----------------------------------------------------
+EXPRESSION: function foo(){}; foo
+{
+ "_type": "function",
+ "_objectId": "<filtered>",
+ "_description": "function foo() {}"
+}
+
+-----------------------------------------------------
+EXPRESSION: function myFunction(a, b) { console.log(a, b); }; myFunction
+{
+ "_type": "function",
+ "_objectId": "<filtered>",
+ "_description": "function myFunction(a, b) { console.log(a, b); }"
+}
+
+-----------------------------------------------------
+EXPRESSION: Array.prototype.push
+{
+ "_type": "function",
+ "_objectId": "<filtered>",
+ "_description": "function push() {\n [native code]\n}"
+}
+
+-----------------------------------------------------
+EXPRESSION: window.setTimeout
+{
+ "_type": "function",
+ "_objectId": "<filtered>",
+ "_description": "function setTimeout() {\n [native code]\n}"
+}
+
+-----------------------------------------------------
+EXPRESSION: Object.getOwnPropertyDescriptor({ get getter() { return 1 } }, 'getter').get
+{
+ "_type": "function",
+ "_objectId": "<filtered>",
+ "_description": "function () { return 1; }"
+}
+
+-----------------------------------------------------
+EXPRESSION: Object.getOwnPropertyDescriptor({ set setter(v) { console.log(v); } }, 'setter').set
+{
+ "_type": "function",
+ "_objectId": "<filtered>",
+ "_description": "function (v) { console.log(v); }"
+}
+
+-----------------------------------------------------
+EXPRESSION: / /
+{
+ "_type": "object",
+ "_subtype": "regexp",
+ "_objectId": "<filtered>",
+ "_description": "/ /",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "lastIndex",
+ "type": "number",
+ "value": "0"
+ },
+ {
+ "name": "global",
+ "type": "boolean",
+ "value": "false"
+ },
+ {
+ "name": "ignoreCase",
+ "type": "boolean",
+ "value": "false"
+ },
+ {
+ "name": "multiline",
+ "type": "boolean",
+ "value": "false"
+ },
+ {
+ "name": "source",
+ "type": "string",
+ "value": " "
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: /(?:)/
+{
+ "_type": "object",
+ "_subtype": "regexp",
+ "_objectId": "<filtered>",
+ "_description": "/(?:)/",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "lastIndex",
+ "type": "number",
+ "value": "0"
+ },
+ {
+ "name": "global",
+ "type": "boolean",
+ "value": "false"
+ },
+ {
+ "name": "ignoreCase",
+ "type": "boolean",
+ "value": "false"
+ },
+ {
+ "name": "multiline",
+ "type": "boolean",
+ "value": "false"
+ },
+ {
+ "name": "source",
+ "type": "string",
+ "value": "(?:)"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: /^r(e)g[e]{1,}x+/
+{
+ "_type": "object",
+ "_subtype": "regexp",
+ "_objectId": "<filtered>",
+ "_description": "/^r(e)g[e]{1,}x+/",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "lastIndex",
+ "type": "number",
+ "value": "0"
+ },
+ {
+ "name": "global",
+ "type": "boolean",
+ "value": "false"
+ },
+ {
+ "name": "ignoreCase",
+ "type": "boolean",
+ "value": "false"
+ },
+ {
+ "name": "multiline",
+ "type": "boolean",
+ "value": "false"
+ },
+ {
+ "name": "source",
+ "type": "string",
+ "value": "^r(e)g[e]{1,}x+"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: /^r(e)g[e]{1,}x+/ig
+{
+ "_type": "object",
+ "_subtype": "regexp",
+ "_objectId": "<filtered>",
+ "_description": "/^r(e)g[e]{1,}x+/gi",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "lastIndex",
+ "type": "number",
+ "value": "0"
+ },
+ {
+ "name": "global",
+ "type": "boolean",
+ "value": "true"
+ },
+ {
+ "name": "ignoreCase",
+ "type": "boolean",
+ "value": "true"
+ },
+ {
+ "name": "multiline",
+ "type": "boolean",
+ "value": "false"
+ },
+ {
+ "name": "source",
+ "type": "string",
+ "value": "^r(e)g[e]{1,}x+"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: new RegExp('')
+{
+ "_type": "object",
+ "_subtype": "regexp",
+ "_objectId": "<filtered>",
+ "_description": "/(?:)/",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "lastIndex",
+ "type": "number",
+ "value": "0"
+ },
+ {
+ "name": "global",
+ "type": "boolean",
+ "value": "false"
+ },
+ {
+ "name": "ignoreCase",
+ "type": "boolean",
+ "value": "false"
+ },
+ {
+ "name": "multiline",
+ "type": "boolean",
+ "value": "false"
+ },
+ {
+ "name": "source",
+ "type": "string",
+ "value": "(?:)"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: new RegExp('test', 'i')
+{
+ "_type": "object",
+ "_subtype": "regexp",
+ "_objectId": "<filtered>",
+ "_description": "/test/i",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "lastIndex",
+ "type": "number",
+ "value": "0"
+ },
+ {
+ "name": "global",
+ "type": "boolean",
+ "value": "false"
+ },
+ {
+ "name": "ignoreCase",
+ "type": "boolean",
+ "value": "true"
+ },
+ {
+ "name": "multiline",
+ "type": "boolean",
+ "value": "false"
+ },
+ {
+ "name": "source",
+ "type": "string",
+ "value": "test"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: []
+{
+ "_type": "object",
+ "_subtype": "array",
+ "_objectId": "<filtered>",
+ "_description": "Array[0]",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": []
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: [1, 2]
+{
+ "_type": "object",
+ "_subtype": "array",
+ "_objectId": "<filtered>",
+ "_description": "Array[2]",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "0",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "1",
+ "type": "number",
+ "value": "2"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: [[1],[2],[3]]
+{
+ "_type": "object",
+ "_subtype": "array",
+ "_objectId": "<filtered>",
+ "_description": "Array[3]",
+ "_preview": {
+ "lossless": false,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "0",
+ "type": "object",
+ "subtype": "array",
+ "value": "Array[1]"
+ },
+ {
+ "name": "1",
+ "type": "object",
+ "subtype": "array",
+ "value": "Array[1]"
+ },
+ {
+ "name": "2",
+ "type": "object",
+ "subtype": "array",
+ "value": "Array[1]"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: [true, 1, 1.234, 'string', /regex/]
+{
+ "_type": "object",
+ "_subtype": "array",
+ "_objectId": "<filtered>",
+ "_description": "Array[5]",
+ "_preview": {
+ "lossless": false,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "0",
+ "type": "boolean",
+ "value": "true"
+ },
+ {
+ "name": "1",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "2",
+ "type": "number",
+ "value": "1.234"
+ },
+ {
+ "name": "3",
+ "type": "string",
+ "value": "string"
+ },
+ {
+ "name": "4",
+ "type": "object",
+ "subtype": "regexp",
+ "value": "/regex/"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: arr = []; arr.length = 100; arr
+{
+ "_type": "object",
+ "_subtype": "array",
+ "_objectId": "<filtered>",
+ "_description": "Array[100]",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": []
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: arr = []; arr.length = 100; arr.fill(1)
+{
+ "_type": "object",
+ "_subtype": "array",
+ "_objectId": "<filtered>",
+ "_description": "Array[100]",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "0",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "1",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "2",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "3",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "4",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "5",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "6",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "7",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "8",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "9",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "10",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "11",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "12",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "13",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "14",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "15",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "16",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "17",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "18",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "19",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "20",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "21",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "22",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "23",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "24",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "25",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "26",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "27",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "28",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "29",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "30",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "31",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "32",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "33",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "34",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "35",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "36",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "37",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "38",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "39",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "40",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "41",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "42",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "43",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "44",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "45",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "46",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "47",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "48",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "49",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "50",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "51",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "52",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "53",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "54",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "55",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "56",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "57",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "58",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "59",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "60",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "61",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "62",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "63",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "64",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "65",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "66",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "67",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "68",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "69",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "70",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "71",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "72",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "73",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "74",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "75",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "76",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "77",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "78",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "79",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "80",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "81",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "82",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "83",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "84",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "85",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "86",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "87",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "88",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "89",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "90",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "91",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "92",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "93",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "94",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "95",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "96",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "97",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "98",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "99",
+ "type": "number",
+ "value": "1"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: arr = []; arr.length = 100; arr[10] = 1; arr
+{
+ "_type": "object",
+ "_subtype": "array",
+ "_objectId": "<filtered>",
+ "_description": "Array[100]",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "10",
+ "type": "number",
+ "value": "1"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: a = null; (function() { a = arguments; })(1, '2', /3/); a
+{
+ "_type": "object",
+ "_subtype": "array",
+ "_objectId": "<filtered>",
+ "_description": "Arguments[3]",
+ "_preview": {
+ "lossless": false,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "0",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "1",
+ "type": "string",
+ "value": "2"
+ },
+ {
+ "name": "2",
+ "type": "object",
+ "subtype": "regexp",
+ "value": "/3/"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: new Int32Array(new ArrayBuffer(16))
+{
+ "_type": "object",
+ "_subtype": "array",
+ "_objectId": "<filtered>",
+ "_description": "Int32Array[4]",
+ "_preview": {
+ "lossless": false,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "0",
+ "type": "number",
+ "value": "0"
+ },
+ {
+ "name": "1",
+ "type": "number",
+ "value": "0"
+ },
+ {
+ "name": "2",
+ "type": "number",
+ "value": "0"
+ },
+ {
+ "name": "3",
+ "type": "number",
+ "value": "0"
+ },
+ {
+ "name": "byteOffset",
+ "type": "number",
+ "value": "0"
+ },
+ {
+ "name": "byteLength",
+ "type": "number",
+ "value": "16"
+ },
+ {
+ "name": "buffer",
+ "type": "object",
+ "value": "ArrayBuffer"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: var intArray = new Int32Array(new ArrayBuffer(16)); for (var i = 0; i < intArray.length; ++i) intArray[i] = i; intArray
+{
+ "_type": "object",
+ "_subtype": "array",
+ "_objectId": "<filtered>",
+ "_description": "Int32Array[4]",
+ "_preview": {
+ "lossless": false,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "0",
+ "type": "number",
+ "value": "0"
+ },
+ {
+ "name": "1",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "2",
+ "type": "number",
+ "value": "2"
+ },
+ {
+ "name": "3",
+ "type": "number",
+ "value": "3"
+ },
+ {
+ "name": "byteOffset",
+ "type": "number",
+ "value": "0"
+ },
+ {
+ "name": "byteLength",
+ "type": "number",
+ "value": "16"
+ },
+ {
+ "name": "buffer",
+ "type": "object",
+ "value": "ArrayBuffer"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: ({})
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Object",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": []
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: ({a: 1})
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Object",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "a",
+ "type": "number",
+ "value": "1"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: ({a: 1, b: "string", c :/regex/})
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Object",
+ "_preview": {
+ "lossless": false,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "a",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "b",
+ "type": "string",
+ "value": "string"
+ },
+ {
+ "name": "c",
+ "type": "object",
+ "subtype": "regexp",
+ "value": "/regex/"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: ({a:function a(){}, b:function b(){}, get getter(){}, set setter(v){}})
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Object",
+ "_preview": {
+ "lossless": false,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "a",
+ "type": "function",
+ "value": ""
+ },
+ {
+ "name": "b",
+ "type": "function",
+ "value": ""
+ },
+ {
+ "name": "getter",
+ "type": "accessor"
+ },
+ {
+ "name": "setter",
+ "type": "accessor"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: function Foo() {}; new Foo
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Foo",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": []
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: function Bar() { this._x = 5 }; Bar.prototype = {constructor: Bar, get x() {return this._x;}}; new Bar
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Bar",
+ "_preview": {
+ "lossless": false,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "_x",
+ "type": "number",
+ "value": "5"
+ },
+ {
+ "name": "constructor",
+ "type": "function",
+ "value": ""
+ },
+ {
+ "name": "x",
+ "type": "accessor"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: window.loadEvent
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Event",
+ "_preview": {
+ "lossless": false,
+ "overflow": true,
+ "properties": [
+ {
+ "name": "clipboardData",
+ "type": "undefined",
+ "value": "undefined"
+ },
+ {
+ "name": "type",
+ "type": "string",
+ "value": "load"
+ },
+ {
+ "name": "target",
+ "type": "object",
+ "subtype": "node",
+ "value": "#document"
+ },
+ {
+ "name": "currentTarget",
+ "type": "object",
+ "value": "Window"
+ },
+ {
+ "name": "eventPhase",
+ "type": "number",
+ "value": "2"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: new ArrayBuffer(16)
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "ArrayBuffer",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "byteLength",
+ "type": "number",
+ "value": "16"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: new DataView(new ArrayBuffer(16))
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "DataView",
+ "_preview": {
+ "lossless": false,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "byteOffset",
+ "type": "number",
+ "value": "0"
+ },
+ {
+ "name": "byteLength",
+ "type": "number",
+ "value": "16"
+ },
+ {
+ "name": "buffer",
+ "type": "object",
+ "value": "ArrayBuffer"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: document.body
+{
+ "_type": "object",
+ "_subtype": "node",
+ "_objectId": "<filtered>",
+ "_description": "body",
+ "_preview": {
+ "lossless": false,
+ "overflow": true,
+ "properties": [
+ {
+ "name": "aLink",
+ "type": "string",
+ "value": ""
+ },
+ {
+ "name": "background",
+ "type": "string",
+ "value": ""
+ },
+ {
+ "name": "bgColor",
+ "type": "string",
+ "value": ""
+ },
+ {
+ "name": "link",
+ "type": "string",
+ "value": ""
+ },
+ {
+ "name": "text",
+ "type": "string",
+ "value": ""
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: div = document.createElement('div'); div.className = 'foo bar'; div
+{
+ "_type": "object",
+ "_subtype": "node",
+ "_objectId": "<filtered>",
+ "_description": "div.foo.bar",
+ "_preview": {
+ "lossless": false,
+ "overflow": true,
+ "properties": [
+ {
+ "name": "align",
+ "type": "string",
+ "value": ""
+ },
+ {
+ "name": "title",
+ "type": "string",
+ "value": ""
+ },
+ {
+ "name": "lang",
+ "type": "string",
+ "value": ""
+ },
+ {
+ "name": "translate",
+ "type": "boolean",
+ "value": "true"
+ },
+ {
+ "name": "dir",
+ "type": "string",
+ "value": ""
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: span = document.createElement('span'); span.id = 'foo'; span
+{
+ "_type": "object",
+ "_subtype": "node",
+ "_objectId": "<filtered>",
+ "_description": "span#foo",
+ "_preview": {
+ "lossless": false,
+ "overflow": true,
+ "properties": [
+ {
+ "name": "title",
+ "type": "string",
+ "value": ""
+ },
+ {
+ "name": "lang",
+ "type": "string",
+ "value": ""
+ },
+ {
+ "name": "translate",
+ "type": "boolean",
+ "value": "true"
+ },
+ {
+ "name": "dir",
+ "type": "string",
+ "value": ""
+ },
+ {
+ "name": "tabIndex",
+ "type": "number",
+ "value": "-1"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: document.createTextNode('text')
+{
+ "_type": "object",
+ "_subtype": "node",
+ "_objectId": "<filtered>",
+ "_description": "#text",
+ "_preview": {
+ "lossless": false,
+ "overflow": true,
+ "properties": [
+ {
+ "name": "wholeText",
+ "type": "string",
+ "value": "text"
+ },
+ {
+ "name": "splitText",
+ "type": "function",
+ "value": ""
+ },
+ {
+ "name": "replaceWholeText",
+ "type": "function",
+ "value": ""
+ },
+ {
+ "name": "data",
+ "type": "string",
+ "value": "text"
+ },
+ {
+ "name": "length",
+ "type": "number",
+ "value": "4"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: document.head.children
+{
+ "_type": "object",
+ "_subtype": "array",
+ "_objectId": "<filtered>",
+ "_description": "HTMLCollection[3]",
+ "_preview": {
+ "lossless": false,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "0",
+ "type": "object",
+ "subtype": "node",
+ "value": "meta"
+ },
+ {
+ "name": "1",
+ "type": "object",
+ "subtype": "node",
+ "value": "script"
+ },
+ {
+ "name": "2",
+ "type": "object",
+ "subtype": "node",
+ "value": "script"
+ },
+ {
+ "name": "item",
+ "type": "function",
+ "value": ""
+ },
+ {
+ "name": "namedItem",
+ "type": "function",
+ "value": ""
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: document.getElementsByClassName('my-test')
+{
+ "_type": "object",
+ "_subtype": "array",
+ "_objectId": "<filtered>",
+ "_description": "NodeList[3]",
+ "_preview": {
+ "lossless": false,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "0",
+ "type": "object",
+ "subtype": "node",
+ "value": "p.my-test"
+ },
+ {
+ "name": "1",
+ "type": "object",
+ "subtype": "node",
+ "value": "p.my-test"
+ },
+ {
+ "name": "2",
+ "type": "object",
+ "subtype": "node",
+ "value": "p.my-test"
+ },
+ {
+ "name": "constructor",
+ "type": "object",
+ "value": "NodeListConstructor"
+ },
+ {
+ "name": "item",
+ "type": "function",
+ "value": ""
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: document.querySelectorAll('.my-test')
+{
+ "_type": "object",
+ "_subtype": "array",
+ "_objectId": "<filtered>",
+ "_description": "NodeList[3]",
+ "_preview": {
+ "lossless": false,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "0",
+ "type": "object",
+ "subtype": "node",
+ "value": "p.my-test"
+ },
+ {
+ "name": "1",
+ "type": "object",
+ "subtype": "node",
+ "value": "p.my-test"
+ },
+ {
+ "name": "2",
+ "type": "object",
+ "subtype": "node",
+ "value": "p.my-test"
+ },
+ {
+ "name": "constructor",
+ "type": "object",
+ "value": "NodeListConstructor"
+ },
+ {
+ "name": "item",
+ "type": "function",
+ "value": ""
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: error = null; try { [].x.x; } catch (e) { error = e; }; error
+{
+ "_type": "object",
+ "_subtype": "error",
+ "_objectId": "<filtered>",
+ "_description": "TypeError: undefined is not an object (evaluating '[].x.x')",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "message",
+ "type": "string",
+ "value": "undefined is not an object (evaluating '[].x.x')"
+ },
+ {
+ "name": "line",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "column",
+ "type": "number",
+ "value": "25"
+ },
+ {
+ "name": "stack",
+ "type": "string",
+ "value": "eval code\neval@[native code]\n_evaluateOn\n_evaluateAndWrap\nevaluate"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: error = null; try { eval('if()'); } catch (e) { error = e; }; error
+{
+ "_type": "object",
+ "_subtype": "error",
+ "_objectId": "<filtered>",
+ "_description": "SyntaxError: Unexpected token ')'",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": [
+ {
+ "name": "message",
+ "type": "string",
+ "value": "Unexpected token ')'"
+ },
+ {
+ "name": "line",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "column",
+ "type": "number",
+ "value": "25"
+ },
+ {
+ "name": "stack",
+ "type": "string",
+ "value": "eval@[native code]\neval code\neval@[native code]\n_evaluateOn\n_evaluateAndWrap\nevaluate"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: error = null; try { document.createTextNode('').splitText(100); } catch (e) { error = e; }; error
+{
+ "_type": "object",
+ "_subtype": "error",
+ "_objectId": "<filtered>",
+ "_description": "Error: IndexSizeError: DOM Exception 1",
+ "_preview": {
+ "lossless": false,
+ "overflow": true,
+ "properties": [
+ {
+ "name": "code",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "name",
+ "type": "string",
+ "value": "IndexSizeError"
+ },
+ {
+ "name": "message",
+ "type": "string",
+ "value": "IndexSizeError: DOM Exception 1"
+ },
+ {
+ "name": "line",
+ "type": "number",
+ "value": "1"
+ },
+ {
+ "name": "column",
+ "type": "number",
+ "value": "58"
+ }
+ ]
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: Object.seal({})
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Object",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": []
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: Object.freeze({})
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Object",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": []
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: new Map
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Map",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": []
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: map = new Map; map.set(1, 2); map.set('key', 'value'); map
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Map",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": []
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: map = new Map; map.set({a:1}, {b:2}); map.set(document.body, [1,2]); map
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Map",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": []
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: map = new Map; for (var i = 0; i <= 100; i++) map.set(i, i); map
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Map",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": []
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: map = new WeakMap; map.set({id:1}, [1,2]); map
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "WeakMap",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": []
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: new Set
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Set",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": []
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: set = new Set; set.add(1); set.add(2); set.add('key'); set
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Set",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": []
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: set = new Set; set.add({a:1}); set.add(document.body); set.add([1,2]); set
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Set",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": []
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: set = new Set; for (var i = 0; i <= 100; i++) set.add(i); set
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Set",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": []
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: new Promise(function(){})
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Promise",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": []
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: Promise.reject()
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Promise",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": []
+ }
+}
+
+-----------------------------------------------------
+EXPRESSION: Promise.resolve()
+{
+ "_type": "object",
+ "_objectId": "<filtered>",
+ "_description": "Promise",
+ "_preview": {
+ "lossless": true,
+ "overflow": false,
+ "properties": []
+ }
+}
+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectormodelremoteobjectgetpropertieshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/model/remote-object-get-properties.html (179018 => 179019)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/model/remote-object-get-properties.html        2015-01-23 20:03:41 UTC (rev 179018)
+++ trunk/LayoutTests/inspector/model/remote-object-get-properties.html        2015-01-23 20:05:44 UTC (rev 179019)
</span><span class="lines">@@ -69,7 +69,7 @@
</span><span class="cx"> InspectorTest.log("-----------------------------------------------------");
</span><span class="cx"> InspectorTest.log("EXPRESSION: " + step.expression);
</span><span class="cx">
</span><del>- WebInspector.runtimeManager.evaluateInInspectedWindow(step.expression, "test", false, true, false, function(remoteObject, wasThrown) {
</del><ins>+ WebInspector.runtimeManager.evaluateInInspectedWindow(step.expression, "test", false, true, false, false, function(remoteObject, wasThrown) {
</ins><span class="cx"> InspectorTest.assert(remoteObject instanceof WebInspector.RemoteObject);
</span><span class="cx"> InspectorTest.log("type: " + remoteObject.type);
</span><span class="cx"> if (remoteObject.subtype)
</span></span></pre></div>
<a id="trunkLayoutTestsinspectormodelremoteobjecthtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/model/remote-object.html (0 => 179019)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/model/remote-object.html         (rev 0)
+++ trunk/LayoutTests/inspector/model/remote-object.html        2015-01-23 20:05:44 UTC (rev 179019)
</span><span class="lines">@@ -0,0 +1,193 @@
</span><ins>+<!doctype html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<script type="text/javascript" src="../../http/tests/inspector/inspector-test.js"></script>
+<script>
+function test()
+{
+ var currentStepIndex = 0;
+ var steps = [
+ // Special:
+
+ // Null / undefined
+ {expression: "null"},
+ {expression: "undefined"},
+
+ // Primatives:
+
+ // Boolean
+ {expression: "true"},
+ {expression: "false"},
+
+ // Number
+ {expression: "0"},
+ {expression: "-0"},
+ {expression: "1"},
+ {expression: "-1"},
+ {expression: "1.234"},
+ {expression: "-1.234"},
+ {expression: "1e3"},
+ {expression: "Number.MAX_VALUE"},
+ {expression: "Number.MIN_VALUE"},
+ {expression: "NaN"},
+ {expression: "Infinity"},
+
+ // Strings
+ {expression: "''"},
+ {expression: "'\"'"}, // a single quote
+ {expression: "\"'\""}, // a double quote
+ {expression: "'string'"},
+ {expression: "'Unicode…'"},
+ {expression: "'I wish I had something to put here.'"},
+
+ // Function
+ {expression: "(function(){})"},
+ {expression: "function foo(){}; foo"},
+ {expression: "function myFunction(a, b) { console.log(a, b); }; myFunction"},
+ {expression: "Array.prototype.push"}, // native (ECMAScript)
+ {expression: "window.setTimeout"}, // native (DOM)
+ {expression: "Object.getOwnPropertyDescriptor({ get getter() { return 1 } }, 'getter').get"}, // getter
+ {expression: "Object.getOwnPropertyDescriptor({ set setter(v) { console.log(v); } }, 'setter').set"}, // setter
+
+ // Objects:
+
+ // Date
+ {expression: "new Date(99)", browserOnly: true},
+ {expression: "new Date(1421903245871)", browserOnly: true},
+
+ // Regexp
+ {expression: "/ /"},
+ {expression: "/(?:)/"},
+ {expression: "/^r(e)g[e]{1,}x+/"},
+ {expression: "/^r(e)g[e]{1,}x+/ig"},
+ {expression: "new RegExp('')"},
+ {expression: "new RegExp('test', 'i')"},
+
+ // Array
+ {expression: "[]"},
+ {expression: "[1, 2]"},
+ {expression: "[[1],[2],[3]]"},
+ {expression: "[true, 1, 1.234, 'string', /regex/]"},
+ {expression: "arr = []; arr.length = 100; arr"}, // 100 empty elements
+ {expression: "arr = []; arr.length = 100; arr.fill(1)"}, // 100 full elements
+ {expression: "arr = []; arr.length = 100; arr[10] = 1; arr"}, // sparse
+
+ // Array-like (Arguments, TypedArrays)
+ {expression: "a = null; (function() { a = arguments; })(1, '2', /3/); a"},
+ {expression: "new Int32Array(new ArrayBuffer(16))"},
+ {expression: "var intArray = new Int32Array(new ArrayBuffer(16)); for (var i = 0; i < intArray.length; ++i) intArray[i] = i; intArray"},
+
+ // Object
+ {expression: "({})"},
+ {expression: "({a: 1})"},
+ {expression: "({a: 1, b: \"string\", c :/regex/})"},
+ {expression: "({a:function a(){}, b:function b(){}, get getter(){}, set setter(v){}})"},
+ {expression: "function Foo() {}; new Foo"},
+ {expression: "function Bar() { this._x = 5 }; Bar.prototype = {constructor: Bar, get x() {return this._x;}}; new Bar"},
+ {expression: "window.loadEvent"}, // window.loadEvent is set inside of <body onload="..."> below.
+ {expression: "new ArrayBuffer(16)"},
+ {expression: "new DataView(new ArrayBuffer(16))"},
+
+ // Node
+ {expression: "document.body"},
+ {expression: "div = document.createElement('div'); div.className = 'foo bar'; div"},
+ {expression: "span = document.createElement('span'); span.id = 'foo'; span"},
+ {expression: "document.createTextNode('text')"},
+
+ // Node Collections (NodeLists / Collections)
+ {expression: "document.all", browserOnly: true}, // HTMLAllCollection
+ {expression: "document.head.children"}, // HTMLCollection
+ {expression: "document.getElementsByClassName('my-test')"}, // NodeList
+ {expression: "document.querySelectorAll('.my-test')"}, // Non-Live NodeList
+
+ // Error
+ {expression: "error = null; try { [].x.x; } catch (e) { error = e; }; error"},
+ {expression: "error = null; try { eval('if()'); } catch (e) { error = e; }; error"},
+ {expression: "error = null; try { document.createTextNode('').splitText(100); } catch (e) { error = e; }; error"},
+
+ // Improveable:
+
+ // Sealed / Frozen objects.
+ {expression: "Object.seal({})"},
+ {expression: "Object.freeze({})"},
+
+ // Map / WeakMap
+ {expression: "new Map"},
+ {expression: "map = new Map; map.set(1, 2); map.set('key', 'value'); map"},
+ {expression: "map = new Map; map.set({a:1}, {b:2}); map.set(document.body, [1,2]); map"},
+ {expression: "map = new Map; for (var i = 0; i <= 100; i++) map.set(i, i); map"},
+ {expression: "map = new WeakMap; map.set({id:1}, [1,2]); map"},
+
+ // Set
+ {expression: "new Set"},
+ {expression: "set = new Set; set.add(1); set.add(2); set.add('key'); set"},
+ {expression: "set = new Set; set.add({a:1}); set.add(document.body); set.add([1,2]); set"},
+ {expression: "set = new Set; for (var i = 0; i <= 100; i++) set.add(i); set"},
+
+ // Promise
+ {expression: "new Promise(function(){})"},
+ {expression: "Promise.reject()"},
+ {expression: "Promise.resolve()"},
+ ];
+
+ if (!window.WebInspector) {
+ window.steps = steps;
+ return;
+ }
+
+ function remoteObjectJSONFilter(key, value)
+ {
+ if (key === "_objectId")
+ return "<filtered>";
+
+ if (key === "_hasChildren")
+ return undefined;
+
+ return value;
+ }
+
+ function runNextStep() {
+ if (currentStepIndex >= steps.length) {
+ InspectorTest.completeTest();
+ return;
+ }
+
+ var step = steps[currentStepIndex++];
+ if (step.browserOnly) {
+ runNextStep();
+ return;
+ }
+
+ InspectorTest.log("");
+ InspectorTest.log("-----------------------------------------------------");
+ InspectorTest.log("EXPRESSION: " + step.expression);
+
+ WebInspector.runtimeManager.evaluateInInspectedWindow(step.expression, "test", false, true, false, true, function(remoteObject, wasThrown) {
+ InspectorTest.assert(remoteObject instanceof WebInspector.RemoteObject);
+ InspectorTest.log(JSON.stringify(remoteObject, remoteObjectJSONFilter, " "));
+ runNextStep();
+ });
+ }
+
+ runNextStep();
+}
+
+function runInBrowserTest()
+{
+ if (window.testRunner)
+ return;
+
+ test(); // get steps.
+
+ for (var step of steps) {
+ console.info("EXPRESSION", step.expression);
+ console.log(eval(step.expression));
+ }
+}
+</script>
+</head>
+<body onload="window.loadEvent = event; runTest(); runInBrowserTest();">
+ <p class="my-test"></p><p class="my-test"></p><p class="my-test"></p>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (179018 => 179019)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-01-23 20:03:41 UTC (rev 179018)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-01-23 20:05:44 UTC (rev 179019)
</span><span class="lines">@@ -1,3 +1,32 @@
</span><ins>+2015-01-23 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Object Previews in the Console
+ https://bugs.webkit.org/show_bug.cgi?id=129204
+
+ Reviewed by Timothy Hatcher.
+
+ Update the very old, unused object preview code. Part of this comes from
+ the earlier WebKit legacy implementation, and the Blink implementation.
+
+ A RemoteObject may include a preview, if it is asked for, and if the
+ RemoteObject is an object. Previews are a shallow (single level) list
+ of a limited number of properties on the object. The previewed
+ properties are always stringified (even if primatives). Previews are
+ limited to just 5 properties or 100 indices. Previews are marked
+ as lossless if they are a complete snapshot of the object.
+
+ There is a path to make previews two levels deep, that is currently
+ unused but should soon be used for tables (e.g. IndexedDB).
+
+ * inspector/InjectedScriptSource.js:
+ - Move some code off of InjectedScript to be generic functions
+ usable by RemoteObject as well.
+ - Update preview generation to use
+
+ * inspector/protocol/Runtime.json:
+ - Add a new type, "accessor" for preview objects. This represents
+ a getter / setter. We currently don't get the value.
+
</ins><span class="cx"> 2015-01-23 Michael Saboff <msaboff@apple.com>
</span><span class="cx">
</span><span class="cx"> Immediate crash when setting JS breakpoint
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorInjectedScriptSourcejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js (179018 => 179019)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js        2015-01-23 20:03:41 UTC (rev 179018)
+++ trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js        2015-01-23 20:05:44 UTC (rev 179019)
</span><span class="lines">@@ -1,5 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx"> * Copyright (C) 2007, 2014 Apple Inc. All rights reserved.
</span><ins>+ * Copyright (C) 2013 Google 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">@@ -33,6 +34,18 @@
</span><span class="cx"> // Protect against Object overwritten by the user code.
</span><span class="cx"> var Object = {}.constructor;
</span><span class="cx">
</span><ins>+function toString(obj)
+{
+ return "" + obj;
+}
+
+function isUInt32(obj)
+{
+ if (typeof obj === "number")
+ return obj >>> 0 === obj && (obj > 0 || 1 / obj > 0);
+ return "" + (obj >>> 0) === obj;
+}
+
</ins><span class="cx"> var InjectedScript = function()
</span><span class="cx"> {
</span><span class="cx"> this._lastBoundObjectId = 1;
</span><span class="lines">@@ -80,7 +93,7 @@
</span><span class="cx"> if (this.isPrimitiveValue(object))
</span><span class="cx"> result.value = object;
</span><span class="cx"> else
</span><del>- result.description = this._toString(object);
</del><ins>+ result.description = toString(object);
</ins><span class="cx"> return result;
</span><span class="cx"> },
</span><span class="cx">
</span><span class="lines">@@ -323,7 +336,7 @@
</span><span class="cx"> {
</span><span class="cx"> var remoteObject = this._wrapObject(value, objectGroup);
</span><span class="cx"> try {
</span><del>- remoteObject.description = this._toString(value);
</del><ins>+ remoteObject.description = toString(value);
</ins><span class="cx"> } catch (e) {}
</span><span class="cx"> return {
</span><span class="cx"> wasThrown: true,
</span><span class="lines">@@ -479,7 +492,7 @@
</span><span class="cx"> // Modes:
</span><span class="cx"> // - ownProperties - only own properties and __proto__
</span><span class="cx"> // - ownAndGetterProperties - own properties, __proto__, and getters in the prototype chain
</span><del>- // - neither - get all properties in the prototype chain, exclude __proto__
</del><ins>+ // - neither - get all properties in the prototype chain and __proto__
</ins><span class="cx">
</span><span class="cx"> var descriptors = [];
</span><span class="cx"> var nameProcessed = {};
</span><span class="lines">@@ -611,7 +624,6 @@
</span><span class="cx"> } catch (e) {
</span><span class="cx"> }
</span><span class="cx">
</span><del>- // If owning frame has navigated to somewhere else window properties will be undefined.
</del><span class="cx"> return null;
</span><span class="cx"> },
</span><span class="cx">
</span><span class="lines">@@ -623,13 +635,13 @@
</span><span class="cx"> var subtype = this._subtype(obj);
</span><span class="cx">
</span><span class="cx"> if (subtype === "regexp")
</span><del>- return this._toString(obj);
</del><ins>+ return toString(obj);
</ins><span class="cx">
</span><span class="cx"> if (subtype === "date")
</span><del>- return this._toString(obj);
</del><ins>+ return toString(obj);
</ins><span class="cx">
</span><span class="cx"> if (subtype === "error")
</span><del>- return this._toString(obj);
</del><ins>+ return toString(obj);
</ins><span class="cx">
</span><span class="cx"> if (subtype === "node") {
</span><span class="cx"> var description = obj.nodeName.toLowerCase();
</span><span class="lines">@@ -655,23 +667,16 @@
</span><span class="cx">
</span><span class="cx"> // NodeList in JSC is a function, check for array prior to this.
</span><span class="cx"> if (typeof obj === "function")
</span><del>- return this._toString(obj);
</del><ins>+ return toString(obj);
</ins><span class="cx">
</span><del>- // FIXME: Can we remove this?
</del><ins>+ // If Object, try for a better name from the constructor.
</ins><span class="cx"> if (className === "Object") {
</span><del>- // In Chromium DOM wrapper prototypes will have Object as their constructor name,
- // get the real DOM wrapper name from the constructor property.
</del><span class="cx"> var constructorName = obj.constructor && obj.constructor.name;
</span><span class="cx"> if (constructorName)
</span><span class="cx"> return constructorName;
</span><span class="cx"> }
</span><ins>+
</ins><span class="cx"> return className;
</span><del>- },
-
- _toString: function(obj)
- {
- // We don't use String(obj) because inspectedGlobalObject.String is undefined if owning frame navigated to another page.
- return "" + obj;
</del><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -708,7 +713,7 @@
</span><span class="cx"> this.className = InjectedScriptHost.internalConstructorName(object);
</span><span class="cx"> this.description = injectedScript._describe(object);
</span><span class="cx">
</span><del>- if (generatePreview && (this.type === "object" || injectedScript._isHTMLAllCollection(object)))
</del><ins>+ if (generatePreview && this.type === "object")
</ins><span class="cx"> this.preview = this._generatePreview(object, undefined, columnNames);
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -727,85 +732,122 @@
</span><span class="cx"> properties: isTableRowsRequest ? 1000 : Math.max(5, firstLevelKeysCount),
</span><span class="cx"> indexes: isTableRowsRequest ? 1000 : Math.max(100, firstLevelKeysCount)
</span><span class="cx"> };
</span><del>- for (var o = object; injectedScript._isDefined(o); o = o.__proto__)
- this._generateProtoPreview(o, preview, propertiesThreshold, firstLevelKeys, secondLevelKeys);
</del><ins>+
+ try {
+ // All properties.
+ var descriptors = injectedScript._propertyDescriptors(object);
+ this._appendPropertyDescriptors(preview, descriptors, propertiesThreshold, secondLevelKeys);
+ if (propertiesThreshold.indexes < 0 || propertiesThreshold.properties < 0)
+ return preview;
+
+ // FIXME: Internal properties.
+ // FIXME: Map/Set/Iterator entries.
+ } catch (e) {
+ preview.lossless = false;
+ }
+
</ins><span class="cx"> return preview;
</span><span class="cx"> },
</span><span class="cx">
</span><del>- _generateProtoPreview: function(object, preview, propertiesThreshold, firstLevelKeys, secondLevelKeys)
</del><ins>+ _appendPropertyDescriptors: function(preview, descriptors, propertiesThreshold, secondLevelKeys)
</ins><span class="cx"> {
</span><del>- var propertyNames = firstLevelKeys ? firstLevelKeys : Object.keys(object);
- try {
- for (var i = 0; i < propertyNames.length; ++i) {
- if (!propertiesThreshold.properties || !propertiesThreshold.indexes) {
- preview.overflow = true;
- preview.lossless = false;
- break;
- }
- var name = propertyNames[i];
- if (this.subtype === "array" && name === "length")
- continue;
</del><ins>+ for (var descriptor of descriptors) {
+ // Seen enough.
+ if (propertiesThreshold.indexes < 0 || propertiesThreshold.properties < 0)
+ break;
</ins><span class="cx">
</span><del>- var descriptor = Object.getOwnPropertyDescriptor(object, name);
- if (!("value" in descriptor) || !descriptor.enumerable) {
- preview.lossless = false;
- continue;
- }
</del><ins>+ // Error in descriptor.
+ if (descriptor.wasThrown) {
+ preview.lossless = false;
+ continue;
+ }
</ins><span class="cx">
</span><del>- var value = descriptor.value;
- if (value === null) {
- this._appendPropertyPreview(preview, { name: name, type: "object", value: "null" }, propertiesThreshold);
- continue;
- }
</del><ins>+ // Do not show "__proto__" in preview.
+ var name = descriptor.name;
+ if (name === "__proto__")
+ continue;
</ins><span class="cx">
</span><del>- const maxLength = 100;
- var type = typeof value;
</del><ins>+ // Do not show "length" on array like objects in preview.
+ if (this.subtype === "array" && name === "length")
+ continue;
</ins><span class="cx">
</span><del>- if (InjectedScript.primitiveTypes[type]) {
- if (type === "string") {
- if (value.length > maxLength) {
- value = this._abbreviateString(value, maxLength, true);
- preview.lossless = false;
- }
- value = value.replace(/\n/g, "\u21B5");
- }
- this._appendPropertyPreview(preview, { name: name, type: type, value: value + "" }, propertiesThreshold);
- continue;
- }
</del><ins>+ // Do not show non-enumerable non-own properties. Special case to allow array indexes that may be on the prototype.
+ if (!descriptor.enumerable && !descriptor.isOwn && !(this.subtype === "array" && isUInt32(name)))
+ continue;
</ins><span class="cx">
</span><del>- if (secondLevelKeys === null || secondLevelKeys) {
- var subPreview = this._generatePreview(value, secondLevelKeys || undefined);
- var property = { name: name, type: type, valuePreview: subPreview };
- this._appendPropertyPreview(preview, property, propertiesThreshold);
- if (!subPreview.lossless)
- preview.lossless = false;
- if (subPreview.overflow)
- preview.overflow = true;
- continue;
</del><ins>+ // Getter/setter.
+ if (!("value" in descriptor)) {
+ preview.lossless = false;
+ this._appendPropertyPreview(preview, {name: name, type: "accessor"}, propertiesThreshold);
+ continue;
+ }
+
+ // Null value.
+ var value = descriptor.value;
+ if (value === null) {
+ this._appendPropertyPreview(preview, {name: name, type: "object", subtype: "null", value: "null"}, propertiesThreshold);
+ continue;
+ }
+
+ // Ignore non-enumerable functions.
+ var type = typeof value;
+ if (!descriptor.enumerable && type === "function")
+ continue;
+
+ // Fix type of document.all.
+ if (type === "undefined" && injectedScript._isHTMLAllCollection(value))
+ type = "object";
+
+ // Primitive.
+ const maxLength = 100;
+ if (InjectedScript.primitiveTypes[type]) {
+ if (type === "string" && value.length > maxLength) {
+ value = this._abbreviateString(value, maxLength, true);
+ preview.lossless = false;
</ins><span class="cx"> }
</span><ins>+ this._appendPropertyPreview(preview, {name: name, type: type, value: toString(value)}, propertiesThreshold);
+ continue;
+ }
</ins><span class="cx">
</span><del>- preview.lossless = false;
</del><ins>+ // Object.
+ var property = {name: name, type: type};
+ var subtype = injectedScript._subtype(value);
+ if (subtype)
+ property.subtype = subtype;
</ins><span class="cx">
</span><del>- var subtype = injectedScript._subtype(value);
</del><ins>+ // Second level.
+ if (secondLevelKeys === null || secondLevelKeys) {
+ var subPreview = this._generatePreview(value, secondLevelKeys || undefined, undefined);
+ property.valuePreview = subPreview;
+ if (!subPreview.lossless)
+ preview.lossless = false;
+ if (subPreview.overflow)
+ preview.overflow = true;
+ } else {
</ins><span class="cx"> var description = "";
</span><span class="cx"> if (type !== "function")
</span><span class="cx"> description = this._abbreviateString(injectedScript._describe(value), maxLength, subtype === "regexp");
</span><ins>+ property.value = description;
+ preview.lossless = false;
+ }
</ins><span class="cx">
</span><del>- var property = { name: name, type: type, value: description };
- if (subtype)
- property.subtype = subtype;
- this._appendPropertyPreview(preview, property, propertiesThreshold);
- }
- } catch (e) {
</del><ins>+ this._appendPropertyPreview(preview, property, propertiesThreshold);
</ins><span class="cx"> }
</span><span class="cx"> },
</span><span class="cx">
</span><span class="cx"> _appendPropertyPreview: function(preview, property, propertiesThreshold)
</span><span class="cx"> {
</span><del>- if (isNaN(property.name))
</del><ins>+ if (toString(property.name >>> 0) === property.name)
+ propertiesThreshold.indexes--;
+ else
</ins><span class="cx"> propertiesThreshold.properties--;
</span><del>- else
- propertiesThreshold.indexes--;
</del><ins>+
+ if (propertiesThreshold.indexes < 0 || propertiesThreshold.properties < 0) {
+ preview.overflow = true;
+ preview.lossless = false;
+ return;
+ }
+
</ins><span class="cx"> preview.properties.push(property);
</span><span class="cx"> },
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorprotocolRuntimejson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/protocol/Runtime.json (179018 => 179019)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/protocol/Runtime.json        2015-01-23 20:03:41 UTC (rev 179018)
+++ trunk/Source/JavaScriptCore/inspector/protocol/Runtime.json        2015-01-23 20:05:44 UTC (rev 179019)
</span><span class="lines">@@ -18,7 +18,7 @@
</span><span class="cx"> { "name": "value", "type": "any", "optional": true, "description": "Remote object value (in case of primitive values or JSON values if it was requested)." },
</span><span class="cx"> { "name": "description", "type": "string", "optional": true, "description": "String representation of the object." },
</span><span class="cx"> { "name": "objectId", "$ref": "RemoteObjectId", "optional": true, "description": "Unique object identifier (for non-primitive values)." },
</span><del>- { "name": "preview", "$ref": "ObjectPreview", "optional": true, "description": "Preview containsing abbreviated property values." }
</del><ins>+ { "name": "preview", "$ref": "ObjectPreview", "optional": true, "description": "Preview containing abbreviated property values. Specified for <code>object</code> type values only." }
</ins><span class="cx"> ]
</span><span class="cx"> },
</span><span class="cx"> {
</span><span class="lines">@@ -36,10 +36,10 @@
</span><span class="cx"> "type": "object",
</span><span class="cx"> "properties": [
</span><span class="cx"> { "name": "name", "type": "string", "description": "Property name." },
</span><del>- { "name": "type", "type": "string", "enum": ["object", "function", "undefined", "string", "number", "boolean"], "description": "Object type." },
</del><ins>+ { "name": "type", "type": "string", "enum": ["object", "function", "undefined", "string", "number", "boolean", "accessor"], "description": "Object type." },
+ { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date", "error"], "description": "Object subtype hint. Specified for <code>object</code> type values only." },
</ins><span class="cx"> { "name": "value", "type": "string", "optional": true, "description": "User-friendly property value string." },
</span><del>- { "name": "valuePreview", "$ref": "ObjectPreview", "optional": true, "description": "Nested value preview." },
- { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date", "error"], "description": "Object subtype hint. Specified for <code>object</code> type values only." }
</del><ins>+ { "name": "valuePreview", "$ref": "ObjectPreview", "optional": true, "description": "Nested value preview." }
</ins><span class="cx"> ]
</span><span class="cx"> },
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (179018 => 179019)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2015-01-23 20:03:41 UTC (rev 179018)
+++ trunk/Source/WebInspectorUI/ChangeLog        2015-01-23 20:05:44 UTC (rev 179019)
</span><span class="lines">@@ -1,3 +1,69 @@
</span><ins>+2015-01-23 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Object Previews in the Console
+ https://bugs.webkit.org/show_bug.cgi?id=129204
+
+ Reviewed by Timothy Hatcher.
+
+ * UserInterface/Controllers/JavaScriptLogViewController.js:
+ (WebInspector.JavaScriptLogViewController.prototype.consolePromptTextCommitted):
+ * UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js:
+ (get WebInspector.JavaScriptRuntimeCompletionProvider.prototype.):
+ Update RuntimeManager callsites that do not need object previews.
+
+ * UserInterface/Controllers/RuntimeManager.js:
+ (WebInspector.RuntimeManager.prototype.evalCallback):
+ (WebInspector.RuntimeManager.prototype.evaluateInInspectedWindow):
+ Update the main evaluate method to include a boolean parameter for
+ object previews. Most callers do not need them. Also, since previews
+ were not available on iOS 6, switch to invoke, to conditionally
+ include the command parameter.
+
+ * UserInterface/Protocol/RemoteObject.js:
+ (WebInspector.RemoteObject):
+ (WebInspector.RemoteObject.fromPayload):
+ (WebInspector.RemoteObject.prototype.get preview):
+ Store the preview from the payload.
+
+ * UserInterface/Views/ConsoleMessageImpl.js:
+ (WebInspector.ConsoleMessageImpl.prototype._format):
+ (WebInspector.ConsoleMessageImpl.prototype._formatParameter):
+ (WebInspector.ConsoleMessageImpl.prototype._formatParameterAsNode):
+ (WebInspector.ConsoleMessageImpl.prototype._formatParameterAsString):
+ (WebInspector.ConsoleMessageImpl.prototype._formatAsArrayEntry):
+ Pass an explicit false for most formatters to not use a preview if available.
+
+ (WebInspector.ConsoleMessageImpl.prototype._formatParameterAsArray):
+ (WebInspector.ConsoleMessageImpl.prototype._formatParameterAsObject):
+ Currently only object types are previewed. Though we request previews
+ for arrays, we don't use the preview because we show a better preview
+ by just immediately requesting for a full non-preview property list.
+
+ (WebInspector.ConsoleMessageImpl.prototype._appendObjectPreview):
+ Quickly output an object preview into the title element. The format
+ is "ClassName {prop: value...}". Elide the class name if it is "Object".
+ Also skip over certain preview properties that may not be useful
+ at a glance (like constructor, or accessors without values).
+
+ * UserInterface/Views/LogContentView.css:
+ (.console-object-preview):
+ (.console-formatted-array .console-object-preview):
+ (.console-object-preview-lossless):
+ (.expanded .console-object-preview):
+ Show lossy previews in italics.
+ Show lossless previews and array previews without italics.
+ Do not show the class name in the preview in italics when expanded.
+
+ (.console-object-preview .name):
+ Give preview property names the same color as ObjectPropertiesSection property names.
+
+ (.expanded .console-object-preview > .console-object-preview-body):
+ When expanding an object, hide the preview.
+
+ (.console-object-preview > .console-object-preview-name.console-object-preview-name-Object):
+ (.expanded .console-object-preview > .console-object-preview-name.console-object-preview-name-Object):
+ For "Object" previews, hide the name "Object" when not expanded, and show it when expanded.
+
</ins><span class="cx"> 2015-01-23 Saam Barati <saambarati1@gmail.com>
</span><span class="cx">
</span><span class="cx"> Web Inspector: Disable *Annotators on minified files that aren't pretty printed
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceControllersJavaScriptLogViewControllerjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/JavaScriptLogViewController.js (179018 => 179019)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Controllers/JavaScriptLogViewController.js        2015-01-23 20:03:41 UTC (rev 179018)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/JavaScriptLogViewController.js        2015-01-23 20:05:44 UTC (rev 179019)
</span><span class="lines">@@ -232,7 +232,7 @@
</span><span class="cx">
</span><span class="cx"> text += "\n//# sourceURL=__WebInspectorConsole__\n";
</span><span class="cx">
</span><del>- WebInspector.runtimeManager.evaluateInInspectedWindow(text, "console", true, false, false, printResult.bind(this));
</del><ins>+ WebInspector.runtimeManager.evaluateInInspectedWindow(text, "console", true, false, false, true, printResult.bind(this));
</ins><span class="cx"> },
</span><span class="cx">
</span><span class="cx"> // Private
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceControllersJavaScriptRuntimeCompletionProviderjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js (179018 => 179019)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js        2015-01-23 20:03:41 UTC (rev 179018)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js        2015-01-23 20:05:44 UTC (rev 179019)
</span><span class="lines">@@ -104,7 +104,7 @@
</span><span class="cx"> if (!base && activeCallFrame && !this._alwaysEvaluateInWindowContext)
</span><span class="cx"> activeCallFrame.collectScopeChainVariableNames(receivedPropertyNames.bind(this));
</span><span class="cx"> else
</span><del>- WebInspector.runtimeManager.evaluateInInspectedWindow(base, "completion", true, true, false, evaluated.bind(this));
</del><ins>+ WebInspector.runtimeManager.evaluateInInspectedWindow(base, "completion", true, true, false, false, evaluated.bind(this));
</ins><span class="cx">
</span><span class="cx"> function updateLastPropertyNames(propertyNames)
</span><span class="cx"> {
</span><span class="lines">@@ -155,7 +155,7 @@
</span><span class="cx"> if (result.type === "object" || result.type === "function")
</span><span class="cx"> result.callFunctionJSON(getCompletions, undefined, receivedPropertyNames.bind(this));
</span><span class="cx"> else if (result.type === "string" || result.type === "number" || result.type === "boolean")
</span><del>- WebInspector.runtimeManager.evaluateInInspectedWindow("(" + getCompletions + ")(\"" + result.type + "\")", "completion", false, true, true, receivedPropertyNamesFromEvaluate.bind(this));
</del><ins>+ WebInspector.runtimeManager.evaluateInInspectedWindow("(" + getCompletions + ")(\"" + result.type + "\")", "completion", false, true, true, false, receivedPropertyNamesFromEvaluate.bind(this));
</ins><span class="cx"> else
</span><span class="cx"> console.error("Unknown result type: " + result.type);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceControllersRuntimeManagerjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/RuntimeManager.js (179018 => 179019)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Controllers/RuntimeManager.js        2015-01-23 20:03:41 UTC (rev 179018)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/RuntimeManager.js        2015-01-23 20:05:44 UTC (rev 179019)
</span><span class="lines">@@ -41,7 +41,7 @@
</span><span class="cx">
</span><span class="cx"> // Public
</span><span class="cx">
</span><del>- evaluateInInspectedWindow: function(expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, callback)
</del><ins>+ evaluateInInspectedWindow: function(expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, generatePreview, callback)
</ins><span class="cx"> {
</span><span class="cx"> if (!expression) {
</span><span class="cx"> // There is no expression, so the completion should happen against global properties.
</span><span class="lines">@@ -51,7 +51,7 @@
</span><span class="cx"> function evalCallback(error, result, wasThrown)
</span><span class="cx"> {
</span><span class="cx"> this.dispatchEventToListeners(WebInspector.RuntimeManager.Event.DidEvaluate);
</span><del>-
</del><ins>+
</ins><span class="cx"> if (error) {
</span><span class="cx"> console.error(error);
</span><span class="cx"> callback(null, false);
</span><span class="lines">@@ -65,14 +65,16 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (WebInspector.debuggerManager.activeCallFrame) {
</span><del>- DebuggerAgent.evaluateOnCallFrame(WebInspector.debuggerManager.activeCallFrame.id, expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, evalCallback.bind(this));
</del><ins>+ // COMPATIBILITY (iOS 6): "generatePreview" did not exist.
+ DebuggerAgent.evaluateOnCallFrame.invoke({callFrameId: WebInspector.debuggerManager.activeCallFrame.id, expression: expression, objectGroup: objectGroup, includeCommandLineAPI: includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole: doNotPauseOnExceptionsAndMuteConsole, returnByValue: returnByValue, generatePreview: generatePreview}, evalCallback.bind(this));
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // COMPATIBILITY (iOS 6): Execution context identifiers (contextId) did not exist
</span><span class="cx"> // in iOS 6. Fallback to including the frame identifier (frameId).
</span><ins>+ // COMPATIBILITY (iOS 6): "generatePreview" did not exist.
</ins><span class="cx"> var contextId = WebInspector.quickConsole.executionContextIdentifier;
</span><del>- RuntimeAgent.evaluate.invoke({expression: expression, objectGroup: objectGroup, includeCommandLineAPI: includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole: doNotPauseOnExceptionsAndMuteConsole, contextId: contextId, frameId: contextId, returnByValue: returnByValue}, evalCallback.bind(this));
</del><ins>+ RuntimeAgent.evaluate.invoke({expression: expression, objectGroup: objectGroup, includeCommandLineAPI: includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole: doNotPauseOnExceptionsAndMuteConsole, contextId: contextId, frameId: contextId, returnByValue: returnByValue, generatePreview: generatePreview}, evalCallback.bind(this));
</ins><span class="cx"> },
</span><span class="cx">
</span><span class="cx"> getPropertiesForRemoteObject: function(objectId, callback)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceProtocolRemoteObjectjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Protocol/RemoteObject.js (179018 => 179019)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Protocol/RemoteObject.js        2015-01-23 20:03:41 UTC (rev 179018)
+++ trunk/Source/WebInspectorUI/UserInterface/Protocol/RemoteObject.js        2015-01-23 20:05:44 UTC (rev 179019)
</span><span class="lines">@@ -28,7 +28,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.RemoteObject = function(objectId, type, subtype, value, description)
</del><ins>+WebInspector.RemoteObject = function(objectId, type, subtype, value, description, preview)
</ins><span class="cx"> {
</span><span class="cx"> this._type = type;
</span><span class="cx"> this._subtype = subtype;
</span><span class="lines">@@ -37,6 +37,7 @@
</span><span class="cx"> this._objectId = objectId;
</span><span class="cx"> this._description = description;
</span><span class="cx"> this._hasChildren = true;
</span><ins>+ this._preview = preview;
</ins><span class="cx"> } else {
</span><span class="cx"> // Primitive or null object.
</span><span class="cx"> console.assert(type !== "object" || value === null);
</span><span class="lines">@@ -70,7 +71,7 @@
</span><span class="cx"> {
</span><span class="cx"> console.assert(typeof payload === "object", "Remote object payload should only be an object");
</span><span class="cx">
</span><del>- return new WebInspector.RemoteObject(payload.objectId, payload.type, payload.subtype, payload.value, payload.description);
</del><ins>+ return new WebInspector.RemoteObject(payload.objectId, payload.type, payload.subtype, payload.value, payload.description, payload.preview);
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> WebInspector.RemoteObject.type = function(remoteObject)
</span><span class="lines">@@ -111,6 +112,11 @@
</span><span class="cx"> return this._hasChildren;
</span><span class="cx"> },
</span><span class="cx">
</span><ins>+ get preview()
+ {
+ return this._preview;
+ },
+
</ins><span class="cx"> getOwnProperties: function(callback)
</span><span class="cx"> {
</span><span class="cx"> this._getProperties(true, false, callback);
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsConsoleMessageImpljs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleMessageImpl.js (179018 => 179019)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleMessageImpl.js        2015-01-23 20:03:41 UTC (rev 179018)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleMessageImpl.js        2015-01-23 20:05:44 UTC (rev 179019)
</span><span class="lines">@@ -237,14 +237,14 @@
</span><span class="cx"> if (shouldFormatMessage && parameters[i].type === "string")
</span><span class="cx"> formattedResult.appendChild(document.createTextNode(parameters[i].description));
</span><span class="cx"> else
</span><del>- formattedResult.appendChild(this._formatParameter(parameters[i]));
</del><ins>+ formattedResult.appendChild(this._formatParameter(parameters[i], false, true));
</ins><span class="cx"> if (i < parameters.length - 1)
</span><span class="cx"> formattedResult.appendChild(document.createTextNode(" "));
</span><span class="cx"> }
</span><span class="cx"> return formattedResult;
</span><span class="cx"> },
</span><span class="cx">
</span><del>- _formatParameter: function(output, forceObjectFormat)
</del><ins>+ _formatParameter: function(output, forceObjectFormat, includePreview)
</ins><span class="cx"> {
</span><span class="cx"> var type;
</span><span class="cx"> if (forceObjectFormat)
</span><span class="lines">@@ -262,7 +262,7 @@
</span><span class="cx">
</span><span class="cx"> var span = document.createElement("span");
</span><span class="cx"> span.className = "console-formatted-" + type + " source-code";
</span><del>- formatter.call(this, output, span);
</del><ins>+ formatter.call(this, output, span, includePreview);
</ins><span class="cx"> return span;
</span><span class="cx"> },
</span><span class="cx">
</span><span class="lines">@@ -271,11 +271,81 @@
</span><span class="cx"> elem.appendChild(document.createTextNode(val));
</span><span class="cx"> },
</span><span class="cx">
</span><del>- _formatParameterAsObject: function(obj, elem)
</del><ins>+ _formatParameterAsObject: function(obj, elem, includePreview)
</ins><span class="cx"> {
</span><del>- elem.appendChild(new WebInspector.ObjectPropertiesSection(obj, obj.description).element);
</del><ins>+ var titleElement = document.createElement("span");
+ if (includePreview && obj.preview) {
+ titleElement.classList.add("console-object-preview");
+ var lossless = this._appendObjectPreview(titleElement, obj);
+ if (lossless) {
+ titleElement.classList.add("console-object-preview-lossless");
+ elem.appendChild(titleElement);
+ return;
+ }
+ } else
+ titleElement.appendChild(document.createTextNode(obj.description || ""));
+
+ var section = new WebInspector.ObjectPropertiesSection(obj, titleElement);
+ elem.appendChild(section.element);
</ins><span class="cx"> },
</span><span class="cx">
</span><ins>+ _appendObjectPreview: function(titleElement, obj)
+ {
+ var preview = obj.preview;
+ var isArray = obj.subtype === "array";
+
+ if (obj.description && !isArray) {
+ var previewObjectNameElement = document.createElement("span");
+ previewObjectNameElement.classList.add("console-object-preview-name");
+ if (obj.description === "Object")
+ previewObjectNameElement.classList.add("console-object-preview-name-Object");
+
+ previewObjectNameElement.textContent = obj.description + " ";
+ titleElement.appendChild(previewObjectNameElement);
+ }
+
+ var bodyElement = titleElement.createChild("span", "console-object-preview-body");
+ bodyElement.appendChild(document.createTextNode(isArray ? "[" : "{"));
+ for (var i = 0; i < preview.properties.length; ++i) {
+ var property = preview.properties[i];
+
+ // FIXME: Better handle getter/setter accessors. Should we show getters in previews?
+ if (property.type === "accessor")
+ continue;
+
+ // Constructor name is often already visible, so don't show it as a property.
+ if (property.name === "constructor")
+ continue;
+
+ if (i > 0)
+ bodyElement.appendChild(document.createTextNode(", "));
+
+ if (!isArray || property.name != i) {
+ bodyElement.createChild("span", "name").textContent = property.name;
+ bodyElement.appendChild(document.createTextNode(": "));
+ }
+
+ var span = bodyElement.createChild("span", "console-formatted-" + property.type);
+ if (property.type === "object") {
+ if (property.subtype === "node")
+ span.classList.add("console-formatted-preview-node");
+ else if (property.subtype === "regexp")
+ span.classList.add("console-formatted-regexp");
+ }
+
+ if (property.type === "string")
+ span.textContent = "\"" + property.value + "\"";
+ else if (property.type === "function")
+ span.textContent = "function";
+ else
+ span.textContent = property.value;
+ }
+ if (preview.overflow)
+ bodyElement.createChild("span").textContent = "\u2026";
+ bodyElement.appendChild(document.createTextNode(isArray ? "]" : "}"));
+ return preview.lossless;
+ },
+
</ins><span class="cx"> _formatParameterAsNode: function(object, elem)
</span><span class="cx"> {
</span><span class="cx"> function printNode(nodeId)
</span><span class="lines">@@ -283,7 +353,7 @@
</span><span class="cx"> if (!nodeId) {
</span><span class="cx"> // Sometimes DOM is loaded after the sync message is being formatted, so we get no
</span><span class="cx"> // nodeId here. So we fall back to object formatting here.
</span><del>- this._formatParameterAsObject(object, elem);
</del><ins>+ this._formatParameterAsObject(object, elem, false);
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx"> var treeOutline = new WebInspector.DOMTreeOutline(false, false, true);
</span><span class="lines">@@ -299,6 +369,7 @@
</span><span class="cx">
</span><span class="cx"> _formatParameterAsArray: function(arr, elem)
</span><span class="cx"> {
</span><ins>+ // FIXME: Array previews look poor. Keep doing what we currently do for arrays.
</ins><span class="cx"> arr.getOwnProperties(this._printArray.bind(this, arr, elem));
</span><span class="cx"> },
</span><span class="cx">
</span><span class="lines">@@ -306,13 +377,12 @@
</span><span class="cx"> {
</span><span class="cx"> var span = document.createElement("span");
</span><span class="cx"> span.className = "console-formatted-string source-code";
</span><ins>+ span.appendChild(document.createTextNode("\""));
</ins><span class="cx"> span.appendChild(WebInspector.linkifyStringAsFragment(output.description));
</span><ins>+ span.appendChild(document.createTextNode("\""));
</ins><span class="cx">
</span><del>- // Make black quotes.
- elem.classList.remove("console-formatted-string");
- elem.appendChild(document.createTextNode("\""));
</del><ins>+ elem.classList.remove("console-formatted-string");
</ins><span class="cx"> elem.appendChild(span);
</span><del>- elem.appendChild(document.createTextNode("\""));
</del><span class="cx"> },
</span><span class="cx">
</span><span class="cx"> _printArray: function(array, elem, properties)
</span><span class="lines">@@ -363,7 +433,7 @@
</span><span class="cx"> _formatAsArrayEntry: function(output)
</span><span class="cx"> {
</span><span class="cx"> // Prevent infinite expansion of cross-referencing arrays.
</span><del>- return this._formatParameter(output, output.subtype && output.subtype === "array");
</del><ins>+ return this._formatParameter(output, output.subtype && output.subtype === "array", false);
</ins><span class="cx"> },
</span><span class="cx">
</span><span class="cx"> _formatWithSubstitutionString: function(parameters, formattedResult)
</span><span class="lines">@@ -372,7 +442,7 @@
</span><span class="cx">
</span><span class="cx"> function parameterFormatter(force, obj)
</span><span class="cx"> {
</span><del>- return this._formatParameter(obj, force);
</del><ins>+ return this._formatParameter(obj, force, false);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> function stringFormatter(obj)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsLogContentViewcss"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/LogContentView.css (179018 => 179019)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/LogContentView.css        2015-01-23 20:03:41 UTC (rev 179018)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/LogContentView.css        2015-01-23 20:05:44 UTC (rev 179019)
</span><span class="lines">@@ -267,6 +267,33 @@
</span><span class="cx"> display: none;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+.console-object-preview {
+ font-style: italic;
+}
+
+.console-object-preview-lossless,
+.console-formatted-array .console-object-preview,
+.expanded .console-object-preview {
+ font-style: normal;
+}
+
+.console-object-preview .name {
+ /* Match ObjectPropertiesSection name styles */
+ color: rgb(136, 19, 145);
+}
+
+.expanded .console-object-preview > .console-object-preview-body {
+ display: none;
+}
+
+.console-object-preview > .console-object-preview-name.console-object-preview-name-Object {
+ display: none;
+}
+
+.expanded .console-object-preview > .console-object-preview-name.console-object-preview-name-Object {
+ display: inline;
+}
+
</ins><span class="cx"> .console-formatted-object, .console-formatted-node, .console-formatted-error {
</span><span class="cx"> position: relative;
</span><span class="cx"> display: inline-block;
</span></span></pre>
</div>
</div>
</body>
</html>