<!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>[188639] 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/188639">188639</a></dd>
<dt>Author</dt> <dd>bburg@apple.com</dd>
<dt>Date</dt> <dd>2015-08-19 09:14:04 -0700 (Wed, 19 Aug 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: split TestStub.js into multiple files and modernize it
https://bugs.webkit.org/show_bug.cgi?id=148077

Reviewed by Timothy Hatcher.
Source/WebInspectorUI:

Since we want to share files between the two harnesses, split some of the parts
into different files so not everything has to be included at once.

Rename InjectedTestHarness to just TestHarness. Update some code to use
ES6 features where appropriate. Put test classes into Test/ directory.

* UserInterface/Base/TestStub.js: Removed.
* UserInterface/Test.html:
* UserInterface/Test/InspectorProtocol.js: Added.
(InspectorProtocol.sendCommand):
(InspectorProtocol.awaitCommand):
(InspectorProtocol.awaitEvent.):
(InspectorProtocol.awaitEvent):
(InspectorProtocol.addEventListener):
(InspectorProtocol.sendMessage):
(InspectorProtocol.checkForError):
(InspectorProtocol.dispatchMessageFromBackend):
* UserInterface/Test/ProtocolTestHarness.js: Added.
(ProtocolTestHarness.prototype.completeTest):
(ProtocolTestHarness.prototype.addResult):
(ProtocolTestHarness.prototype.debugLog):
(ProtocolTestHarness.prototype.evaluateInPage):
(ProtocolTestHarness):
* UserInterface/Test/Test.js: Renamed from Source/WebInspectorUI/UserInterface/Base/Test.js.
(WebInspector.loaded):
(WebInspector.contentLoaded):
(WebInspector.UIString):
(WebInspector.updateDockedState):
(WebInspector.updateDockingAvailability):
(InspectorTest.EventDispatcher.prototype.dispatchEvent):
(InspectorTest.EventDispatcher):
(InspectorTest.log):
(InspectorTest.assert):
(InspectorTest.expectThat):
(InspectorTest.debugLog):
(InspectorTest.expectNoError):
(InspectorTest.completeTest):
(InspectorTest.evaluateInPage):
(InspectorTest.addResult):
(InspectorTest._resendResults):
(InspectorTest.testPageDidLoad):
(InspectorTest.reloadPage):
(InspectorTest.reportUncaughtException):
* UserInterface/Test/TestHarness.js: Added.
(TestHarness):
(TestHarness.prototype.completeTest):
(TestHarness.prototype.addResult):
(TestHarness.prototype.debugLog):
(TestHarness.prototype.evaluateInPage):
(TestHarness.prototype.createAsyncSuite):
(TestHarness.prototype.createSyncSuite):
(TestHarness.prototype.get logCount):
(TestHarness.prototype.log):
(TestHarness.prototype.assert):
(TestHarness.prototype.expectThat):
* UserInterface/Test/TestStub.js: Added.
* UserInterface/Test/TestSuite.js: Added.
(TestSuite):
(TestSuite.prototype.runTestCasesAndFinish):
(TestSuite.prototype.runTestCases):
(TestSuite.prototype.get passCount):
(TestSuite.prototype.get skipCount):
(TestSuite.prototype.addTestCase):
(AsyncTestSuite.prototype.runTestCasesAndFinish.finish):
(AsyncTestSuite.prototype.runTestCasesAndFinish):
(AsyncTestSuite.prototype.runTestCases):
(AsyncTestSuite):
(SyncTestSuite.prototype.runTestCasesAndFinish):
(SyncTestSuite.prototype.runTestCases):
(SyncTestSuite):
* UserInterface/TestStub.html:

LayoutTests:

Add the prefix 'TestPage' to everything in protocol-test.js. Continue
exporting it to the global namespace for backwards compatibility, too.

Rename some things to match changes in the test harness. Tighten up
preconditions for test suite and test case names. Sprinkle some ES6.

* http/tests/inspector/dom/resources/InspectorDOMListener.js:
* http/tests/inspector/resources/console-test.js:
* http/tests/inspector/resources/probe-test.js:
* http/tests/inspector/resources/protocol-test.js:
(TestPage.registerInitializer):
(TestPage.debugLog.window.debugLog):
(TestPage.log.window.log):
(TestPage.closeTest.window.closeTest):
(TestPage.runTest.window.runTest):
(ProtocolTestProxy.registerInitializer): Deleted.
(debugLog): Deleted.
(log): Deleted.
(closeTest): Deleted.
(runTest): Deleted.
* inspector/dom/resources/dom-search-queries.js:
* inspector/unit-tests/async-test-suite.html:
* inspector/unit-tests/sync-test-suite.html:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestshttptestsinspectordomresourcesInspectorDOMListenerjs">trunk/LayoutTests/http/tests/inspector/dom/resources/InspectorDOMListener.js</a></li>
<li><a href="#trunkLayoutTestshttptestsinspectorresourcesconsoletestjs">trunk/LayoutTests/http/tests/inspector/resources/console-test.js</a></li>
<li><a href="#trunkLayoutTestshttptestsinspectorresourcesprobetestjs">trunk/LayoutTests/http/tests/inspector/resources/probe-test.js</a></li>
<li><a href="#trunkLayoutTestshttptestsinspectorresourcesprotocoltestjs">trunk/LayoutTests/http/tests/inspector/resources/protocol-test.js</a></li>
<li><a href="#trunkLayoutTestsinspectordomresourcesdomsearchqueriesjs">trunk/LayoutTests/inspector/dom/resources/dom-search-queries.js</a></li>
<li><a href="#trunkLayoutTestsinspectorunittestsasynctestsuiteexpectedtxt">trunk/LayoutTests/inspector/unit-tests/async-test-suite-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectorunittestsasynctestsuitehtml">trunk/LayoutTests/inspector/unit-tests/async-test-suite.html</a></li>
<li><a href="#trunkLayoutTestsinspectorunittestssynctestsuiteexpectedtxt">trunk/LayoutTests/inspector/unit-tests/sync-test-suite-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectorunittestssynctestsuitehtml">trunk/LayoutTests/inspector/unit-tests/sync-test-suite.html</a></li>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceTesthtml">trunk/Source/WebInspectorUI/UserInterface/Test.html</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceTestStubhtml">trunk/Source/WebInspectorUI/UserInterface/TestStub.html</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li>trunk/Source/WebInspectorUI/UserInterface/Test/</li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceTestInspectorProtocoljs">trunk/Source/WebInspectorUI/UserInterface/Test/InspectorProtocol.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceTestProtocolTestHarnessjs">trunk/Source/WebInspectorUI/UserInterface/Test/ProtocolTestHarness.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceTestTestjs">trunk/Source/WebInspectorUI/UserInterface/Test/Test.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceTestTestHarnessjs">trunk/Source/WebInspectorUI/UserInterface/Test/TestHarness.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceTestTestStubjs">trunk/Source/WebInspectorUI/UserInterface/Test/TestStub.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceTestTestSuitejs">trunk/Source/WebInspectorUI/UserInterface/Test/TestSuite.js</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceBaseTestjs">trunk/Source/WebInspectorUI/UserInterface/Base/Test.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceBaseTestStubjs">trunk/Source/WebInspectorUI/UserInterface/Base/TestStub.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (188638 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-08-19 15:38:14 UTC (rev 188638)
+++ trunk/LayoutTests/ChangeLog        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -1,3 +1,34 @@
</span><ins>+2015-08-19  Brian Burg  &lt;bburg@apple.com&gt;
+
+        Web Inspector: split TestStub.js into multiple files and modernize it
+        https://bugs.webkit.org/show_bug.cgi?id=148077
+
+        Reviewed by Timothy Hatcher.
+
+        Add the prefix 'TestPage' to everything in protocol-test.js. Continue
+        exporting it to the global namespace for backwards compatibility, too.
+
+        Rename some things to match changes in the test harness. Tighten up
+        preconditions for test suite and test case names. Sprinkle some ES6.
+
+        * http/tests/inspector/dom/resources/InspectorDOMListener.js:
+        * http/tests/inspector/resources/console-test.js:
+        * http/tests/inspector/resources/probe-test.js:
+        * http/tests/inspector/resources/protocol-test.js:
+        (TestPage.registerInitializer):
+        (TestPage.debugLog.window.debugLog):
+        (TestPage.log.window.log):
+        (TestPage.closeTest.window.closeTest):
+        (TestPage.runTest.window.runTest):
+        (ProtocolTestProxy.registerInitializer): Deleted.
+        (debugLog): Deleted.
+        (log): Deleted.
+        (closeTest): Deleted.
+        (runTest): Deleted.
+        * inspector/dom/resources/dom-search-queries.js:
+        * inspector/unit-tests/async-test-suite.html:
+        * inspector/unit-tests/sync-test-suite.html:
+
</ins><span class="cx"> 2015-08-18  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Cocoa] Punctuation near Hindi text is garbled when styled with the system font
</span></span></pre></div>
<a id="trunkLayoutTestshttptestsinspectordomresourcesInspectorDOMListenerjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/inspector/dom/resources/InspectorDOMListener.js (188638 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/inspector/dom/resources/InspectorDOMListener.js        2015-08-19 15:38:14 UTC (rev 188638)
+++ trunk/LayoutTests/http/tests/inspector/dom/resources/InspectorDOMListener.js        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -27,7 +27,7 @@
</span><span class="cx">  * SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-ProtocolTestProxy.registerInitializer(function(){
</del><ins>+TestPage.registerInitializer(function() {
</ins><span class="cx"> 
</span><span class="cx"> window.createDOMListener = function()
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkLayoutTestshttptestsinspectorresourcesconsoletestjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/inspector/resources/console-test.js (188638 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/inspector/resources/console-test.js        2015-08-19 15:38:14 UTC (rev 188638)
+++ trunk/LayoutTests/http/tests/inspector/resources/console-test.js        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -1,5 +1,30 @@
</span><del>-ProtocolTestProxy.registerInitializer(function() {
</del><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS &quot;AS IS&quot; AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
</ins><span class="cx"> 
</span><ins>+TestPage.registerInitializer(function() {
+
</ins><span class="cx"> ProtocolTest.Console = {};
</span><span class="cx"> 
</span><span class="cx"> ProtocolTest.Console.sanitizeConsoleMessage = function(messageObject)
</span><span class="lines">@@ -34,7 +59,7 @@
</span><span class="cx"> 
</span><span class="cx"> ProtocolTest.Console.addTestCase = function(suite, args)
</span><span class="cx"> {
</span><del>-    if (!(suite instanceof InjectedTestHarness.AsyncTestSuite))
</del><ins>+    if (!(suite instanceof AsyncTestSuite))
</ins><span class="cx">         throw new Error(&quot;Console test cases must be added to an async test suite.&quot;);
</span><span class="cx"> 
</span><span class="cx">     var {name, description, expression, expected} = args;
</span></span></pre></div>
<a id="trunkLayoutTestshttptestsinspectorresourcesprobetestjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/inspector/resources/probe-test.js (188638 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/inspector/resources/probe-test.js        2015-08-19 15:38:14 UTC (rev 188638)
+++ trunk/LayoutTests/http/tests/inspector/resources/probe-test.js        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -1,5 +1,30 @@
</span><del>-ProtocolTestProxy.registerInitializer(function() {
</del><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS &quot;AS IS&quot; AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
</ins><span class="cx"> 
</span><ins>+TestPage.registerInitializer(function() {
+
</ins><span class="cx"> ProtocolTest.Probe = {};
</span><span class="cx"> 
</span><span class="cx"> ProtocolTest.Probe.sanitizeProbeSample = function(messageObject)
</span></span></pre></div>
<a id="trunkLayoutTestshttptestsinspectorresourcesprotocoltestjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/inspector/resources/protocol-test.js (188638 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/inspector/resources/protocol-test.js        2015-08-19 15:38:14 UTC (rev 188638)
+++ trunk/LayoutTests/http/tests/inspector/resources/protocol-test.js        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -25,33 +25,26 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> // This namespace is injected into every test page. Its functions are invoked by
</span><del>-// ProtocolTest methods on the inspector page via InjectedTestHarness.
-ProtocolTestProxy = {};
-ProtocolTestProxy._initializers = [];
</del><ins>+// ProtocolTest methods on the inspector page via a TestHarness subclass.
+TestPage = {};
+TestPage._initializers = [];
</ins><span class="cx"> 
</span><span class="cx"> // Helper scripts like `console-test.js` must register their initialization
</span><span class="cx"> // function with this method so it will be marshalled to the inspector page.
</span><del>-ProtocolTestProxy.registerInitializer = function(initializer)
</del><ins>+TestPage.registerInitializer = function(initializer)
</ins><span class="cx"> {
</span><span class="cx">     if (typeof initializer === &quot;function&quot;)
</span><span class="cx">         this._initializers.push(initializer.toString());
</span><del>-}
</del><ins>+};
</ins><span class="cx"> 
</span><span class="cx"> let outputElement;
</span><span class="cx"> 
</span><del>-/**
- * Logs message to process stdout via alert (hopefully implemented with immediate flush).
- * @param {string} text
- */
-function debugLog(text)
</del><ins>+TestPage.debugLog = window.debugLog = function(text)
</ins><span class="cx"> {
</span><span class="cx">     alert(text);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-/**
- * @param {string} text
- */
-function log(text)
</del><ins>+TestPage.log = window.log = function(text)
</ins><span class="cx"> {
</span><span class="cx">     if (!outputElement) {
</span><span class="cx">         let intermediate = document.createElement(&quot;div&quot;);
</span><span class="lines">@@ -68,31 +61,30 @@
</span><span class="cx">     }
</span><span class="cx">     outputElement.appendChild(document.createTextNode(text));
</span><span class="cx">     outputElement.appendChild(document.createElement(&quot;br&quot;));
</span><del>-}
</del><ins>+};
</ins><span class="cx"> 
</span><del>-function closeTest()
</del><ins>+TestPage.closeTest = window.closeTest = function()
</ins><span class="cx"> {
</span><span class="cx">     window.internals.closeDummyInspectorFrontend();
</span><span class="cx"> 
</span><span class="cx">     // This code might be executed while the debugger is still running through a stack based EventLoop.
</span><span class="cx">     // Use a setTimeout to defer to a clean stack before letting the testRunner load the next test.
</span><del>-    setTimeout(function() {
-        testRunner.notifyDone();
-    }, 0);
-}
</del><ins>+    setTimeout(() =&gt; { testRunner.notifyDone(); }, 0);
+};
</ins><span class="cx"> 
</span><del>-function runTest()
</del><ins>+TestPage.runTest = window.runTest = function()
</ins><span class="cx"> {
</span><span class="cx">     if (!window.testRunner) {
</span><del>-        console.error(&quot;This test requires DumpRenderTree&quot;);
</del><ins>+        console.error(&quot;This test must be run via DumpRenderTree or WebKitTestRunner.&quot;);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><ins>+
</ins><span class="cx">     testRunner.dumpAsText();
</span><span class="cx">     testRunner.waitUntilDone();
</span><span class="cx">     testRunner.setCanOpenWindows(true);
</span><span class="cx"> 
</span><span class="cx">     let testFunction = window.test;
</span><del>-    if (!(typeof testFunction === &quot;function&quot;)) {
</del><ins>+    if (typeof testFunction !== &quot;function&quot;) {
</ins><span class="cx">         alert(&quot;Failed to send test() because it is not a function.&quot;);
</span><span class="cx">         testRunner.notifyDone();
</span><span class="cx">     }
</span><span class="lines">@@ -126,11 +118,11 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     let inspectorFrontend = window.internals.openDummyInspectorFrontend(url);
</span><del>-    inspectorFrontend.addEventListener(&quot;load&quot;, function(event) {
-        let initializationCodeString = `(${runInitializationMethodsInFrontend.toString()})([${ProtocolTestProxy._initializers}]);`;
</del><ins>+    inspectorFrontend.addEventListener(&quot;load&quot;, (event) =&gt; {
+        let initializationCodeString = `(${runInitializationMethodsInFrontend.toString()})([${TestPage._initializers}]);`;
</ins><span class="cx">         let testFunctionCodeString = `(${runTestMethodInFrontend.toString()})(${testFunction.toString()});`;
</span><span class="cx"> 
</span><span class="cx">         inspectorFrontend.postMessage(initializationCodeString, &quot;*&quot;);
</span><span class="cx">         inspectorFrontend.postMessage(testFunctionCodeString, &quot;*&quot;);
</span><span class="cx">     });
</span><del>-}
</del><ins>+};
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectordomresourcesdomsearchqueriesjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/dom/resources/dom-search-queries.js (188638 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/dom/resources/dom-search-queries.js        2015-08-19 15:38:14 UTC (rev 188638)
+++ trunk/LayoutTests/inspector/dom/resources/dom-search-queries.js        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -1,4 +1,4 @@
</span><del>-ProtocolTestProxy.registerInitializer(function() {
</del><ins>+TestPage.registerInitializer(function() {
</ins><span class="cx"> 
</span><span class="cx"> // Having the queries in an external file, so that DOM search will not find the script when searching for values.
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsinspectorunittestsasynctestsuiteexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/unit-tests/async-test-suite-expected.txt (188638 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/unit-tests/async-test-suite-expected.txt        2015-08-19 15:38:14 UTC (rev 188638)
+++ trunk/LayoutTests/inspector/unit-tests/async-test-suite-expected.txt        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -1,9 +1,11 @@
</span><span class="cx"> PASS: instantiating AsyncTestSuite requires name argument.
</span><span class="cx"> PASS: instantiating AsyncTestSuite requires string name argument.
</span><ins>+PASS: instantiating AsyncTestSuite requires non-whitespace name argument.
</ins><span class="cx"> PASS: instantiating AsyncTestSuite requires test harness argument.
</span><span class="cx"> PASS: should not be able to add empty test case.
</span><span class="cx"> PASS: should not be able to add non-object test case.
</span><span class="cx"> PASS: test case should require string name.
</span><ins>+PASS: test case should require non-whitespace name.
</ins><span class="cx"> PASS: test case should require test function.
</span><span class="cx"> PASS: should not be able to run empty test suite.
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsinspectorunittestsasynctestsuitehtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/unit-tests/async-test-suite.html (188638 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/unit-tests/async-test-suite.html        2015-08-19 15:38:14 UTC (rev 188638)
+++ trunk/LayoutTests/inspector/unit-tests/async-test-suite.html        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -6,27 +6,34 @@
</span><span class="cx"> function test()
</span><span class="cx"> {
</span><span class="cx">     try {
</span><del>-        let result = new InjectedTestHarness.AsyncTestSuite(this);
</del><ins>+        let result = new AsyncTestSuite(this);
</ins><span class="cx">         ProtocolTest.log(&quot;FAIL: instantiating AsyncTestSuite requires name argument.&quot;);
</span><span class="cx">     } catch (e) {
</span><span class="cx">         ProtocolTest.log(&quot;PASS: instantiating AsyncTestSuite requires name argument.&quot;);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     try {
</span><del>-        let result = new InjectedTestHarness.AsyncTestSuite(this, {});
</del><ins>+        let result = new AsyncTestSuite(this, {});
</ins><span class="cx">         ProtocolTest.log(&quot;FAIL: instantiating AsyncTestSuite requires string name argument.&quot;);
</span><span class="cx">     } catch (e) {
</span><span class="cx">         ProtocolTest.log(&quot;PASS: instantiating AsyncTestSuite requires string name argument.&quot;);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     try {
</span><del>-        let result = new InjectedTestHarness.AsyncTestSuite(&quot;something&quot;, {});
</del><ins>+        let result = new AsyncTestSuite(this, &quot;      &quot;);
+        ProtocolTest.log(&quot;FAIL: instantiating AsyncTestSuite requires non-whitespace name argument.&quot;);
+    } catch (e) {
+        ProtocolTest.log(&quot;PASS: instantiating AsyncTestSuite requires non-whitespace name argument.&quot;);
+    }
+
+    try {
+        let result = new AsyncTestSuite(&quot;something&quot;, {});
</ins><span class="cx">         ProtocolTest.log(&quot;FAIL: instantiating AsyncTestSuite requires test harness argument.&quot;);
</span><span class="cx">     } catch (e) {
</span><span class="cx">         ProtocolTest.log(&quot;PASS: instantiating AsyncTestSuite requires test harness argument.&quot;);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    var badArgsSuite = ProtocolTest.createAsyncSuite(&quot;dummy&quot;);
</del><ins>+    let badArgsSuite = ProtocolTest.createAsyncSuite(&quot;dummy&quot;);
</ins><span class="cx">     try {
</span><span class="cx">         badArgsSuite.addTestCase();
</span><span class="cx">         ProtocolTest.log(&quot;FAIL: should not be able to add empty test case.&quot;);
</span><span class="lines">@@ -42,7 +49,7 @@
</span><span class="cx">     try {
</span><span class="cx">         badArgsSuite.addTestCase({
</span><span class="cx">             name: {},
</span><del>-            test: function() {},
</del><ins>+            test: () =&gt; {},
</ins><span class="cx">         });
</span><span class="cx">         ProtocolTest.log(&quot;FAIL: test case should require string name.&quot;);
</span><span class="cx">     } catch (e) {
</span><span class="lines">@@ -50,6 +57,15 @@
</span><span class="cx">     }
</span><span class="cx">     try {
</span><span class="cx">         badArgsSuite.addTestCase({
</span><ins>+            name: &quot;        &quot;,
+            test: () =&gt; {},
+        });
+        ProtocolTest.log(&quot;FAIL: test case should require non-whitespace name.&quot;);
+    } catch (e) {
+        ProtocolTest.log(&quot;PASS: test case should require non-whitespace name.&quot;);
+    }
+    try {
+        badArgsSuite.addTestCase({
</ins><span class="cx">             name: &quot;foo&quot;,
</span><span class="cx">             test: null,
</span><span class="cx">         });
</span><span class="lines">@@ -58,7 +74,7 @@
</span><span class="cx">         ProtocolTest.log(&quot;PASS: test case should require test function.&quot;);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    var runEmptySuite = ProtocolTest.createAsyncSuite(&quot;AsyncTestSuite.RunEmptySuite&quot;);
</del><ins>+    let runEmptySuite = ProtocolTest.createAsyncSuite(&quot;AsyncTestSuite.RunEmptySuite&quot;);
</ins><span class="cx">     try {
</span><span class="cx">         runEmptySuite.runTestCases();
</span><span class="cx">         ProtocolTest.log(&quot;FAIL: should not be able to run empty test suite.&quot;);
</span><span class="lines">@@ -66,16 +82,14 @@
</span><span class="cx">         ProtocolTest.log(&quot;PASS: should not be able to run empty test suite.&quot;);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    var runTwiceSuite = ProtocolTest.createAsyncSuite(&quot;AsyncTestSuite.RunTwiceSuite&quot;);
</del><ins>+    let runTwiceSuite = ProtocolTest.createAsyncSuite(&quot;AsyncTestSuite.RunTwiceSuite&quot;);
</ins><span class="cx">     runTwiceSuite.addTestCase({
</span><span class="cx">         name: &quot;DummyTest0&quot;,
</span><span class="cx">         description: &quot;Check that a suite can't run more than once.&quot;,
</span><del>-        test: function(resolve, reject) {
-            resolve();
-        }
</del><ins>+        test: (resolve, reject) =&gt; { resolve(); }
</ins><span class="cx">     });
</span><span class="cx"> 
</span><del>-    var result = runTwiceSuite.runTestCases();
</del><ins>+    let result = runTwiceSuite.runTestCases();
</ins><span class="cx">     try {
</span><span class="cx">         // Test cases won't run in this event loop; this call should still throw.
</span><span class="cx">         // Later tests are chained to this suite to avoid nondeterminism.
</span><span class="lines">@@ -85,64 +99,50 @@
</span><span class="cx">         ProtocolTest.log(&quot;PASS: should not be able to run a test suite twice.&quot;);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    var rejectToken = {&quot;token&quot;: 666};
-    var thrownError = new Error(rejectToken);
</del><ins>+    let rejectToken = {&quot;token&quot;: 666};
+    let thrownError = new Error(rejectToken);
</ins><span class="cx"> 
</span><del>-    var sequentialExecutionSuite = ProtocolTest.createAsyncSuite(&quot;AsyncTestSuite.SequentialExecution&quot;);
</del><ins>+    let sequentialExecutionSuite = ProtocolTest.createAsyncSuite(&quot;AsyncTestSuite.SequentialExecution&quot;);
</ins><span class="cx">     sequentialExecutionSuite.addTestCase({
</span><span class="cx">         name: &quot;DummyTest1&quot;,
</span><span class="cx">         description: &quot;Check test case execution order.&quot;,
</span><del>-        test: function(resolve, reject) {
-            resolve();
-        }
</del><ins>+        test: (resolve, reject) =&gt; { resolve(); }
</ins><span class="cx">     });
</span><span class="cx">     sequentialExecutionSuite.addTestCase({
</span><span class="cx">         name: &quot;DummyTest2&quot;,
</span><span class="cx">         description: &quot;Check test case execution order.&quot;,
</span><del>-        test: function(resolve, reject) {
-            resolve();
-        }
</del><ins>+        test: (resolve, reject) =&gt; { resolve(); }
</ins><span class="cx">     });
</span><span class="cx">     sequentialExecutionSuite.addTestCase({
</span><span class="cx">         name: &quot;DummyTest3&quot;,
</span><span class="cx">         description: &quot;Check test case execution order.&quot;,
</span><del>-        test: function(resolve, reject) {
-            resolve();
-        }
</del><ins>+        test: (resolve, reject) =&gt; { resolve(); }
</ins><span class="cx">     });
</span><span class="cx">     sequentialExecutionSuite.addTestCase({
</span><span class="cx">         name: &quot;FailingTest4&quot;,
</span><span class="cx">         description: &quot;Check that test fails by throwing an Error instance.&quot;,
</span><del>-        test: function(resolve, reject) {
-            throw thrownError;
-        }
</del><ins>+        test: (resolve, reject) =&gt; { throw thrownError; }
</ins><span class="cx">     });
</span><span class="cx"> 
</span><del>-    var abortOnFailureSuite = ProtocolTest.createAsyncSuite(&quot;AsyncTestSuite.AbortOnFailure&quot;);
</del><ins>+    let abortOnFailureSuite = ProtocolTest.createAsyncSuite(&quot;AsyncTestSuite.AbortOnFailure&quot;);
</ins><span class="cx">     abortOnFailureSuite.addTestCase({
</span><span class="cx">         name: &quot;PassingTest5&quot;,
</span><span class="cx">         description: &quot;This test is a dummy.&quot;,
</span><del>-        test: function(resolve, reject) {
-            resolve();
-        }
</del><ins>+        test: (resolve, reject) =&gt; { resolve(); }
</ins><span class="cx">     });
</span><span class="cx">     abortOnFailureSuite.addTestCase({
</span><span class="cx">         name: &quot;FailingTest6&quot;,
</span><span class="cx">         description: &quot;This test should fail by explicitly calling the `reject` callback.&quot;,
</span><del>-        test: function(resolve, reject) {
-            reject(rejectToken);
-        }
</del><ins>+        test: (resolve, reject) =&gt; { reject(rejectToken); }
</ins><span class="cx">     });
</span><span class="cx">     abortOnFailureSuite.addTestCase({
</span><span class="cx">         name: &quot;PassingTest7&quot;,
</span><span class="cx">         description: &quot;This test should not executed when the preceding test fails.&quot;,
</span><del>-        test: function(resolve, reject) {
-            resolve();
-        }
</del><ins>+        test: (resolve, reject) =&gt; { resolve(); }
</ins><span class="cx">     });
</span><span class="cx"> 
</span><del>-    result = result.then(function() {
-        var promise = sequentialExecutionSuite.runTestCases();
</del><ins>+    result = result.then(() =&gt; {
+        let promise = sequentialExecutionSuite.runTestCases();
</ins><span class="cx">         ProtocolTest.expectThat(result instanceof Promise, &quot;AsyncTestSuite.RunTestCases() should return a Promise.&quot;);
</span><span class="cx">         return promise;
</span><span class="cx">     });
</span><span class="lines">@@ -160,7 +160,7 @@
</span><span class="cx">         return Promise.resolve(); // Continue this test.
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-    result = result.then(function() {
</del><ins>+    result = result.then(() =&gt; {
</ins><span class="cx">         return abortOnFailureSuite.runTestCases();
</span><span class="cx">     }).then(function resolved() {
</span><span class="cx">         ProtocolTest.log(&quot;FAIL: Promise from abortOnFailureSuite.runTestCases() should reject when a test case fails.&quot;);
</span><span class="lines">@@ -177,7 +177,7 @@
</span><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     // This will finish the test whether the chain was resolved or rejected.
</span><del>-    result = result.then(function() { ProtocolTest.completeTest(); });
</del><ins>+    result = result.then(() =&gt; { ProtocolTest.completeTest(); });
</ins><span class="cx"> }
</span><span class="cx"> &lt;/script&gt;
</span><span class="cx"> &lt;/head&gt;
</span></span></pre></div>
<a id="trunkLayoutTestsinspectorunittestssynctestsuiteexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/unit-tests/sync-test-suite-expected.txt (188638 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/unit-tests/sync-test-suite-expected.txt        2015-08-19 15:38:14 UTC (rev 188638)
+++ trunk/LayoutTests/inspector/unit-tests/sync-test-suite-expected.txt        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -1,9 +1,11 @@
</span><span class="cx"> PASS: instantiating SyncTestSuite requires name argument.
</span><span class="cx"> PASS: instantiating SyncTestSuite requires string name argument.
</span><ins>+PASS: instantiating AsyncTestSuite requires non-whitespace name argument.
</ins><span class="cx"> PASS: instantiating SyncTestSuite requires test harness argument.
</span><span class="cx"> PASS: should not be able to add empty test case.
</span><span class="cx"> PASS: should not be able to add non-object test case.
</span><span class="cx"> PASS: test case should require string name.
</span><ins>+PASS: test case should require non-whitespace name.
</ins><span class="cx"> PASS: test case should require test function.
</span><span class="cx"> PASS: should not be able to run empty test suite.
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsinspectorunittestssynctestsuitehtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/inspector/unit-tests/sync-test-suite.html (188638 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/unit-tests/sync-test-suite.html        2015-08-19 15:38:14 UTC (rev 188638)
+++ trunk/LayoutTests/inspector/unit-tests/sync-test-suite.html        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -6,27 +6,34 @@
</span><span class="cx"> function test()
</span><span class="cx"> {
</span><span class="cx">     try {
</span><del>-        let result = new ProtocolTest.SyncTestSuite(this);
</del><ins>+        let result = new SyncTestSuite(this);
</ins><span class="cx">         ProtocolTest.log(&quot;FAIL: instantiating SyncTestSuite requires name argument.&quot;);
</span><span class="cx">     } catch (e) {
</span><span class="cx">         ProtocolTest.log(&quot;PASS: instantiating SyncTestSuite requires name argument.&quot;);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     try {
</span><del>-        let result = new ProtocolTest.SyncTestSuite(this, {});
</del><ins>+        let result = new SyncTestSuite(this, {});
</ins><span class="cx">         ProtocolTest.log(&quot;FAIL: instantiating SyncTestSuite requires string name argument.&quot;);
</span><span class="cx">     } catch (e) {
</span><span class="cx">         ProtocolTest.log(&quot;PASS: instantiating SyncTestSuite requires string name argument.&quot;);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     try {
</span><del>-        let result = new ProtocolTest.SyncTestSuite(&quot;something&quot;, {});
</del><ins>+        let result = new syncTestSuite(this, &quot;      &quot;);
+        ProtocolTest.log(&quot;FAIL: instantiating AsyncTestSuite requires non-whitespace name argument.&quot;);
+    } catch (e) {
+        ProtocolTest.log(&quot;PASS: instantiating AsyncTestSuite requires non-whitespace name argument.&quot;);
+    }
+
+    try {
+        let result = new SyncTestSuite(&quot;something&quot;, {});
</ins><span class="cx">         ProtocolTest.log(&quot;FAIL: instantiating SyncTestSuite requires test harness argument.&quot;);
</span><span class="cx">     } catch (e) {
</span><span class="cx">         ProtocolTest.log(&quot;PASS: instantiating SyncTestSuite requires test harness argument.&quot;);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    var badArgsSuite = ProtocolTest.createSyncSuite(&quot;dummy&quot;);
</del><ins>+    let badArgsSuite = ProtocolTest.createSyncSuite(&quot;dummy&quot;);
</ins><span class="cx">     try {
</span><span class="cx">         badArgsSuite.addTestCase();
</span><span class="cx">         ProtocolTest.log(&quot;FAIL: should not be able to add empty test case.&quot;);
</span><span class="lines">@@ -42,7 +49,7 @@
</span><span class="cx">     try {
</span><span class="cx">         badArgsSuite.addTestCase({
</span><span class="cx">             name: {},
</span><del>-            test: function() { return true; },
</del><ins>+            test: () =&gt; true,
</ins><span class="cx">         });
</span><span class="cx">         ProtocolTest.log(&quot;FAIL: test case should require string name.&quot;);
</span><span class="cx">     } catch (e) {
</span><span class="lines">@@ -50,6 +57,15 @@
</span><span class="cx">     }
</span><span class="cx">     try {
</span><span class="cx">         badArgsSuite.addTestCase({
</span><ins>+            name: &quot;        &quot;,
+            test: () =&gt; {},
+        });
+        ProtocolTest.log(&quot;FAIL: test case should require non-whitespace name.&quot;);
+    } catch (e) {
+        ProtocolTest.log(&quot;PASS: test case should require non-whitespace name.&quot;);
+    }
+    try {
+        badArgsSuite.addTestCase({
</ins><span class="cx">             name: &quot;foo&quot;,
</span><span class="cx">             test: null,
</span><span class="cx">         });
</span><span class="lines">@@ -58,7 +74,7 @@
</span><span class="cx">         ProtocolTest.log(&quot;PASS: test case should require test function.&quot;);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    var runEmptySuite = ProtocolTest.createSyncSuite(&quot;SyncTestSuite.RunEmptySuite&quot;);
</del><ins>+    let runEmptySuite = ProtocolTest.createSyncSuite(&quot;SyncTestSuite.RunEmptySuite&quot;);
</ins><span class="cx">     try {
</span><span class="cx">         runEmptySuite.runTestCases();
</span><span class="cx">         ProtocolTest.log(&quot;FAIL: should not be able to run empty test suite.&quot;);
</span><span class="lines">@@ -66,15 +82,15 @@
</span><span class="cx">         ProtocolTest.log(&quot;PASS: should not be able to run empty test suite.&quot;);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    var runTwiceSuite = ProtocolTest.createSyncSuite(&quot;SyncTestSuite.RunTwiceSuite&quot;);
</del><ins>+    let runTwiceSuite = ProtocolTest.createSyncSuite(&quot;SyncTestSuite.RunTwiceSuite&quot;);
</ins><span class="cx">     runTwiceSuite.addTestCase({
</span><span class="cx">         name: &quot;DummyTest0&quot;,
</span><span class="cx">         description: &quot;Check that a suite can't run more than once.&quot;,
</span><del>-        test: function() { return true; }
</del><ins>+        test: () =&gt; true,
</ins><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     try {
</span><del>-        var result = runTwiceSuite.runTestCases();
</del><ins>+        let result = runTwiceSuite.runTestCases();
</ins><span class="cx">         ProtocolTest.expectThat(result === true, &quot;Return value of runTwiceSuite.runTestCases() should be true when all tests pass.&quot;);
</span><span class="cx"> 
</span><span class="cx">         runTwiceSuite.runTestCases(); // Try to trigger an error.
</span><span class="lines">@@ -83,52 +99,52 @@
</span><span class="cx">         ProtocolTest.log(&quot;PASS: should not be able to run a test suite twice.&quot;);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    var thrownError = new Error({&quot;token&quot;: 666});
</del><ins>+    let thrownError = new Error({&quot;token&quot;: 666});
</ins><span class="cx"> 
</span><del>-    var sequentialExecutionSuite = ProtocolTest.createSyncSuite(&quot;SyncTestSuite.SequentialExecution&quot;);
</del><ins>+    let sequentialExecutionSuite = ProtocolTest.createSyncSuite(&quot;SyncTestSuite.SequentialExecution&quot;);
</ins><span class="cx">     sequentialExecutionSuite.addTestCase({
</span><span class="cx">         name: &quot;DummyTest1&quot;,
</span><span class="cx">         description: &quot;Check test case execution order.&quot;,
</span><del>-        test: function() { return true; }
</del><ins>+        test: () =&gt; true
</ins><span class="cx">     });
</span><span class="cx">     sequentialExecutionSuite.addTestCase({
</span><span class="cx">         name: &quot;DummyTest2&quot;,
</span><span class="cx">         description: &quot;Check test case execution order.&quot;,
</span><del>-        test: function() { return true; }
</del><ins>+        test: () =&gt; true
</ins><span class="cx">     });
</span><span class="cx">     sequentialExecutionSuite.addTestCase({
</span><span class="cx">         name: &quot;DummyTest3&quot;,
</span><span class="cx">         description: &quot;Check test case execution order.&quot;,
</span><del>-        test: function() { return true; }
</del><ins>+        test: () =&gt; true
</ins><span class="cx">     });
</span><span class="cx">     sequentialExecutionSuite.addTestCase({
</span><span class="cx">         name: &quot;FailingTest4&quot;,
</span><span class="cx">         description: &quot;Check that test fails by throwing an Error instance.&quot;,
</span><del>-        test: function() { throw thrownError; }
</del><ins>+        test: () =&gt; { throw thrownError; }
</ins><span class="cx">     });
</span><span class="cx"> 
</span><del>-    var result = sequentialExecutionSuite.runTestCases();
</del><ins>+    let result = sequentialExecutionSuite.runTestCases();
</ins><span class="cx">     ProtocolTest.expectThat(result === false, &quot;Return value of sequentialExecutionSuite.runTestCases() should be false when a test case fails.&quot;);
</span><span class="cx">     ProtocolTest.expectThat(sequentialExecutionSuite.runCount === 4, &quot;sequentialExecutionSuite should have executed four tests.&quot;);
</span><span class="cx">     ProtocolTest.expectThat(sequentialExecutionSuite.passCount === 3, &quot;sequentialExecutionSuite should have passed three tests.&quot;);
</span><span class="cx">     ProtocolTest.expectThat(sequentialExecutionSuite.failCount === 1, &quot;sequentialExecutionSuite should have failed 1 test.&quot;);
</span><span class="cx">     ProtocolTest.expectThat(sequentialExecutionSuite.skipCount === 0, &quot;sequentialExecutionSuite should have skipped zero tests.&quot;);
</span><span class="cx"> 
</span><del>-    var abortOnFailureSuite = ProtocolTest.createSyncSuite(&quot;SyncTestSuite.AbortOnFailure&quot;);
</del><ins>+    let abortOnFailureSuite = ProtocolTest.createSyncSuite(&quot;SyncTestSuite.AbortOnFailure&quot;);
</ins><span class="cx">     abortOnFailureSuite.addTestCase({
</span><span class="cx">         name: &quot;PassingTest5&quot;,
</span><span class="cx">         description: &quot;This test is a dummy.&quot;,
</span><del>-        test: function() { return true; }
</del><ins>+        test: () =&gt; true
</ins><span class="cx">     });
</span><span class="cx">     abortOnFailureSuite.addTestCase({
</span><span class="cx">         name: &quot;FailingTest6&quot;,
</span><span class="cx">         description: &quot;This test should fail by explicitly returning `false`.&quot;,
</span><del>-        test: function() { return false; }
</del><ins>+        test: () =&gt; false
</ins><span class="cx">     });
</span><span class="cx">     abortOnFailureSuite.addTestCase({
</span><span class="cx">         name: &quot;PassingTest7&quot;,
</span><span class="cx">         description: &quot;This test should not executed when the preceding test fails.&quot;,
</span><del>-        test: function() { return true; }
</del><ins>+        test: () =&gt; true
</ins><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     abortOnFailureSuite.runTestCases();
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (188638 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2015-08-19 15:38:14 UTC (rev 188638)
+++ trunk/Source/WebInspectorUI/ChangeLog        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -1,3 +1,82 @@
</span><ins>+2015-08-19  Brian Burg  &lt;bburg@apple.com&gt;
+
+        Web Inspector: split TestStub.js into multiple files and modernize it
+        https://bugs.webkit.org/show_bug.cgi?id=148077
+
+        Reviewed by Timothy Hatcher.

+        Since we want to share files between the two harnesses, split some of the parts
+        into different files so not everything has to be included at once.
+
+        Rename InjectedTestHarness to just TestHarness. Update some code to use
+        ES6 features where appropriate. Put test classes into Test/ directory.
+
+        * UserInterface/Base/TestStub.js: Removed.
+        * UserInterface/Test.html:
+        * UserInterface/Test/InspectorProtocol.js: Added.
+        (InspectorProtocol.sendCommand):
+        (InspectorProtocol.awaitCommand):
+        (InspectorProtocol.awaitEvent.):
+        (InspectorProtocol.awaitEvent):
+        (InspectorProtocol.addEventListener):
+        (InspectorProtocol.sendMessage):
+        (InspectorProtocol.checkForError):
+        (InspectorProtocol.dispatchMessageFromBackend):
+        * UserInterface/Test/ProtocolTestHarness.js: Added.
+        (ProtocolTestHarness.prototype.completeTest):
+        (ProtocolTestHarness.prototype.addResult):
+        (ProtocolTestHarness.prototype.debugLog):
+        (ProtocolTestHarness.prototype.evaluateInPage):
+        (ProtocolTestHarness):
+        * UserInterface/Test/Test.js: Renamed from Source/WebInspectorUI/UserInterface/Base/Test.js.
+        (WebInspector.loaded):
+        (WebInspector.contentLoaded):
+        (WebInspector.UIString):
+        (WebInspector.updateDockedState):
+        (WebInspector.updateDockingAvailability):
+        (InspectorTest.EventDispatcher.prototype.dispatchEvent):
+        (InspectorTest.EventDispatcher):
+        (InspectorTest.log):
+        (InspectorTest.assert):
+        (InspectorTest.expectThat):
+        (InspectorTest.debugLog):
+        (InspectorTest.expectNoError):
+        (InspectorTest.completeTest):
+        (InspectorTest.evaluateInPage):
+        (InspectorTest.addResult):
+        (InspectorTest._resendResults):
+        (InspectorTest.testPageDidLoad):
+        (InspectorTest.reloadPage):
+        (InspectorTest.reportUncaughtException):
+        * UserInterface/Test/TestHarness.js: Added.
+        (TestHarness):
+        (TestHarness.prototype.completeTest):
+        (TestHarness.prototype.addResult):
+        (TestHarness.prototype.debugLog):
+        (TestHarness.prototype.evaluateInPage):
+        (TestHarness.prototype.createAsyncSuite):
+        (TestHarness.prototype.createSyncSuite):
+        (TestHarness.prototype.get logCount):
+        (TestHarness.prototype.log):
+        (TestHarness.prototype.assert):
+        (TestHarness.prototype.expectThat):
+        * UserInterface/Test/TestStub.js: Added.
+        * UserInterface/Test/TestSuite.js: Added.
+        (TestSuite):
+        (TestSuite.prototype.runTestCasesAndFinish):
+        (TestSuite.prototype.runTestCases):
+        (TestSuite.prototype.get passCount):
+        (TestSuite.prototype.get skipCount):
+        (TestSuite.prototype.addTestCase):
+        (AsyncTestSuite.prototype.runTestCasesAndFinish.finish):
+        (AsyncTestSuite.prototype.runTestCasesAndFinish):
+        (AsyncTestSuite.prototype.runTestCases):
+        (AsyncTestSuite):
+        (SyncTestSuite.prototype.runTestCasesAndFinish):
+        (SyncTestSuite.prototype.runTestCases):
+        (SyncTestSuite):
+        * UserInterface/TestStub.html:
+
</ins><span class="cx"> 2015-08-19  Nikita Vasilyev  &lt;nvasilyev@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Pressing Command-Enter should re-evaluate selected console user command
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceBaseTestjs"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebInspectorUI/UserInterface/Base/Test.js (188638 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Base/Test.js        2015-08-19 15:38:14 UTC (rev 188638)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Test.js        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -1,279 +0,0 @@
</span><del>-/*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS
- * IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-WebInspector.DebuggableType = {
-    Web: &quot;web&quot;,
-    JavaScript: &quot;javascript&quot;
-};
-
-WebInspector.loaded = function()
-{
-    this.debuggableType = WebInspector.DebuggableType.Web;
-    this.hasExtraDomains = false;
-
-    // Register observers for events from the InspectorBackend.
-    // The initialization order should match the same in Main.js.
-    InspectorBackend.registerInspectorDispatcher(new WebInspector.InspectorObserver);
-    InspectorBackend.registerPageDispatcher(new WebInspector.PageObserver);
-    InspectorBackend.registerConsoleDispatcher(new WebInspector.ConsoleObserver);
-    InspectorBackend.registerDOMDispatcher(new WebInspector.DOMObserver);
-    InspectorBackend.registerNetworkDispatcher(new WebInspector.NetworkObserver);
-    InspectorBackend.registerDebuggerDispatcher(new WebInspector.DebuggerObserver);
-    InspectorBackend.registerTimelineDispatcher(new WebInspector.TimelineObserver);
-    InspectorBackend.registerCSSDispatcher(new WebInspector.CSSObserver);
-    InspectorBackend.registerRuntimeDispatcher(new WebInspector.RuntimeObserver);
-    if (InspectorBackend.registerReplayDispatcher)
-        InspectorBackend.registerReplayDispatcher(new WebInspector.ReplayObserver);
-
-    // Instantiate controllers used by tests.
-    this.frameResourceManager = new WebInspector.FrameResourceManager;
-    this.domTreeManager = new WebInspector.DOMTreeManager;
-    this.cssStyleManager = new WebInspector.CSSStyleManager;
-    this.logManager = new WebInspector.LogManager;
-    this.issueManager = new WebInspector.IssueManager;
-    this.runtimeManager = new WebInspector.RuntimeManager;
-    this.timelineManager = new WebInspector.TimelineManager;
-    this.debuggerManager = new WebInspector.DebuggerManager;
-    this.probeManager = new WebInspector.ProbeManager;
-    this.replayManager = new WebInspector.ReplayManager;
-
-    // Global controllers.
-    this.quickConsole = {executionContextIdentifier: undefined};
-
-    document.addEventListener(&quot;DOMContentLoaded&quot;, this.contentLoaded.bind(this));
-
-    // Enable agents.
-    InspectorAgent.enable();
-    ConsoleAgent.enable();
-
-    // Perform one-time tasks.
-    WebInspector.CSSCompletions.requestCSSCompletions();
-
-    // Global settings.
-    this.showShadowDOMSetting = new WebInspector.Setting(&quot;show-shadow-dom&quot;, true);
-}
-
-WebInspector.contentLoaded = function()
-{
-    // Signal that the frontend is now ready to receive messages.
-    InspectorFrontendAPI.loadCompleted();
-
-    // Tell the InspectorFrontendHost we loaded, which causes the window to display
-    // and pending InspectorFrontendAPI commands to be sent.
-    InspectorFrontendHost.loaded();
-}
-
-WebInspector.UIString = function(string)
-{
-    return string;
-}
-
-// Add stubs that are called by the frontend API.
-WebInspector.updateDockedState = function() {};
-WebInspector.updateDockingAvailability = function() {};
-
-// InspectorTest contains extra methods that are only available to test code running
-// in the Web Inspector page. They rely on equivalents in the actual test page
-// which are provided by `inspector-test.js`.
-InspectorTest = {};
-
-// This is useful for debugging Inspector tests by synchronously logging messages.
-InspectorTest.dumpMessagesToConsole = false;
-
-// This is a workaround for the fact that it would be hard to set up a constructor,
-// prototype, and prototype chain for the singleton InspectorTest.
-InspectorTest.EventDispatcher = class EventDispatcher extends WebInspector.Object
-{
-    dispatchEvent(event)
-    {
-        this.dispatchEventToListeners(event);
-    }
-};
-
-InspectorTest.EventDispatcher.Event = {
-    TestPageDidLoad: &quot;inspector-test-test-page-did-load&quot;
-};
-
-InspectorTest.eventDispatcher = new InspectorTest.EventDispatcher;
-
-// Note: Additional InspectorTest methods are included on a per-test basis from
-// files like `debugger-test.js`.
-
-// Appends a log message in the test document.
-InspectorTest.log = function(message)
-{
-    var stringifiedMessage = typeof message !== &quot;object&quot; ? message : JSON.stringify(message);
-    InspectorTest.addResult(stringifiedMessage);
-}
-
-// Appends a message in the test document only if the condition is false.
-InspectorTest.assert = function(condition, message)
-{
-    if (condition)
-        return;
-
-    var stringifiedMessage = typeof message !== &quot;object&quot; ? message : JSON.stringify(message);
-    InspectorTest.addResult(&quot;ASSERT: &quot; + stringifiedMessage);
-}
-
-// Appends a message in the test document whether the condition is true or not.
-InspectorTest.expectThat = function(condition, message)
-{
-    var prefix = condition ? &quot;PASS&quot; : &quot;FAIL&quot;;
-    var stringifiedMessage = typeof message !== &quot;object&quot; ? message : JSON.stringify(message);
-    InspectorTest.addResult(prefix + &quot;: &quot; + stringifiedMessage);
-}
-
-// This function should only be used to debug tests and not to produce normal test output.
-InspectorTest.debugLog = function(message)
-{
-    if (InspectorTest.dumpMessagesToConsole)
-        InspectorFrontendHost.unbufferedLog(&quot;debugLog: &quot; + message);
-
-    this.evaluateInPage(&quot;InspectorTestProxy.debugLog(unescape('&quot; + escape(JSON.stringify(message)) + &quot;'))&quot;);
-}
-
-// Appends a message in the test document if there was an error, and attempts to complete the test.
-InspectorTest.expectNoError = function(error)
-{
-    if (error) {
-        InspectorTest.log(&quot;PROTOCOL ERROR: &quot; + error);
-        InspectorTest.completeTest();
-        throw &quot;PROTOCOL ERROR&quot;;
-    }
-}
-
-InspectorTest.completeTest = function()
-{
-    if (InspectorTest.dumpMessagesToConsole)
-        InspectorFrontendHost.unbufferedLog(&quot;InspectorTest.completeTest()&quot;);
-
-    // Wait for results to be resent before requesting completeTest(). Otherwise, messages will be
-    // queued after pending dispatches run to zero and the test page will quit before processing them.
-    if (this._testPageIsReloading) {
-        this._completeTestAfterReload = true;
-        return;
-    }
-
-    InspectorBackend.runAfterPendingDispatches(this.evaluateInPage.bind(this, &quot;InspectorTestProxy.completeTest()&quot;));
-}
-
-InspectorTest.evaluateInPage = function(codeString, callback)
-{
-    // If we load this page outside of the inspector, or hit an early error when loading
-    // the test frontend, then defer evaluating the commands (indefinitely in the former case).
-    if (!window.RuntimeAgent) {
-        this._originalConsoleMethods[&quot;error&quot;](&quot;Tried to evaluate in test page, but connection not yet established:&quot;, codeString);
-        return;
-    }
-
-    RuntimeAgent.evaluate.invoke({expression: codeString, objectGroup: &quot;test&quot;, includeCommandLineAPI: false}, callback);
-}
-
-InspectorTest.addResult = function(text)
-{
-    this._results.push(text);
-
-    if (InspectorTest.dumpMessagesToConsole)
-        InspectorFrontendHost.unbufferedLog(&quot;addResult: &quot; + text);
-
-    if (!this._testPageIsReloading)
-        this.evaluateInPage(&quot;InspectorTestProxy.addResult(unescape('&quot; + escape(text) + &quot;'))&quot;);
-}
-
-InspectorTest._resendResults = function()
-{
-    console.assert(this._shouldResendResults);
-    this._shouldResendResults = false;
-
-    for (var result of this._results)
-        this.evaluateInPage(&quot;InspectorTestProxy.addResult(unescape('&quot; + escape(result) + &quot;'))&quot;);
-}
-
-InspectorTest.testPageDidLoad = function()
-{
-    this._testPageIsReloading = false;
-    this._resendResults();
-
-    this.eventDispatcher.dispatchEvent(InspectorTest.EventDispatcher.Event.TestPageDidLoad);
-
-    if (this._completeTestAfterReload)
-        InspectorTest.completeTest();
-}
-
-InspectorTest.reloadPage = function(shouldIgnoreCache)
-{
-    console.assert(!this._testPageIsReloading);
-    console.assert(!this._testPageReloadedOnce);
-
-    this._testPageIsReloading = true;
-
-    return PageAgent.reload(!!shouldIgnoreCache)
-        .then(function() {
-            this._shouldResendResults = true;
-            this._testPageReloadedOnce = true;
-
-            return Promise.resolve(null);
-        }.bind(this));
-}
-
-InspectorTest.reportUncaughtException = function(message, url, lineNumber)
-{
-    var result = &quot;Uncaught exception in inspector page: &quot; + message + &quot; [&quot; + url + &quot;:&quot; + lineNumber + &quot;]&quot;;
-
-    // If the connection to the test page is not set up, then just dump to console and give up.
-    // Errors encountered this early can be debugged by loading Test.html in a normal browser page.
-    if (!InspectorFrontendHost || !InspectorBackend) {
-        this._originalConsoleMethods[&quot;error&quot;](result);
-        return false;
-    }
-
-    this.addResult(result);
-    this.completeTest();
-    // Stop default handler so we can empty InspectorBackend's message queue.
-    return true;
-}
-
-// Initialize reporting mechanisms before loading the rest of the inspector page.
-InspectorTest._results = [];
-InspectorTest._shouldResendResults = true;
-InspectorTest._originalConsoleMethods = {};
-
-// Catch syntax errors, type errors, and other exceptions.
-window.onerror = InspectorTest.reportUncaughtException.bind(InspectorTest);
-
-// Redirect frontend console methods to log messages into the test result.
-(function() {
-    function createProxyConsoleHandler(type) {
-        return function() {
-            InspectorTest.addResult(type + &quot;: &quot; + Array.from(arguments).join(&quot; &quot;));
-        };
-    }
-
-    for (var type of [&quot;log&quot;, &quot;error&quot;, &quot;info&quot;]) {
-        InspectorTest._originalConsoleMethods[type] = console[type].bind(console);
-        console[type] = createProxyConsoleHandler(type.toUpperCase());
-    }
-})();
</del></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceBaseTestStubjs"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebInspectorUI/UserInterface/Base/TestStub.js (188638 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Base/TestStub.js        2015-08-19 15:38:14 UTC (rev 188638)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/TestStub.js        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -1,480 +0,0 @@
</span><del>-/*
- * Copyright (C) 2012 Samsung Electronics. All rights reserved.
- * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS &quot;AS IS&quot; AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-InspectorFrontendAPI = {};
-
-InjectedTestHarness = class InjectedTestHarness
-{
-    constructor()
-    {
-        this._logCount = 0;
-        this.forceSyncDebugLogging = false;
-    }
-
-    completeTest()
-    {
-        throw new Error(&quot;Must be implemented by subclasses.&quot;);
-    }
-
-    addResult()
-    {
-        throw new Error(&quot;Must be implemented by subclasses.&quot;);
-    }
-
-    debugLog()
-    {
-        throw new Error(&quot;Must be implemented by subclasses.&quot;);
-    }
-
-    evaluateInPage(string, callback)
-    {
-        throw new Error(&quot;Must be implemented by subclasses.&quot;);
-    }
-
-    createAsyncSuite(name)
-    {
-        return new InjectedTestHarness.AsyncTestSuite(this, name);
-    }
-
-    createSyncSuite(name)
-    {
-        return new InjectedTestHarness.SyncTestSuite(this, name);
-    }
-
-    get logCount()
-    {
-        return this._logCount;
-    }
-
-    log(message)
-    {
-        ++this._logCount;
-
-        if (this.forceSyncDebugLogging)
-            this.debugLog(message);
-        else
-            this.addResult(message);
-    }
-
-    assert(condition, message)
-    {
-        if (condition)
-            return;
-
-        let stringifiedMessage = typeof message !== &quot;object&quot; ? message : JSON.stringify(message);
-        this.addResult(&quot;ASSERT: &quot; + stringifiedMessage);
-    }
-
-    expectThat(condition, message)
-    {
-        let prefix = condition ? &quot;PASS&quot; : &quot;FAIL&quot;;
-        let stringifiedMessage = typeof message !== &quot;object&quot; ? message : JSON.stringify(message);
-        this.addResult(prefix + &quot;: &quot; + stringifiedMessage);
-    }
-}
-
-InjectedTestHarness.AsyncTestSuite = class AsyncTestSuite
-{
-    constructor(harness, name) {
-        if (!(harness instanceof InjectedTestHarness))
-            throw new Error(&quot;Must pass the test's harness as the first argument.&quot;);
-
-        if (!name || typeof name !== &quot;string&quot;)
-            throw new Error(&quot;Tried to create AsyncTestSuite without string suite name.&quot;);
-
-        this.name = name;
-        this._harness = harness;
-
-        this.testcases = [];
-        this.runCount = 0;
-        this.failCount = 0;
-    }
-
-    get passCount()
-    {
-        return this.runCount - this.failCount;
-    }
-
-    get skipCount()
-    {
-        if (this.failCount)
-            return this.testcases.length - this.runCount;
-        else
-            return 0;
-    }
-
-    addTestCase(testcase)
-    {
-        if (!testcase || !(testcase instanceof Object))
-            throw new Error(&quot;Tried to add non-object test case.&quot;);
-
-        if (typeof testcase.name !== &quot;string&quot;)
-            throw new Error(&quot;Tried to add test case without a name.&quot;);
-
-        if (typeof testcase.test !== &quot;function&quot;)
-            throw new Error(&quot;Tried to add test case without `test` function.&quot;);
-
-        this.testcases.push(testcase);
-    }
-
-    // Use this if the test file only has one suite, and no handling
-    // of the promise returned by runTestCases() is needed.
-    runTestCasesAndFinish()
-    {
-        function finish() {
-            this._harness.completeTest();
-        }
-
-        this.runTestCases()
-            .then(finish.bind(this))
-            .catch(finish.bind(this));
-    }
-
-    runTestCases()
-    {
-        if (!this.testcases.length)
-            throw new Error(&quot;Tried to call runTestCases() for suite with no test cases&quot;);
-        if (this._startedRunning)
-            throw new Error(&quot;Tried to call runTestCases() more than once.&quot;);
-
-        this._startedRunning = true;
-
-        this._harness.log(&quot;&quot;);
-        this._harness.log(&quot;== Running test suite: &quot; + this.name);
-
-        // Avoid adding newlines if nothing was logged.
-        var priorLogCount = this._harness.logCount;
-        var suite = this;
-        var result = this.testcases.reduce(function(chain, testcase, i) {
-            return chain.then(function() {
-                if (i &gt; 0 &amp;&amp; priorLogCount + 1 &lt; suite._harness.logCount)
-                    suite._harness.log(&quot;&quot;);
-
-                priorLogCount = suite._harness.logCount;
-                suite._harness.log(&quot;-- Running test case: &quot; + testcase.name);
-                suite.runCount++;
-                return new Promise(testcase.test);
-            });
-        }, Promise.resolve());
-
-        return result.catch(function(e) {
-            suite.failCount++;
-            var message = e;
-            if (e instanceof Error)
-                message = e.message;
-
-            if (typeof message !== &quot;string&quot;)
-                message = JSON.stringify(message);
-
-            suite._harness.log(&quot;!! EXCEPTION: &quot; + message);
-            throw e; // Reject this promise by re-throwing the error.
-        });
-    }
-}
-
-InjectedTestHarness.SyncTestSuite = class SyncTestSuite
-{
-    constructor(harness, name) {
-        if (!(harness instanceof InjectedTestHarness))
-            throw new Error(&quot;Must pass the test's harness as the first argument.&quot;);
-
-        if (!name || typeof name !== &quot;string&quot;)
-            throw new Error(&quot;Tried to create SyncTestSuite without string suite name.&quot;);
-
-        this.name = name;
-        this._harness = harness;
-
-        this.testcases = [];
-        this.runCount = 0;
-        this.failCount = 0;
-    }
-
-    get passCount()
-    {
-        return this.runCount - this.failCount;
-    }
-
-    get skipCount()
-    {
-        if (this.failCount)
-            return this.testcases.length - this.runCount;
-        else
-            return 0;
-    }
-
-    addTestCase(testcase)
-    {
-        if (!testcase || !(testcase instanceof Object))
-            throw new Error(&quot;Tried to add non-object test case.&quot;);
-
-        if (typeof testcase.name !== &quot;string&quot;)
-            throw new Error(&quot;Tried to add test case without a name.&quot;);
-
-        if (typeof testcase.test !== &quot;function&quot;)
-            throw new Error(&quot;Tried to add test case without `test` function.&quot;);
-
-        this.testcases.push(testcase);
-    }
-
-    // Use this if the test file only has one suite.
-    runTestCasesAndFinish()
-    {
-        this.runTestCases();
-        this._harness.completeTest();
-    }
-
-    runTestCases()
-    {
-        if (!this.testcases.length)
-            throw new Error(&quot;Tried to call runTestCases() for suite with no test cases&quot;);
-        if (this._startedRunning)
-            throw new Error(&quot;Tried to call runTestCases() more than once.&quot;);
-
-        this._startedRunning = true;
-
-        this._harness.log(&quot;&quot;);
-        this._harness.log(&quot;== Running test suite: &quot; + this.name);
-
-        var priorLogCount = this._harness.logCount;
-        var suite = this;
-        for (var i = 0; i &lt; this.testcases.length; i++) {
-            var testcase = this.testcases[i];
-            if (i &gt; 0 &amp;&amp; priorLogCount + 1 &lt; this._harness.logCount)
-                this._harness.log(&quot;&quot;);
-
-            priorLogCount = this._harness.logCount;
-
-            this._harness.log(&quot;-- Running test case: &quot; + testcase.name);
-            suite.runCount++;
-            try {
-                var result = testcase.test.call(null);
-                if (result === false) {
-                    suite.failCount++;
-                    return false;
-                }
-            } catch (e) {
-                suite.failCount++;
-                var message = e;
-                if (e instanceof Error)
-                    message = e.message;
-                else
-                    e = new Error(e);
-
-                if (typeof message !== &quot;string&quot;)
-                    message = JSON.stringify(message);
-
-                this._harness.log(&quot;!! EXCEPTION: &quot; + message);
-                return false;
-            }
-        }
-
-        return true;
-    }
-}
-
-class ProtocolTestHarness extends InjectedTestHarness
-{
-    // InjectedTestHarness Overrides
-
-    completeTest()
-    {
-        this.evaluateInPage(&quot;closeTest();&quot;);
-    }
-
-    addResult(message)
-    {
-        // Unfortunately, every string argument must be escaped because tests are not consistent
-        // with respect to escaping with single or double quotes. Some exceptions use single quotes.
-        var stringifiedMessage = typeof message !== &quot;string&quot; ? JSON.stringify(message) : message;
-        this.evaluateInPage(&quot;log(unescape('&quot; + escape(stringifiedMessage) + &quot;'));&quot;);
-    }
-
-    debugLog(message)
-    {
-        var stringifiedMessage = typeof message !== &quot;string&quot; ? JSON.stringify(message) : message;
-        this.evaluateInPage(&quot;debugLog(unescape('&quot; + escape(stringifiedMessage) + &quot;'));&quot;)
-    }
-
-    evaluateInPage(expression, callback)
-    {
-        let args = {
-            method: &quot;Runtime.evaluate&quot;,
-            params: {expression}
-        }
-
-        if (typeof callback === &quot;function&quot;)
-            InspectorProtocol.sendCommand(args, callback);
-        else
-            return InspectorProtocol.awaitCommand(args);
-    }
-}
-
-window.ProtocolTest = new ProtocolTestHarness();
-
-InspectorProtocol = {};
-InspectorProtocol._dispatchTable = [];
-InspectorProtocol._requestId = -1;
-InspectorProtocol.eventHandler = {};
-
-InspectorProtocol.dumpInspectorProtocolMessages = false;
-
-InspectorProtocol.sendCommand = function(methodOrObject, params, handler)
-{
-    // Allow new-style arguments object, as in awaitCommand.
-    var method = methodOrObject;
-    if (typeof methodOrObject === &quot;object&quot;)
-        var {method, params, handler} = methodOrObject;
-
-    this._dispatchTable[++this._requestId] = handler;
-    var messageObject = {method, params, &quot;id&quot;: this._requestId};
-    this.sendMessage(messageObject);
-
-    return this._requestId;
-}
-
-InspectorProtocol.awaitCommand = function(args)
-{
-    var {method, params} = args;
-    return new Promise(function(resolve, reject) {
-        this._dispatchTable[++this._requestId] = {resolve, reject};
-        var messageObject = {method, params, &quot;id&quot;: this._requestId};
-        this.sendMessage(messageObject);
-    }.bind(this));
-}
-
-InspectorProtocol.awaitEvent = function(args)
-{
-    var {event} = args;
-    if (typeof event !== &quot;string&quot;)
-        throw new Error(&quot;Event must be a string.&quot;);
-
-    return new Promise(function(resolve, reject) {
-        InspectorProtocol.eventHandler[event] = function(message) {
-            InspectorProtocol.eventHandler[event] = undefined;
-            resolve(message);
-        }
-    });
-}
-
-InspectorProtocol.addEventListener = function(eventTypeOrObject, listener)
-{
-    var event = eventTypeOrObject;
-    if (typeof eventTypeOrObject === &quot;object&quot;)
-        var {event, listener} = eventTypeOrObject;
-
-    if (typeof event !== &quot;string&quot;)
-        throw new Error(&quot;Event name must be a string.&quot;);
-
-    if (typeof listener !== &quot;function&quot;)
-        throw new Error(&quot;Event listener must be callable.&quot;);
-
-    // Convert to an array of listeners.
-    var listeners = InspectorProtocol.eventHandler[event];
-    if (!listeners)
-        listeners = InspectorProtocol.eventHandler[event] = [];
-    else if (typeof listeners === &quot;function&quot;)
-        listeners = InspectorProtocol.eventHandler[event] = [listeners];
-
-    // Prevent registering multiple times.
-    if (listeners.includes(listener))
-        throw new Error(&quot;Cannot register the same listener more than once.&quot;);
-
-    listeners.push(listener);
-}
-
-InspectorProtocol.sendMessage = function(messageObject)
-{
-    // This matches the debug dumping in InspectorBackend, which is bypassed
-    // by InspectorProtocol. Return messages should be dumped by InspectorBackend.
-    if (InspectorProtocol.dumpInspectorProtocolMessages)
-        console.log(&quot;frontend: &quot; + JSON.stringify(messageObject));
-
-    InspectorFrontendHost.sendMessageToBackend(JSON.stringify(messageObject));
-}
-
-InspectorProtocol.checkForError = function(responseObject)
-{
-    if (responseObject.error) {
-        ProtocolTest.log(&quot;PROTOCOL ERROR: &quot; + JSON.stringify(responseObject.error));
-        ProtocolTest.completeTest();
-        throw &quot;PROTOCOL ERROR&quot;;
-    }
-}
-
-InspectorFrontendAPI.dispatchMessageAsync = function(messageObject)
-{
-    // This matches the debug dumping in InspectorBackend, which is bypassed
-    // by InspectorProtocol. Return messages should be dumped by InspectorBackend.
-    if (InspectorProtocol.dumpInspectorProtocolMessages)
-        console.log(&quot;backend: &quot; + JSON.stringify(messageObject));
-
-    // If the message has an id, then it is a reply to a command.
-    var messageId = messageObject[&quot;id&quot;];
-    if (typeof messageId === &quot;number&quot;) {
-        var handler = InspectorProtocol._dispatchTable[messageId];
-        if (!handler)
-            return;
-
-        if (typeof handler === &quot;function&quot;)
-            handler(messageObject);
-        else if (typeof handler === &quot;object&quot;) {
-            var {resolve, reject} = handler;
-            if (&quot;error&quot; in messageObject)
-                reject(messageObject.error.message);
-            else
-                resolve(messageObject.result);
-        }
-    // Otherwise, it is an event.
-    } else {
-        var eventName = messageObject[&quot;method&quot;];
-        var handler = InspectorProtocol.eventHandler[eventName];
-        if (!handler)
-            return;
-
-        if (typeof handler === &quot;function&quot;)
-            handler(messageObject);
-        else if (handler instanceof Array) {
-            handler.map(function(listener) {
-                listener.call(null, messageObject);
-            });
-        } else if (typeof handler === &quot;object&quot;) {
-            var {resolve, reject} = handler;
-            if (&quot;error&quot; in messageObject)
-                reject(messageObject.error.message);
-            else
-                resolve(messageObject.result);
-        }
-    }
-}
-
-window.addEventListener(&quot;message&quot;, function(event) {
-    try {
-        eval(event.data);
-    } catch (e) {
-        alert(e.stack);
-        ProtocolTest.completeTest();
-        throw e;
-    }
-});
</del><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceTestInspectorProtocoljs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Test/InspectorProtocol.js (0 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Test/InspectorProtocol.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Test/InspectorProtocol.js        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -0,0 +1,157 @@
</span><ins>+/*
+ * Copyright (C) 2012 Samsung Electronics. All rights reserved.
+ * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS &quot;AS IS&quot; AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+InspectorProtocol = {};
+InspectorProtocol._dispatchTable = [];
+InspectorProtocol._requestId = -1;
+InspectorProtocol.eventHandler = {};
+
+InspectorProtocol.sendCommand = function(methodOrObject, params, handler)
+{
+    // Allow new-style arguments object, as in awaitCommand.
+    let method = methodOrObject;
+    if (typeof methodOrObject === &quot;object&quot;)
+        var {method, params, handler} = methodOrObject;
+
+    this._dispatchTable[++this._requestId] = handler;
+    let messageObject = {method, params, id: this._requestId};
+    this.sendMessage(messageObject);
+
+    return this._requestId;
+}
+
+InspectorProtocol.awaitCommand = function(args)
+{
+    let {method, params} = args;
+    return new Promise((resolve, reject) =&gt; {
+        this._dispatchTable[++this._requestId] = {resolve, reject};
+        let messageObject = {method, params, id: this._requestId};
+        this.sendMessage(messageObject);
+    });
+}
+
+InspectorProtocol.awaitEvent = function(args)
+{
+    let event = args.event;
+    if (typeof event !== &quot;string&quot;)
+        throw new Error(&quot;Event must be a string.&quot;);
+
+    return new Promise((resolve, reject) =&gt; {
+        InspectorProtocol.eventHandler[event] = function(message) {
+            InspectorProtocol.eventHandler[event] = undefined;
+            resolve(message);
+        }
+    });
+}
+
+InspectorProtocol.addEventListener = function(eventTypeOrObject, listener)
+{
+    let event = eventTypeOrObject;
+    if (typeof eventTypeOrObject === &quot;object&quot;)
+        var {event, listener} = eventTypeOrObject;
+
+    if (typeof event !== &quot;string&quot;)
+        throw new Error(&quot;Event name must be a string.&quot;);
+
+    if (typeof listener !== &quot;function&quot;)
+        throw new Error(&quot;Event listener must be callable.&quot;);
+
+    // Convert to an array of listeners.
+    let listeners = InspectorProtocol.eventHandler[event];
+    if (!listeners)
+        listeners = InspectorProtocol.eventHandler[event] = [];
+    else if (typeof listeners === &quot;function&quot;)
+        listeners = InspectorProtocol.eventHandler[event] = [listeners];
+
+    // Prevent registering multiple times.
+    if (listeners.includes(listener))
+        throw new Error(&quot;Cannot register the same listener more than once.&quot;);
+
+    listeners.push(listener);
+}
+
+InspectorProtocol.sendMessage = function(messageObject)
+{
+    // This matches the debug dumping in InspectorBackend, which is bypassed
+    // by InspectorProtocol. Return messages should be dumped by InspectorBackend.
+    if (ProtocolTest.dumpInspectorProtocolMessages)
+        console.log(&quot;frontend: &quot; + JSON.stringify(messageObject));
+
+    InspectorFrontendHost.sendMessageToBackend(JSON.stringify(messageObject));
+}
+
+InspectorProtocol.checkForError = function(responseObject)
+{
+    if (responseObject.error) {
+        ProtocolTest.log(&quot;PROTOCOL ERROR: &quot; + JSON.stringify(responseObject.error));
+        ProtocolTest.completeTest();
+        throw &quot;PROTOCOL ERROR&quot;;
+    }
+}
+
+InspectorProtocol.dispatchMessageFromBackend = function(messageObject)
+{
+    // This matches the debug dumping in InspectorBackend, which is bypassed
+    // by InspectorProtocol. Return messages should be dumped by InspectorBackend.
+    if (ProtocolTest.dumpInspectorProtocolMessages)
+        console.log(&quot;backend: &quot; + JSON.stringify(messageObject));
+
+    // If the message has an id, then it is a reply to a command.
+    let messageId = messageObject.id;
+    if (typeof messageId === &quot;number&quot;) {
+        let handler = InspectorProtocol._dispatchTable[messageId];
+        if (!handler)
+            return;
+
+        if (typeof handler === &quot;function&quot;)
+            handler(messageObject);
+        else if (typeof handler === &quot;object&quot;) {
+            let {resolve, reject} = handler;
+            if (&quot;error&quot; in messageObject)
+                reject(messageObject.error.message);
+            else
+                resolve(messageObject.result);
+        }
+    } else {
+        // Otherwise, it is an event.
+        let eventName = messageObject[&quot;method&quot;];
+        let handler = InspectorProtocol.eventHandler[eventName];
+        if (!handler)
+            return;
+
+        if (typeof handler === &quot;function&quot;)
+            handler(messageObject);
+        else if (handler instanceof Array) {
+            handler.map((listener) =&gt; { listener.call(null, messageObject); });
+        } else if (typeof handler === &quot;object&quot;) {
+            let {resolve, reject} = handler;
+            if (&quot;error&quot; in messageObject)
+                reject(messageObject.error.message);
+            else
+                resolve(messageObject.result);
+        }
+    }
+}
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceTestProtocolTestHarnessjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Test/ProtocolTestHarness.js (0 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Test/ProtocolTestHarness.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Test/ProtocolTestHarness.js        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -0,0 +1,61 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS &quot;AS IS&quot; AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ProtocolTestHarness = class ProtocolTestHarness extends TestHarness
+{
+    // TestHarness Overrides
+
+    completeTest()
+    {
+        this.evaluateInPage(&quot;TestPage.closeTest();&quot;);
+    }
+
+    addResult(message)
+    {
+        // Unfortunately, every string argument must be escaped because tests are not consistent
+        // with respect to escaping with single or double quotes. Some exceptions use single quotes.
+        let stringifiedMessage = typeof message !== &quot;string&quot; ? JSON.stringify(message) : message;
+        this.evaluateInPage(`TestPage.log(unescape(&quot;${escape(stringifiedMessage)}&quot;));`);
+    }
+
+    debugLog(message)
+    {
+        let stringifiedMessage = typeof message !== &quot;string&quot; ? JSON.stringify(message) : message;
+        this.evaluateInPage(`TestPage.debugLog(unescape(&quot;${escape(stringifiedMessage)}&quot;));`);
+    }
+
+    evaluateInPage(expression, callback)
+    {
+        let args = {
+            method: &quot;Runtime.evaluate&quot;,
+            params: {expression}
+        }
+
+        if (typeof callback === &quot;function&quot;)
+            InspectorProtocol.sendCommand(args, callback);
+        else
+            return InspectorProtocol.awaitCommand(args);
+    }
+}
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceTestTestjsfromrev188638trunkSourceWebInspectorUIUserInterfaceBaseTestjs"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebInspectorUI/UserInterface/Test/Test.js (from rev 188638, trunk/Source/WebInspectorUI/UserInterface/Base/Test.js) (0 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Test/Test.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Test/Test.js        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -0,0 +1,279 @@
</span><ins>+/*
+ * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS
+ * IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DebuggableType = {
+    Web: &quot;web&quot;,
+    JavaScript: &quot;javascript&quot;
+};
+
+WebInspector.loaded = function()
+{
+    this.debuggableType = WebInspector.DebuggableType.Web;
+    this.hasExtraDomains = false;
+
+    // Register observers for events from the InspectorBackend.
+    // The initialization order should match the same in Main.js.
+    InspectorBackend.registerInspectorDispatcher(new WebInspector.InspectorObserver);
+    InspectorBackend.registerPageDispatcher(new WebInspector.PageObserver);
+    InspectorBackend.registerConsoleDispatcher(new WebInspector.ConsoleObserver);
+    InspectorBackend.registerDOMDispatcher(new WebInspector.DOMObserver);
+    InspectorBackend.registerNetworkDispatcher(new WebInspector.NetworkObserver);
+    InspectorBackend.registerDebuggerDispatcher(new WebInspector.DebuggerObserver);
+    InspectorBackend.registerTimelineDispatcher(new WebInspector.TimelineObserver);
+    InspectorBackend.registerCSSDispatcher(new WebInspector.CSSObserver);
+    InspectorBackend.registerRuntimeDispatcher(new WebInspector.RuntimeObserver);
+    if (InspectorBackend.registerReplayDispatcher)
+        InspectorBackend.registerReplayDispatcher(new WebInspector.ReplayObserver);
+
+    // Instantiate controllers used by tests.
+    this.frameResourceManager = new WebInspector.FrameResourceManager;
+    this.domTreeManager = new WebInspector.DOMTreeManager;
+    this.cssStyleManager = new WebInspector.CSSStyleManager;
+    this.logManager = new WebInspector.LogManager;
+    this.issueManager = new WebInspector.IssueManager;
+    this.runtimeManager = new WebInspector.RuntimeManager;
+    this.timelineManager = new WebInspector.TimelineManager;
+    this.debuggerManager = new WebInspector.DebuggerManager;
+    this.probeManager = new WebInspector.ProbeManager;
+    this.replayManager = new WebInspector.ReplayManager;
+
+    // Global controllers.
+    this.quickConsole = {executionContextIdentifier: undefined};
+
+    document.addEventListener(&quot;DOMContentLoaded&quot;, this.contentLoaded.bind(this));
+
+    // Enable agents.
+    InspectorAgent.enable();
+    ConsoleAgent.enable();
+
+    // Perform one-time tasks.
+    WebInspector.CSSCompletions.requestCSSCompletions();
+
+    // Global settings.
+    this.showShadowDOMSetting = new WebInspector.Setting(&quot;show-shadow-dom&quot;, true);
+}
+
+WebInspector.contentLoaded = function()
+{
+    // Signal that the frontend is now ready to receive messages.
+    InspectorFrontendAPI.loadCompleted();
+
+    // Tell the InspectorFrontendHost we loaded, which causes the window to display
+    // and pending InspectorFrontendAPI commands to be sent.
+    InspectorFrontendHost.loaded();
+}
+
+WebInspector.UIString = function(string)
+{
+    return string;
+}
+
+// Add stubs that are called by the frontend API.
+WebInspector.updateDockedState = function() {};
+WebInspector.updateDockingAvailability = function() {};
+
+// InspectorTest contains extra methods that are only available to test code running
+// in the Web Inspector page. They rely on equivalents in the actual test page
+// which are provided by `inspector-test.js`.
+InspectorTest = {};
+
+// This is useful for debugging Inspector tests by synchronously logging messages.
+InspectorTest.dumpMessagesToConsole = false;
+
+// This is a workaround for the fact that it would be hard to set up a constructor,
+// prototype, and prototype chain for the singleton InspectorTest.
+InspectorTest.EventDispatcher = class EventDispatcher extends WebInspector.Object
+{
+    dispatchEvent(event)
+    {
+        this.dispatchEventToListeners(event);
+    }
+};
+
+InspectorTest.EventDispatcher.Event = {
+    TestPageDidLoad: &quot;inspector-test-test-page-did-load&quot;
+};
+
+InspectorTest.eventDispatcher = new InspectorTest.EventDispatcher;
+
+// Note: Additional InspectorTest methods are included on a per-test basis from
+// files like `debugger-test.js`.
+
+// Appends a log message in the test document.
+InspectorTest.log = function(message)
+{
+    var stringifiedMessage = typeof message !== &quot;object&quot; ? message : JSON.stringify(message);
+    InspectorTest.addResult(stringifiedMessage);
+}
+
+// Appends a message in the test document only if the condition is false.
+InspectorTest.assert = function(condition, message)
+{
+    if (condition)
+        return;
+
+    var stringifiedMessage = typeof message !== &quot;object&quot; ? message : JSON.stringify(message);
+    InspectorTest.addResult(&quot;ASSERT: &quot; + stringifiedMessage);
+}
+
+// Appends a message in the test document whether the condition is true or not.
+InspectorTest.expectThat = function(condition, message)
+{
+    var prefix = condition ? &quot;PASS&quot; : &quot;FAIL&quot;;
+    var stringifiedMessage = typeof message !== &quot;object&quot; ? message : JSON.stringify(message);
+    InspectorTest.addResult(prefix + &quot;: &quot; + stringifiedMessage);
+}
+
+// This function should only be used to debug tests and not to produce normal test output.
+InspectorTest.debugLog = function(message)
+{
+    if (InspectorTest.dumpMessagesToConsole)
+        InspectorFrontendHost.unbufferedLog(&quot;debugLog: &quot; + message);
+
+    this.evaluateInPage(&quot;InspectorTestProxy.debugLog(unescape('&quot; + escape(JSON.stringify(message)) + &quot;'))&quot;);
+}
+
+// Appends a message in the test document if there was an error, and attempts to complete the test.
+InspectorTest.expectNoError = function(error)
+{
+    if (error) {
+        InspectorTest.log(&quot;PROTOCOL ERROR: &quot; + error);
+        InspectorTest.completeTest();
+        throw &quot;PROTOCOL ERROR&quot;;
+    }
+}
+
+InspectorTest.completeTest = function()
+{
+    if (InspectorTest.dumpMessagesToConsole)
+        InspectorFrontendHost.unbufferedLog(&quot;InspectorTest.completeTest()&quot;);
+
+    // Wait for results to be resent before requesting completeTest(). Otherwise, messages will be
+    // queued after pending dispatches run to zero and the test page will quit before processing them.
+    if (this._testPageIsReloading) {
+        this._completeTestAfterReload = true;
+        return;
+    }
+
+    InspectorBackend.runAfterPendingDispatches(this.evaluateInPage.bind(this, &quot;InspectorTestProxy.completeTest()&quot;));
+}
+
+InspectorTest.evaluateInPage = function(codeString, callback)
+{
+    // If we load this page outside of the inspector, or hit an early error when loading
+    // the test frontend, then defer evaluating the commands (indefinitely in the former case).
+    if (!window.RuntimeAgent) {
+        this._originalConsoleMethods[&quot;error&quot;](&quot;Tried to evaluate in test page, but connection not yet established:&quot;, codeString);
+        return;
+    }
+
+    RuntimeAgent.evaluate.invoke({expression: codeString, objectGroup: &quot;test&quot;, includeCommandLineAPI: false}, callback);
+}
+
+InspectorTest.addResult = function(text)
+{
+    this._results.push(text);
+
+    if (InspectorTest.dumpMessagesToConsole)
+        InspectorFrontendHost.unbufferedLog(&quot;addResult: &quot; + text);
+
+    if (!this._testPageIsReloading)
+        this.evaluateInPage(&quot;InspectorTestProxy.addResult(unescape('&quot; + escape(text) + &quot;'))&quot;);
+}
+
+InspectorTest._resendResults = function()
+{
+    console.assert(this._shouldResendResults);
+    this._shouldResendResults = false;
+
+    for (var result of this._results)
+        this.evaluateInPage(&quot;InspectorTestProxy.addResult(unescape('&quot; + escape(result) + &quot;'))&quot;);
+}
+
+InspectorTest.testPageDidLoad = function()
+{
+    this._testPageIsReloading = false;
+    this._resendResults();
+
+    this.eventDispatcher.dispatchEvent(InspectorTest.EventDispatcher.Event.TestPageDidLoad);
+
+    if (this._completeTestAfterReload)
+        InspectorTest.completeTest();
+}
+
+InspectorTest.reloadPage = function(shouldIgnoreCache)
+{
+    console.assert(!this._testPageIsReloading);
+    console.assert(!this._testPageReloadedOnce);
+
+    this._testPageIsReloading = true;
+
+    return PageAgent.reload(!!shouldIgnoreCache)
+        .then(function() {
+            this._shouldResendResults = true;
+            this._testPageReloadedOnce = true;
+
+            return Promise.resolve(null);
+        }.bind(this));
+}
+
+InspectorTest.reportUncaughtException = function(message, url, lineNumber)
+{
+    var result = &quot;Uncaught exception in inspector page: &quot; + message + &quot; [&quot; + url + &quot;:&quot; + lineNumber + &quot;]&quot;;
+
+    // If the connection to the test page is not set up, then just dump to console and give up.
+    // Errors encountered this early can be debugged by loading Test.html in a normal browser page.
+    if (!InspectorFrontendHost || !InspectorBackend) {
+        this._originalConsoleMethods[&quot;error&quot;](result);
+        return false;
+    }
+
+    this.addResult(result);
+    this.completeTest();
+    // Stop default handler so we can empty InspectorBackend's message queue.
+    return true;
+}
+
+// Initialize reporting mechanisms before loading the rest of the inspector page.
+InspectorTest._results = [];
+InspectorTest._shouldResendResults = true;
+InspectorTest._originalConsoleMethods = {};
+
+// Catch syntax errors, type errors, and other exceptions.
+window.onerror = InspectorTest.reportUncaughtException.bind(InspectorTest);
+
+// Redirect frontend console methods to log messages into the test result.
+(function() {
+    function createProxyConsoleHandler(type) {
+        return function() {
+            InspectorTest.addResult(type + &quot;: &quot; + Array.from(arguments).join(&quot; &quot;));
+        };
+    }
+
+    for (var type of [&quot;log&quot;, &quot;error&quot;, &quot;info&quot;]) {
+        InspectorTest._originalConsoleMethods[type] = console[type].bind(console);
+        console[type] = createProxyConsoleHandler(type.toUpperCase());
+    }
+})();
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceTestTestHarnessjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Test/TestHarness.js (0 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Test/TestHarness.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Test/TestHarness.js        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -0,0 +1,95 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS &quot;AS IS&quot; AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+TestHarness = class TestHarness extends WebInspector.Object
+{
+    constructor()
+    {
+        super();
+
+        this._logCount = 0;
+    }
+
+    completeTest()
+    {
+        throw new Error(&quot;Must be implemented by subclasses.&quot;);
+    }
+
+    addResult()
+    {
+        throw new Error(&quot;Must be implemented by subclasses.&quot;);
+    }
+
+    debugLog()
+    {
+        throw new Error(&quot;Must be implemented by subclasses.&quot;);
+    }
+
+    evaluateInPage(string, callback)
+    {
+        throw new Error(&quot;Must be implemented by subclasses.&quot;);
+    }
+
+    createAsyncSuite(name)
+    {
+        return new AsyncTestSuite(this, name);
+    }
+
+    createSyncSuite(name)
+    {
+        return new SyncTestSuite(this, name);
+    }
+
+    get logCount()
+    {
+        return this._logCount;
+    }
+
+    log(message)
+    {
+        ++this._logCount;
+
+        if (this.forceSyncDebugLogging)
+            this.debugLog(message);
+        else
+            this.addResult(message);
+    }
+
+    assert(condition, message)
+    {
+        if (condition)
+            return;
+
+        let stringifiedMessage = typeof message !== &quot;object&quot; ? message : JSON.stringify(message);
+        this.addResult(&quot;ASSERT: &quot; + stringifiedMessage);
+    }
+
+    expectThat(condition, message)
+    {
+        let prefix = condition ? &quot;PASS&quot; : &quot;FAIL&quot;;
+        let stringifiedMessage = typeof message !== &quot;object&quot; ? message : JSON.stringify(message);
+        this.addResult(`${prefix}: ${stringifiedMessage}`);
+    }
+};
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceTestTestStubjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Test/TestStub.js (0 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Test/TestStub.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Test/TestStub.js        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -0,0 +1,40 @@
</span><ins>+/*
+ * Copyright (C) 2012 Samsung Electronics. All rights reserved.
+ * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS &quot;AS IS&quot; AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+InspectorFrontendAPI = {};
+InspectorFrontendAPI.dispatchMessageAsync = InspectorProtocol.dispatchMessageFromBackend;
+
+window.ProtocolTest = new ProtocolTestHarness();
+
+window.addEventListener(&quot;message&quot;, (event) =&gt; {
+    try {
+        eval(event.data);
+    } catch (e) {
+        alert(e.stack);
+        ProtocolTest.completeTest();
+        throw e;
+    }
+});
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceTestTestSuitejs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Test/TestSuite.js (0 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Test/TestSuite.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Test/TestSuite.js        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -0,0 +1,192 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS &quot;AS IS&quot; AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+TestSuite = class TestSuite extends WebInspector.Object
+{
+    constructor(harness, name) {
+        if (!(harness instanceof TestHarness))
+            throw new Error(&quot;Must pass the test's harness as the first argument.&quot;);
+
+        if (typeof name !== &quot;string&quot; || !name.trim().length)
+            throw new Error(&quot;Tried to create TestSuite without string suite name.&quot;);
+
+        super();
+
+        this.name = name;
+        this._harness = harness;
+
+        this.testcases = [];
+        this.runCount = 0;
+        this.failCount = 0;
+    }
+
+    // Use this if the test file only has one suite, and no handling
+    // of the value returned by runTestCases() is needed.
+    runTestCasesAndFinish()
+    {
+        throw new Error(&quot;Must be implemented by subclasses.&quot;);
+    }
+
+    runTestCases()
+    {
+        throw new Error(&quot;Must be implemented by subclasses.&quot;);
+    }
+
+    get passCount()
+    {
+        return this.runCount - this.failCount;
+    }
+
+    get skipCount()
+    {
+        if (this.failCount)
+            return this.testcases.length - this.runCount;
+        else
+            return 0;
+    }
+
+    addTestCase(testcase)
+    {
+        if (!testcase || !(testcase instanceof Object))
+            throw new Error(&quot;Tried to add non-object test case.&quot;);
+
+        if (typeof testcase.name !== &quot;string&quot; || !testcase.name.trim().length)
+            throw new Error(&quot;Tried to add test case without a name.&quot;);
+
+        if (typeof testcase.test !== &quot;function&quot;)
+            throw new Error(&quot;Tried to add test case without `test` function.&quot;);
+
+        this.testcases.push(testcase);
+    }
+};
+
+AsyncTestSuite = class AsyncTestSuite extends TestSuite
+{
+    runTestCasesAndFinish()
+    {
+        let finish = () =&gt; { this._harness.completeTest(); };
+
+        this.runTestCases()
+            .then(finish)
+            .catch(finish);
+    }
+
+    runTestCases()
+    {
+        if (!this.testcases.length)
+            throw new Error(&quot;Tried to call runTestCases() for suite with no test cases&quot;);
+        if (this._startedRunning)
+            throw new Error(&quot;Tried to call runTestCases() more than once.&quot;);
+
+        this._startedRunning = true;
+
+        this._harness.log(&quot;&quot;);
+        this._harness.log(&quot;== Running test suite: &quot; + this.name);
+
+        // Avoid adding newlines if nothing was logged.
+        let priorLogCount = this._harness.logCount;
+        let result = this.testcases.reduce((chain, testcase, i) =&gt; {
+            return chain.then(() =&gt; {
+                if (i &gt; 0 &amp;&amp; priorLogCount + 1 &lt; this._harness.logCount)
+                    this._harness.log(&quot;&quot;);
+
+                priorLogCount = this._harness.logCount;
+                this._harness.log(&quot;-- Running test case: &quot; + testcase.name);
+                this.runCount++;
+                return new Promise(testcase.test);
+            });
+        }, Promise.resolve());
+
+        return result.catch((e) =&gt; {
+            this.failCount++;
+            let message = e;
+            if (e instanceof Error)
+                message = e.message;
+
+            if (typeof message !== &quot;string&quot;)
+                message = JSON.stringify(message);
+
+            this._harness.log(&quot;!! EXCEPTION: &quot; + message);
+            throw e; // Reject this promise by re-throwing the error.
+        });
+    }
+};
+
+SyncTestSuite = class SyncTestSuite extends TestSuite
+{
+    runTestCasesAndFinish()
+    {
+        this.runTestCases();
+        this._harness.completeTest();
+    }
+
+    runTestCases()
+    {
+        if (!this.testcases.length)
+            throw new Error(&quot;Tried to call runTestCases() for suite with no test cases&quot;);
+        if (this._startedRunning)
+            throw new Error(&quot;Tried to call runTestCases() more than once.&quot;);
+
+        this._startedRunning = true;
+
+        this._harness.log(&quot;&quot;);
+        this._harness.log(&quot;== Running test suite: &quot; + this.name);
+
+        let priorLogCount = this._harness.logCount;
+        let self = this;
+        for (let i = 0; i &lt; this.testcases.length; i++) {
+            let testcase = this.testcases[i];
+            if (i &gt; 0 &amp;&amp; priorLogCount + 1 &lt; this._harness.logCount)
+                this._harness.log(&quot;&quot;);
+
+            priorLogCount = this._harness.logCount;
+
+            this._harness.log(&quot;-- Running test case: &quot; + testcase.name);
+            self.runCount++;
+            try {
+                let result = testcase.test.call(null);
+                if (result === false) {
+                    self.failCount++;
+                    return false;
+                }
+            } catch (e) {
+                self.failCount++;
+                let message = e;
+                if (e instanceof Error)
+                    message = e.message;
+                else
+                    e = new Error(e);
+
+                if (typeof message !== &quot;string&quot;)
+                    message = JSON.stringify(message);
+
+                this._harness.log(&quot;!! EXCEPTION: &quot; + message);
+                return false;
+            }
+        }
+
+        return true;
+    }
+};
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceTesthtml"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Test.html (188638 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Test.html        2015-08-19 15:38:14 UTC (rev 188638)
+++ trunk/Source/WebInspectorUI/UserInterface/Test.html        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -32,7 +32,7 @@
</span><span class="cx">     &lt;script src=&quot;Base/WebInspector.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Base/Object.js&quot;&gt;&lt;/script&gt;
</span><span class="cx"> 
</span><del>-    &lt;script src=&quot;Base/Test.js&quot;&gt;&lt;/script&gt;
</del><ins>+    &lt;script src=&quot;Test/Test.js&quot;&gt;&lt;/script&gt;
</ins><span class="cx"> 
</span><span class="cx">     &lt;script src=&quot;Base/DOMUtilities.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Base/EventListener.js&quot;&gt;&lt;/script&gt;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceTestStubhtml"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/TestStub.html (188638 => 188639)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/TestStub.html        2015-08-19 15:38:14 UTC (rev 188638)
+++ trunk/Source/WebInspectorUI/UserInterface/TestStub.html        2015-08-19 16:14:04 UTC (rev 188639)
</span><span class="lines">@@ -22,8 +22,29 @@
</span><span class="cx"> (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
</span><span class="cx"> THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx"> --&gt;
</span><ins>+&lt;!DOCTYPE html&gt;
</ins><span class="cx"> &lt;html&gt;
</span><span class="cx"> &lt;head&gt;
</span><del>-    &lt;script type=&quot;text/javascript&quot; src=&quot;Base/TestStub.js&quot;&gt;&lt;/script&gt;
</del><ins>+    &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;
+    &lt;!--
+    These resources should match the order and groups used in Main.html and Test.html.
+    --&gt;
+    &lt;script src=&quot;Base/WebInspector.js&quot;&gt;&lt;/script&gt;
+    &lt;script src=&quot;Base/Object.js&quot;&gt;&lt;/script&gt;
+
+    &lt;script src=&quot;Test/TestSuite.js&quot;&gt;&lt;/script&gt;
+    &lt;script src=&quot;Test/TestHarness.js&quot;&gt;&lt;/script&gt;
+    &lt;script src=&quot;Test/ProtocolTestHarness.js&quot;&gt;&lt;/script&gt;
+
+    &lt;script src=&quot;Test/InspectorProtocol.js&quot;&gt;&lt;/script&gt;
+
+    &lt;script src=&quot;Test/TestStub.js&quot;&gt;&lt;/script&gt;
+    &lt;script&gt;
+        // Not reliable unless console messages are dumped to console. See wiki for details.
+        ProtocolTest.dumpInspectorProtocolMessages = false;
+
+        // Synchronous logging may produce more output prior to a timeout.
+        ProtocolTest.forceSyncDebugLogging = false;
+    &lt;/script&gt;
</ins><span class="cx"> &lt;/head&gt;
</span><span class="cx"> &lt;/html&gt;
</span></span></pre>
</div>
</div>

</body>
</html>