<!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>[193204] branches/safari-601-branch</title>
</head>
<body>

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

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/189415">r189415</a>. rdar://problem/23221163</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari601branchLayoutTestsChangeLog">branches/safari-601-branch/LayoutTests/ChangeLog</a></li>
<li><a href="#branchessafari601branchSourceJavaScriptCoreChangeLog">branches/safari-601-branch/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchessafari601branchSourceJavaScriptCoreinspectorInjectedScriptSourcejs">branches/safari-601-branch/Source/JavaScriptCore/inspector/InjectedScriptSource.js</a></li>
<li><a href="#branchessafari601branchSourceWebInspectorUIChangeLog">branches/safari-601-branch/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#branchessafari601branchSourceWebInspectorUIUserInterfaceProtocolInspectorBackendjs">branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Protocol/InspectorBackend.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li>branches/safari-601-branch/LayoutTests/inspector/runtime/</li>
<li><a href="#branchessafari601branchLayoutTestsinspectorruntimeparsehtml">branches/safari-601-branch/LayoutTests/inspector/runtime/parse.html</a></li>
<li><a href="#branchessafari601branchLayoutTestsinspectorruntimesaveResultexpectedtxt">branches/safari-601-branch/LayoutTests/inspector/runtime/saveResult-expected.txt</a></li>
<li><a href="#branchessafari601branchLayoutTestsinspectorruntimesaveResulthtml">branches/safari-601-branch/LayoutTests/inspector/runtime/saveResult.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari601branchLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/LayoutTests/ChangeLog (193203 => 193204)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/ChangeLog        2015-12-03 18:57:20 UTC (rev 193203)
+++ branches/safari-601-branch/LayoutTests/ChangeLog        2015-12-03 18:57:27 UTC (rev 193204)
</span><span class="lines">@@ -1,5 +1,20 @@
</span><span class="cx"> 2015-12-02  Timothy Hatcher  &lt;timothy@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r189415. rdar://problem/23221163
+
+    2015-09-04  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+            Web Inspector: Test Runtime.saveResult and $n values
+            https://bugs.webkit.org/show_bug.cgi?id=148837
+
+            Reviewed by Timothy Hatcher.
+
+            * inspector/runtime/parse.html: Remove unncessary debug flag.
+            * inspector/runtime/saveResult-expected.txt: Added.
+            * inspector/runtime/saveResult.html: Added.
+
+2015-12-02  Timothy Hatcher  &lt;timothy@apple.com&gt;
+
</ins><span class="cx">         Merge r189373. rdar://problem/23221163
</span><span class="cx"> 
</span><span class="cx">     2015-09-04  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari601branchLayoutTestsinspectorruntimeparsehtml"></a>
<div class="addfile"><h4>Added: branches/safari-601-branch/LayoutTests/inspector/runtime/parse.html (0 => 193204)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/inspector/runtime/parse.html                                (rev 0)
+++ branches/safari-601-branch/LayoutTests/inspector/runtime/parse.html        2015-12-03 18:57:27 UTC (rev 193204)
</span><span class="lines">@@ -0,0 +1,190 @@
</span><ins>+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../http/tests/inspector/resources/inspector-test.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+function test()
+{
+    function outputErrorSourceRange(range) {
+        var str = &quot; &quot;.repeat(&quot;Source: &quot;.length);
+        str += &quot; &quot;.repeat(range.startOffset);
+        str += &quot;^&quot;;
+        str += &quot;~&quot;.repeat(range.endOffset - range.startOffset - 1);
+        InspectorTest.log(str);
+    }
+
+    let suite = InspectorTest.createAsyncSuite(&quot;Runtime.parse&quot;);
+
+    suite.addTestCase({
+        name: &quot;SyntaxErrorType.None&quot;,
+        description: &quot;Test source without an issue.&quot;,
+        test: (resolve, reject) =&gt; {
+            function testSource(source) {
+                RuntimeAgent.parse(source, (error, result, message, range) =&gt; {
+                    InspectorTest.assert(!error, &quot;Should not be a protocol error.&quot;);
+                    InspectorTest.expectThat(result === RuntimeAgent.SyntaxErrorType.None, &quot;Should be SyntaxErrorType None.&quot;);
+                    InspectorTest.log(&quot;Source: &quot; + source);
+                    InspectorTest.assert(!message);
+                    InspectorTest.assert(!range);
+                    InspectorTest.log(&quot;&quot;);
+                });
+            }
+
+            // Complete programs without syntax errors (could have runtime errors).
+            testSource(&quot;&quot;);
+            testSource(&quot;;&quot;);
+            testSource(&quot;myVariable&quot;);
+            testSource(&quot;var x = 1; x&quot;);
+            testSource(&quot;[1,2,3]&quot;);
+            testSource(&quot;({})&quot;);
+            testSource(&quot;({prop:true}).x.x.x&quot;);
+            testSource(&quot;if(1)1&quot;);
+            InspectorBackend.runAfterPendingDispatches(resolve);
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;SyntaxErrorType.UnterminatedLiteral&quot;,
+        description: &quot;Test source with an unterminated literal.&quot;,
+        test: (resolve, reject) =&gt; {
+            function testSource(source) {
+                RuntimeAgent.parse(source, (error, result, message, range) =&gt; {
+                    InspectorTest.assert(!error, &quot;Should not be a protocol error.&quot;);
+                    InspectorTest.expectThat(result === RuntimeAgent.SyntaxErrorType.UnterminatedLiteral, &quot;Should be SyntaxErrorType UnterminatedLiteral.&quot;);
+                    InspectorTest.log(&quot;Source: &quot; + source);
+                    outputErrorSourceRange(range);
+                    InspectorTest.log(&quot;Error Message: &quot; + message);
+                    InspectorTest.log(&quot;Range: &quot; + JSON.stringify(range));
+                    InspectorTest.log(&quot;&quot;);
+                });
+            }
+
+            // A literal that is not yet complete, but would be a single token.
+            testSource(&quot;0b&quot;); // binary
+            testSource(&quot;0o&quot;); // octal
+            testSource(&quot;0x&quot;); // hex
+            testSource(&quot;1e&quot;); // scientific notation number
+            testSource(&quot;'&quot;);  // string
+            testSource(&quot;\&quot;&quot;); // string
+            testSource(&quot;var \\u007&quot;); // identifier unicode escape
+            // testSource(&quot;/r&quot;); // regexp - Not detected by JavaScriptCore.
+            InspectorBackend.runAfterPendingDispatches(resolve);
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;SyntaxErrorType.Recoverable&quot;,
+        description: &quot;Test source with a recoverable error.&quot;,
+        test: (resolve, reject) =&gt; {
+            function testSource(source) {
+                RuntimeAgent.parse(source, (error, result, message, range) =&gt; {
+                    InspectorTest.assert(!error, &quot;Should not be a protocol error.&quot;);
+                    InspectorTest.expectThat(result === RuntimeAgent.SyntaxErrorType.Recoverable, &quot;Should be SyntaxErrorType Recoverable.&quot;);
+                    InspectorTest.log(&quot;Source: &quot; + source);
+                    outputErrorSourceRange(range);
+                    InspectorTest.log(&quot;Error Message: &quot; + message);
+                    InspectorTest.log(&quot;Error Range: &quot; + JSON.stringify(range));
+                    InspectorTest.log(&quot;&quot;);
+                });
+            }
+
+            // Not yet a syntax error, just an incomplete program.
+            testSource(&quot;(&quot;);
+            testSource(&quot;{&quot;);
+            testSource(&quot;!&quot;);
+            testSource(&quot;-&quot;); // unary
+            testSource(&quot;+&quot;); // unary
+            testSource(&quot;~&quot;); // unary
+            testSource(&quot;1,&quot;);
+            testSource(&quot;var&quot;);
+            testSource(&quot;'use strict'; let&quot;); // When not in strict mode, let is treated as the start of an identifier, not a keyword!
+            testSource(&quot;const&quot;);
+            testSource(&quot;var {x&quot;); // destructuring
+            testSource(&quot;var [x&quot;); // destructuring
+            testSource(&quot;var x,&quot;);
+            testSource(&quot;if(1)&quot;);
+            testSource(&quot;if(1){&quot;);
+            testSource(&quot;if(1){}else&quot;);
+            testSource(&quot;if(1){}else{&quot;);
+            testSource(&quot;while(1)&quot;);
+            testSource(&quot;while(1){&quot;);
+            testSource(&quot;for(;;)&quot;);
+            testSource(&quot;for(;;){&quot;);
+            testSource(&quot;()=&gt;&quot;);  // arrow function
+            testSource(&quot;()=&gt;{&quot;); // arrow function
+            testSource(&quot;/*&quot;);    // comment
+            testSource(&quot;`&quot;);     // template string
+            testSource(&quot;`${1}&quot;); // template string
+            testSource(&quot;`${&quot;);   // template string
+            testSource(&quot;function&quot;);
+            testSource(&quot;function foo&quot;);
+            testSource(&quot;function foo(&quot;);
+            testSource(&quot;function foo(){&quot;);
+            testSource(&quot;(function() {&quot;);
+            testSource(&quot;(function() {}&quot;);
+            testSource(&quot;(function() {})(&quot;);
+            testSource(&quot;switch(x)&quot;);
+            testSource(&quot;switch(x){&quot;);
+            testSource(&quot;switch(x){case&quot;);
+            testSource(&quot;switch(x){case 1&quot;);
+            testSource(&quot;switch(x){case 1:&quot;);
+            testSource(&quot;class&quot;);
+            testSource(&quot;class Klass&quot;);
+            testSource(&quot;class Klass {&quot;);
+            testSource(&quot;var x = {&quot;);
+            testSource(&quot;var x = {prop&quot;);
+            testSource(&quot;var x = {prop:&quot;);
+            testSource(&quot;var x = {prop:123&quot;);
+            testSource(&quot;var x = {prop:123 &quot;);
+            testSource(&quot;var x = {prop:123,&quot;);
+            testSource(&quot;var x = {prop:123, &quot;);
+            testSource(&quot;var x = {prop:123, 'prop2'&quot;);
+            testSource(&quot;var x = {prop:123, [12&quot;);
+            testSource(&quot;var x = {prop:123, [12]&quot;);
+            testSource(&quot;var x = {prop:123, [12]:&quot;);
+            testSource(&quot;var x = {prop:123, [12]:567&quot;);
+            testSource(&quot;var x = [&quot;);
+            testSource(&quot;var x = [1&quot;);
+            testSource(&quot;var x = [1,&quot;);
+            testSource(&quot;var x = [1,[]&quot;);
+            testSource(&quot;var x = [1,{}&quot;);
+            InspectorBackend.runAfterPendingDispatches(resolve);
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;SyntaxErrorType.Irrecoverable&quot;,
+        description: &quot;Test source with an irrecoverable issue.&quot;,
+        test: (resolve, reject) =&gt; {
+            function testSource(source) {
+                RuntimeAgent.parse(source, (error, result, message, range) =&gt; {
+                    InspectorTest.assert(!error, &quot;Should not be a protocol error.&quot;);
+                    InspectorTest.expectThat(result === RuntimeAgent.SyntaxErrorType.Irrecoverable, &quot;Should be SyntaxErrorType Irrecoverable.&quot;);
+                    InspectorTest.log(&quot;Source: &quot; + source);
+                    outputErrorSourceRange(range);
+                    InspectorTest.log(&quot;Error Message: &quot; + message);
+                    InspectorTest.log(&quot;Error Range: &quot; + JSON.stringify(range));
+                    InspectorTest.log(&quot;&quot;);
+                });
+            }
+
+            // SyntaxErrors. Any typing after the syntax error is detected does not matter.
+            testSource(&quot;1$&quot;);
+            testSource(&quot;var x = {}}&quot;);
+            testSource(&quot;({}))&quot;);
+            testSource(&quot;var x = =&quot;);
+            testSource(&quot;const x;&quot;);
+            testSource(&quot;let x = 1; let x = 2;&quot;);
+            testSource(&quot;if x(1)&quot;);
+            InspectorBackend.runAfterPendingDispatches(resolve);
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runTest()&quot;&gt;
+&lt;p&gt;Tests for the Runtime.parse command.&lt;/p&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="branchessafari601branchLayoutTestsinspectorruntimesaveResultexpectedtxt"></a>
<div class="addfile"><h4>Added: branches/safari-601-branch/LayoutTests/inspector/runtime/saveResult-expected.txt (0 => 193204)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/inspector/runtime/saveResult-expected.txt                                (rev 0)
+++ branches/safari-601-branch/LayoutTests/inspector/runtime/saveResult-expected.txt        2015-12-03 18:57:27 UTC (rev 193204)
</span><span class="lines">@@ -0,0 +1,36 @@
</span><ins>+Tests for the Runtime.saveResult command ($n values).
+
+
+== Running test suite: Runtime.saveResult
+-- Running test case: SavePrimitiveValue1
+PASS: Value 123 should become $1.
+
+-- Running test case: SavePrimitiveValue2
+PASS: Value true should become $2.
+
+-- Running test case: RepeatPrimitiveValue1
+PASS: Value 123 should have existed as $1.
+
+-- Running test case: $1MatchesValue1
+PASS: $1 value should be 123.
+
+-- Running test case: SaveObject1
+PASS: New Object {&quot;x&quot;:100,&quot;y&quot;:200} should become $3.
+
+-- Running test case: SaveObject2
+PASS: New Object {&quot;x&quot;:100,&quot;y&quot;:200} should become $4.
+
+-- Running test case: RepeatSaveObject1
+PASS: Repeat Object should have existed as $3.
+
+-- Running test case: NoContextWithPrimitiveShouldUseMainContext
+PASS: Value 999 should become $5.
+PASS: Value 999 should have existed as $5.
+
+-- Running test case: ClearConsoleShouldResetValues
+PASS: Value 999 should become $1.
+
+-- Running test case: EvaluateWithSaveIndex
+PASS: Evaluated result 990 should become $2.
+PASS: Evaluated result 999 should match previous value $1.
+
</ins></span></pre></div>
<a id="branchessafari601branchLayoutTestsinspectorruntimesaveResulthtml"></a>
<div class="addfile"><h4>Added: branches/safari-601-branch/LayoutTests/inspector/runtime/saveResult.html (0 => 193204)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/inspector/runtime/saveResult.html                                (rev 0)
+++ branches/safari-601-branch/LayoutTests/inspector/runtime/saveResult.html        2015-12-03 18:57:27 UTC (rev 193204)
</span><span class="lines">@@ -0,0 +1,181 @@
</span><ins>+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../http/tests/inspector/resources/inspector-test.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+function test()
+{
+    function createCallArgumentWithValue(value) {
+        return {value};
+    }
+
+    function createCallArgumentWithRemoteObject(remoteObject) {
+        return {objectId: remoteObject.objectId};
+    }
+
+    function remoteObjectForSimpleObject(simpleObject, callback) {
+        InspectorTest.evaluateInPage(&quot;(&quot; + JSON.stringify(simpleObject) + &quot;)&quot;, callback);
+    }
+
+    let contextId = WebInspector.frameResourceManager.mainFrame.pageExecutionContext.id;
+    let remoteObject1;
+
+    let suite = InspectorTest.createAsyncSuite(&quot;Runtime.saveResult&quot;);
+
+    suite.addTestCase({
+        name: &quot;SavePrimitiveValue1&quot;,
+        description: &quot;Saving a new value should produce a new $n value.&quot;,
+        test: (resolve, reject) =&gt; {
+            let value = 123;
+            RuntimeAgent.saveResult(createCallArgumentWithValue(value), contextId, (error, savedResultIndex) =&gt; {
+                InspectorTest.assert(!error, &quot;Should not be a protocol error.&quot;);
+                InspectorTest.expectThat(savedResultIndex === 1, `Value ${value} should become $1.`);
+                resolve();
+            });
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;SavePrimitiveValue2&quot;,
+        description: &quot;Saving a new value should produce a new $n value.&quot;,
+        test: (resolve, reject) =&gt; {
+            let value = true;
+            RuntimeAgent.saveResult(createCallArgumentWithValue(value), contextId, (error, savedResultIndex) =&gt; {
+                InspectorTest.assert(!error, &quot;Should not be a protocol error.&quot;);
+                InspectorTest.expectThat(savedResultIndex === 2, `Value ${value} should become $2.`);
+                resolve();
+            });
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;RepeatPrimitiveValue1&quot;,
+        description: &quot;Saving a previously saved value should produce the original $n value.&quot;,
+        test: (resolve, reject) =&gt; {
+            let value = 123;
+            RuntimeAgent.saveResult(createCallArgumentWithValue(value), contextId, (error, savedResultIndex) =&gt; {
+                InspectorTest.assert(!error, &quot;Should not be a protocol error.&quot;);
+                InspectorTest.expectThat(savedResultIndex === 1, `Value ${value} should have existed as $1.`);
+                resolve();
+            });
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;$1MatchesValue1&quot;,
+        description: &quot;Evaluating $1 should get us the value we saved previously.&quot;,
+        test: (resolve, reject) =&gt; {
+            RuntimeAgent.evaluate.invoke({expression: &quot;$1&quot;, objectGroup: &quot;test&quot;, includeCommandLineAPI: true}, (error, remoteObjectPayload, wasThrown, savedResultIndex) =&gt; {
+                InspectorTest.assert(!error, &quot;Should not be a protocol error.&quot;);
+                let remoteObject = WebInspector.RemoteObject.fromPayload(remoteObjectPayload);
+                InspectorTest.assert(remoteObject.hasValue(), &quot;RemoteObject for $1 should be a value, not an object.&quot;);
+                InspectorTest.expectThat(remoteObject.value === 123, &quot;$1 value should be 123.&quot;);
+                resolve();
+            });
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;SaveObject1&quot;,
+        description: &quot;Saving a new object should produce a new $n value.&quot;,
+        test: (resolve, reject) =&gt; {
+            let object = {x:100, y:200};
+            remoteObjectForSimpleObject(object, (error, remoteObject) =&gt; {
+                remoteObject1 = remoteObject;
+                RuntimeAgent.saveResult(createCallArgumentWithRemoteObject(remoteObject), (error, savedResultIndex) =&gt; {
+                    InspectorTest.assert(!error, &quot;Should not be a protocol error.&quot;);
+                    InspectorTest.expectThat(savedResultIndex === 3, `New Object ${JSON.stringify(object)} should become $3.`);
+                    resolve();
+                });
+            });
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;SaveObject2&quot;,
+        description: &quot;Saving a new object should produce a new $n value.&quot;,
+        test: (resolve, reject) =&gt; {
+            let object = {x:100, y:200};
+            remoteObjectForSimpleObject(object, (error, remoteObject) =&gt; {
+                RuntimeAgent.saveResult(createCallArgumentWithRemoteObject(remoteObject), (error, savedResultIndex) =&gt; {
+                    InspectorTest.assert(!error, &quot;Should not be a protocol error.&quot;);
+                    InspectorTest.expectThat(savedResultIndex === 4, `New Object ${JSON.stringify(object)} should become $4.`);
+                    resolve();
+                });
+            });
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;RepeatSaveObject1&quot;,
+        description: &quot;Saving a previously saved value should produce the original $n value.&quot;,
+        test: (resolve, reject) =&gt; {
+            RuntimeAgent.saveResult(createCallArgumentWithRemoteObject(remoteObject1), (error, savedResultIndex) =&gt; {
+                InspectorTest.assert(!error, &quot;Should not be a protocol error.&quot;);
+                InspectorTest.expectThat(savedResultIndex === 3, `Repeat Object should have existed as $3.`);
+                resolve();
+            });
+        }
+    });
+
+    // ------
+
+    suite.addTestCase({
+        name: &quot;NoContextWithPrimitiveShouldUseMainContext&quot;,
+        description: &quot;Saving a primitive should specify the context.&quot;,
+        test: (resolve, reject) =&gt; {
+            let value = 999;
+            RuntimeAgent.saveResult(createCallArgumentWithValue(value), (error, savedResultIndex) =&gt; {
+                InspectorTest.assert(!error, &quot;Should not be a protocol error.&quot;);
+                InspectorTest.expectThat(savedResultIndex === 5, `Value ${value} should become $5.`);
+            });
+            RuntimeAgent.saveResult(createCallArgumentWithValue(value), contextId, (error, savedResultIndex) =&gt; {
+                InspectorTest.assert(!error, &quot;Should not be a protocol error.&quot;);
+                InspectorTest.expectThat(savedResultIndex === 5, `Value ${value} should have existed as $5.`);
+                resolve();
+            });
+        }
+    });
+
+    // ------
+
+    suite.addTestCase({
+        name: &quot;ClearConsoleShouldResetValues&quot;,
+        description: &quot;Clearing the console should reset the $n values.&quot;,
+        test: (resolve, reject) =&gt; {
+            let value = 999;
+            ConsoleAgent.clearMessages();
+            RuntimeAgent.saveResult(createCallArgumentWithValue(value), (error, savedResultIndex) =&gt; {
+                InspectorTest.assert(!error, &quot;Should not be a protocol error.&quot;);
+                InspectorTest.expectThat(savedResultIndex === 1, `Value ${value} should become $1.`);
+                resolve();
+            });
+        }
+    });
+
+    // ------
+
+    suite.addTestCase({
+        name: &quot;EvaluateWithSaveIndex&quot;,
+        description: &quot;Evalute with the saveIndex option should affect $n.&quot;,
+        test: (resolve, reject) =&gt; {
+            RuntimeAgent.evaluate.invoke({expression: &quot;900 + 90&quot;, objectGroup: &quot;test&quot;, includeCommandLineAPI: true, saveResult: true}, (error, remoteObjectPayload, wasThrown, savedResultIndex) =&gt; {
+                InspectorTest.assert(!error, &quot;Should not be a protocol error.&quot;);
+                InspectorTest.expectThat(savedResultIndex === 2, &quot;Evaluated result 990 should become $2.&quot;);
+            });
+            RuntimeAgent.evaluate.invoke({expression: &quot;$2 + 9&quot;, objectGroup: &quot;test&quot;, includeCommandLineAPI: true, saveResult: true}, (error, remoteObjectPayload, wasThrown, savedResultIndex) =&gt; {
+                InspectorTest.assert(!error, &quot;Should not be a protocol error.&quot;);
+                InspectorTest.expectThat(savedResultIndex === 1, &quot;Evaluated result 999 should match previous value $1.&quot;);
+                resolve();
+            });
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runTest()&quot;&gt;
+&lt;p&gt;Tests for the Runtime.saveResult command ($n values).&lt;/p&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="branchessafari601branchSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/JavaScriptCore/ChangeLog (193203 => 193204)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/JavaScriptCore/ChangeLog        2015-12-03 18:57:20 UTC (rev 193203)
+++ branches/safari-601-branch/Source/JavaScriptCore/ChangeLog        2015-12-03 18:57:27 UTC (rev 193204)
</span><span class="lines">@@ -1,5 +1,23 @@
</span><span class="cx"> 2015-12-02  Timothy Hatcher  &lt;timothy@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r189415. rdar://problem/23221163
+
+    2015-09-04  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+            Web Inspector: Test Runtime.saveResult and $n values
+            https://bugs.webkit.org/show_bug.cgi?id=148837
+
+            Reviewed by Timothy Hatcher.
+
+            * inspector/InjectedScriptSource.js:
+            (InjectedScript.prototype._evaluateOn):
+            We don't need to be in the console object group to put the value
+            in the saved results list. That strong reference will ensure $n
+            values are always alive even if other object groups were used
+            when creating and subsequently released.
+
+2015-12-02  Timothy Hatcher  &lt;timothy@apple.com&gt;
+
</ins><span class="cx">         Merge r189373. rdar://problem/23221163
</span><span class="cx"> 
</span><span class="cx">     2015-09-04  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari601branchSourceJavaScriptCoreinspectorInjectedScriptSourcejs"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/JavaScriptCore/inspector/InjectedScriptSource.js (193203 => 193204)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/JavaScriptCore/inspector/InjectedScriptSource.js        2015-12-03 18:57:20 UTC (rev 193203)
+++ branches/safari-601-branch/Source/JavaScriptCore/inspector/InjectedScriptSource.js        2015-12-03 18:57:27 UTC (rev 193204)
</span><span class="lines">@@ -487,7 +487,7 @@
</span><span class="cx">             var expressionFunction = evalFunction.call(object, boundExpressionFunctionString);
</span><span class="cx">             var result = expressionFunction.apply(null, parameters);
</span><span class="cx"> 
</span><del>-            if (objectGroup === &quot;console&quot; &amp;&amp; saveResult)
</del><ins>+            if (saveResult)
</ins><span class="cx">                 this._saveResult(result);
</span><span class="cx"> 
</span><span class="cx">             return result;
</span><span class="lines">@@ -507,7 +507,7 @@
</span><span class="cx"> 
</span><span class="cx">             var result = evalFunction.call(inspectedGlobalObject, expression);
</span><span class="cx"> 
</span><del>-            if (objectGroup === &quot;console&quot; &amp;&amp; saveResult)
</del><ins>+            if (saveResult)
</ins><span class="cx">                 this._saveResult(result);
</span><span class="cx"> 
</span><span class="cx">             return result;
</span></span></pre></div>
<a id="branchessafari601branchSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebInspectorUI/ChangeLog (193203 => 193204)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebInspectorUI/ChangeLog        2015-12-03 18:57:20 UTC (rev 193203)
+++ branches/safari-601-branch/Source/WebInspectorUI/ChangeLog        2015-12-03 18:57:27 UTC (rev 193204)
</span><span class="lines">@@ -1,5 +1,26 @@
</span><span class="cx"> 2015-12-02  Timothy Hatcher  &lt;timothy@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r189415. rdar://problem/23221163
+
+    2015-09-04  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+            Web Inspector: Test Runtime.saveResult and $n values
+            https://bugs.webkit.org/show_bug.cgi?id=148837
+
+            Reviewed by Timothy Hatcher.
+
+            * UserInterface/Protocol/InspectorBackend.js:
+            (InspectorBackendClass):
+            Initialize the dump logging function different if we are in tests or not.
+            When in tests, using console.log as well as dumping system activity to
+            the system console results in an infinite loop of logging!
+
+            (InspectorBackendClass.prototype.dispatch):
+            (InspectorBackendClass.prototype._sendCommandToBackendWithCallback):
+            Use the logging function we figured out earlier.
+
+2015-12-02  Timothy Hatcher  &lt;timothy@apple.com&gt;
+
</ins><span class="cx">         Merge r189385. rdar://problem/23221163
</span><span class="cx"> 
</span><span class="cx">     2015-09-04  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari601branchSourceWebInspectorUIUserInterfaceProtocolInspectorBackendjs"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Protocol/InspectorBackend.js (193203 => 193204)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Protocol/InspectorBackend.js        2015-12-03 18:57:20 UTC (rev 193203)
+++ branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Protocol/InspectorBackend.js        2015-12-03 18:57:27 UTC (rev 193204)
</span><span class="lines">@@ -43,6 +43,8 @@
</span><span class="cx">         this.dumpInspectorProtocolMessages = false;
</span><span class="cx">         this.warnForLongMessageHandling = false;
</span><span class="cx">         this.longMessageHandlingThreshold = 10; // milliseconds.
</span><ins>+
+        this._log = window.InspectorTest ? InspectorFrontendHost.unbufferedLog.bind(InspectorFrontendHost) : console.log.bind(console);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Public
</span><span class="lines">@@ -77,7 +79,7 @@
</span><span class="cx">     dispatch(message)
</span><span class="cx">     {
</span><span class="cx">         if (this.dumpInspectorProtocolMessages)
</span><del>-            console.log(&quot;backend: &quot; + ((typeof message === &quot;string&quot;) ? message : JSON.stringify(message)));
</del><ins>+            this._log(&quot;backend: &quot; + ((typeof message === &quot;string&quot;) ? message : JSON.stringify(message)));
</ins><span class="cx"> 
</span><span class="cx">         var messageObject = (typeof message === &quot;string&quot;) ? JSON.parse(message) : message;
</span><span class="cx"> 
</span><span class="lines">@@ -173,7 +175,7 @@
</span><span class="cx">     {
</span><span class="cx">         var stringifiedMessage = JSON.stringify(messageObject);
</span><span class="cx">         if (this.dumpInspectorProtocolMessages)
</span><del>-            console.log(&quot;frontend: &quot; + stringifiedMessage);
</del><ins>+            this._log(&quot;frontend: &quot; + stringifiedMessage);
</ins><span class="cx"> 
</span><span class="cx">         InspectorFrontendHost.sendMessageToBackend(stringifiedMessage);
</span><span class="cx">     }
</span></span></pre>
</div>
</div>

</body>
</html>