<!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>[32343] trunk/tests/qunit/vendor: Update QUnit to v1.18.0</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" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/32343">32343</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/32343","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>jorbin</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2015-05-04 19:43:38 +0000 (Mon, 04 May 2015)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Update QUnit to v1.18.0

See https://github.com/jquery/qunit/blob/1.18.0/History.md for changes from 1.12.0 to now.  Mostly bug fixes and internal changes in preparation for QUnit v2.

See <a href="https://core.trac.wordpress.org/ticket/30824">#30824</a></pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunktestsqunitvendorqunitcss">trunk/tests/qunit/vendor/qunit.css</a></li>
<li><a href="#trunktestsqunitvendorqunitjs">trunk/tests/qunit/vendor/qunit.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunktestsqunitvendorqunitcss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/qunit/vendor/qunit.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/qunit/vendor/qunit.css        2015-05-04 13:09:14 UTC (rev 32342)
+++ trunk/tests/qunit/vendor/qunit.css  2015-05-04 19:43:38 UTC (rev 32343)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,11 +1,12 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * QUnit v1.12.0 - A JavaScript Unit Testing Framework
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/*!
+ * QUnit 1.18.0
+ * http://qunitjs.com/
</ins><span class="cx" style="display: block; padding: 0 10px">  *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * http://qunitjs.com
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
</ins><span class="cx" style="display: block; padding: 0 10px">  *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Date: 2015-04-03T10:23Z
</ins><span class="cx" style="display: block; padding: 0 10px">  */
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /** Font Family and Sizes */
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -31,32 +32,29 @@
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-header {
</span><span class="cx" style="display: block; padding: 0 10px">        padding: 0.5em 0 0.5em 1em;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        color: #8699a4;
-       background-color: #0d3349;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ color: #8699A4;
+       background-color: #0D3349;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        font-size: 1.5em;
</span><span class="cx" style="display: block; padding: 0 10px">        line-height: 1em;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        font-weight: normal;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ font-weight: 400;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        border-radius: 5px 5px 0 0;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        -moz-border-radius: 5px 5px 0 0;
-       -webkit-border-top-right-radius: 5px;
-       -webkit-border-top-left-radius: 5px;
</del><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-header a {
</span><span class="cx" style="display: block; padding: 0 10px">        text-decoration: none;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        color: #c2ccd1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ color: #C2CCD1;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-header a:hover,
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-header a:focus {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        color: #fff;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ color: #FFF;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-testrunner-toolbar label {
</span><span class="cx" style="display: block; padding: 0 10px">        display: inline-block;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        padding: 0 .5em 0 .1em;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ padding: 0 0.5em 0 0.1em;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-banner {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -64,23 +62,35 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-testrunner-toolbar {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        padding: 0.5em 0 0.5em 2em;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ padding: 0.5em 1em 0.5em 1em;
</ins><span class="cx" style="display: block; padding: 0 10px">         color: #5E740B;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        background-color: #eee;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ background-color: #EEE;
</ins><span class="cx" style="display: block; padding: 0 10px">         overflow: hidden;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-userAgent {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        padding: 0.5em 0 0.5em 2.5em;
-       background-color: #2b81af;
-       color: #fff;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ padding: 0.5em 1em 0.5em 1em;
+       background-color: #2B81AF;
+       color: #FFF;
</ins><span class="cx" style="display: block; padding: 0 10px">         text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-modulefilter-container {
</span><span class="cx" style="display: block; padding: 0 10px">        float: right;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        padding: 0.2em;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.qunit-url-config {
+       display: inline-block;
+       padding: 0.1em;
+}
+
+.qunit-filter {
+       display: block;
+       float: right;
+       margin-left: 1em;
+}
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /** Tests: Pass/Fail */
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -88,24 +98,51 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests li {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        padding: 0.4em 0.5em 0.4em 2.5em;
-       border-bottom: 1px solid #fff;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ padding: 0.4em 1em 0.4em 1em;
+       border-bottom: 1px solid #FFF;
</ins><span class="cx" style="display: block; padding: 0 10px">         list-style-position: inside;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running  {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+#qunit-tests > li {
</ins><span class="cx" style="display: block; padding: 0 10px">         display: none;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+#qunit-tests li.running,
+#qunit-tests li.pass,
+#qunit-tests li.fail,
+#qunit-tests li.skipped {
+       display: list-item;
+}
+
+#qunit-tests.hidepass li.running,
+#qunit-tests.hidepass li.pass {
+       visibility: hidden;
+       position: absolute;
+       width:   0px;
+       height:  0px;
+       padding: 0;
+       border:  0;
+       margin:  0;
+}
+
</ins><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests li strong {
</span><span class="cx" style="display: block; padding: 0 10px">        cursor: pointer;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+#qunit-tests li.skipped strong {
+       cursor: default;
+}
+
</ins><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests li a {
</span><span class="cx" style="display: block; padding: 0 10px">        padding: 0.5em;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        color: #c2ccd1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ color: #C2CCD1;
</ins><span class="cx" style="display: block; padding: 0 10px">         text-decoration: none;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+#qunit-tests li p a {
+       padding: 0.25em;
+       color: #6B6464;
+}
</ins><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests li a:hover,
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests li a:focus {
</span><span class="cx" style="display: block; padding: 0 10px">        color: #000;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -120,11 +157,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">        margin-top: 0.5em;
</span><span class="cx" style="display: block; padding: 0 10px">        padding: 0.5em;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        background-color: #fff;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ background-color: #FFF;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        border-radius: 5px;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        -moz-border-radius: 5px;
-       -webkit-border-radius: 5px;
</del><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> .qunit-collapsed {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -133,13 +168,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests table {
</span><span class="cx" style="display: block; padding: 0 10px">        border-collapse: collapse;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        margin-top: .2em;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ margin-top: 0.2em;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests th {
</span><span class="cx" style="display: block; padding: 0 10px">        text-align: right;
</span><span class="cx" style="display: block; padding: 0 10px">        vertical-align: top;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        padding: 0 .5em 0 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ padding: 0 0.5em 0 0;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests td {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -153,26 +188,26 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests del {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        background-color: #e0f2be;
-       color: #374e0c;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ background-color: #E0F2BE;
+       color: #374E0C;
</ins><span class="cx" style="display: block; padding: 0 10px">         text-decoration: none;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests ins {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        background-color: #ffcaca;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ background-color: #FFCACA;
</ins><span class="cx" style="display: block; padding: 0 10px">         color: #500;
</span><span class="cx" style="display: block; padding: 0 10px">        text-decoration: none;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /*** Test Counts */
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-#qunit-tests b.counts                       { color: black; }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+#qunit-tests b.counts                       { color: #000; }
</ins><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests b.passed                       { color: #5E740B; }
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests b.failed                       { color: #710909; }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests li li {
</span><span class="cx" style="display: block; padding: 0 10px">        padding: 5px;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        background-color: #fff;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ background-color: #FFF;
</ins><span class="cx" style="display: block; padding: 0 10px">         border-bottom: none;
</span><span class="cx" style="display: block; padding: 0 10px">        list-style-position: inside;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -180,8 +215,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /*** Passing Styles */
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests li li.pass {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        color: #3c510c;
-       background-color: #fff;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ color: #3C510C;
+       background-color: #FFF;
</ins><span class="cx" style="display: block; padding: 0 10px">         border-left: 10px solid #C6E746;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -189,7 +224,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests .pass .test-name               { color: #366097; }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests .pass .test-actual,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-#qunit-tests .pass .test-expected           { color: #999999; }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+#qunit-tests .pass .test-expected           { color: #999; }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-banner.qunit-pass                    { background-color: #C6E746; }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -197,40 +232,52 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests li li.fail {
</span><span class="cx" style="display: block; padding: 0 10px">        color: #710909;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        background-color: #fff;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ background-color: #FFF;
</ins><span class="cx" style="display: block; padding: 0 10px">         border-left: 10px solid #EE5757;
</span><span class="cx" style="display: block; padding: 0 10px">        white-space: pre;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests > li:last-child {
</span><span class="cx" style="display: block; padding: 0 10px">        border-radius: 0 0 5px 5px;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        -moz-border-radius: 0 0 5px 5px;
-       -webkit-border-bottom-right-radius: 5px;
-       -webkit-border-bottom-left-radius: 5px;
</del><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-#qunit-tests .fail                          { color: #000000; background-color: #EE5757; }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+#qunit-tests .fail                          { color: #000; background-color: #EE5757; }
</ins><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests .fail .test-name,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-#qunit-tests .fail .module-name             { color: #000000; }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+#qunit-tests .fail .module-name             { color: #000; }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-tests .fail .test-actual             { color: #EE5757; }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-#qunit-tests .fail .test-expected           { color: green;   }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+#qunit-tests .fail .test-expected           { color: #008000; }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-banner.qunit-fail                    { background-color: #EE5757; }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/*** Skipped tests */
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+#qunit-tests .skipped {
+       background-color: #EBECE9;
+}
+
+#qunit-tests .qunit-skipped-label {
+       background-color: #F4FF77;
+       display: inline-block;
+       font-style: normal;
+       color: #366097;
+       line-height: 1.8em;
+       padding: 0 0.5em;
+       margin: -0.4em 0.4em -0.4em 0;
+}
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /** Result */
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-testresult {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        padding: 0.5em 0.5em 0.5em 2.5em;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ padding: 0.5em 1em 0.5em 1em;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        color: #2b81af;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ color: #2B81AF;
</ins><span class="cx" style="display: block; padding: 0 10px">         background-color: #D2E0E6;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        border-bottom: 1px solid white;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ border-bottom: 1px solid #FFF;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> #qunit-testresult .module-name {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        font-weight: bold;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ font-weight: 700;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /** Fixture */
</span></span></pre></div>
<a id="trunktestsqunitvendorqunitjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/qunit/vendor/qunit.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/qunit/vendor/qunit.js 2015-05-04 13:09:14 UTC (rev 32342)
+++ trunk/tests/qunit/vendor/qunit.js   2015-05-04 19:43:38 UTC (rev 32343)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,35 +1,42 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * QUnit v1.12.0 - A JavaScript Unit Testing Framework
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/*!
+ * QUnit 1.18.0
+ * http://qunitjs.com/
</ins><span class="cx" style="display: block; padding: 0 10px">  *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * http://qunitjs.com
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
</ins><span class="cx" style="display: block; padding: 0 10px">  *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Copyright 2013 jQuery Foundation and other contributors
- * Released under the MIT license.
- * https://jquery.org/license/
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Date: 2015-04-03T10:23Z
</ins><span class="cx" style="display: block; padding: 0 10px">  */
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> (function( window ) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> var QUnit,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        assert,
</del><span class="cx" style="display: block; padding: 0 10px">         config,
</span><span class="cx" style="display: block; padding: 0 10px">        onErrorFnPrev,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        testId = 0,
-       fileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ loggingCallbacks = {},
+       fileName = ( sourceFromStacktrace( 0 ) || "" ).replace( /(:\d+)+\)?/, "" ).replace( /.+\//, "" ),
</ins><span class="cx" style="display: block; padding: 0 10px">         toString = Object.prototype.toString,
</span><span class="cx" style="display: block; padding: 0 10px">        hasOwn = Object.prototype.hasOwnProperty,
</span><span class="cx" style="display: block; padding: 0 10px">        // Keep a local reference to Date (GH-283)
</span><span class="cx" style="display: block; padding: 0 10px">        Date = window.Date,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        now = Date.now || function() {
+               return new Date().getTime();
+       },
+       globalStartCalled = false,
+       runStarted = false,
</ins><span class="cx" style="display: block; padding: 0 10px">         setTimeout = window.setTimeout,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        clearTimeout = window.clearTimeout,
</ins><span class="cx" style="display: block; padding: 0 10px">         defined = {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                setTimeout: typeof window.setTimeout !== "undefined",
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         document: window.document !== undefined,
+               setTimeout: window.setTimeout !== undefined,
</ins><span class="cx" style="display: block; padding: 0 10px">                 sessionStorage: (function() {
</span><span class="cx" style="display: block; padding: 0 10px">                        var x = "qunit-test-string";
</span><span class="cx" style="display: block; padding: 0 10px">                        try {
</span><span class="cx" style="display: block; padding: 0 10px">                                sessionStorage.setItem( x, x );
</span><span class="cx" style="display: block; padding: 0 10px">                                sessionStorage.removeItem( x );
</span><span class="cx" style="display: block; padding: 0 10px">                                return true;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        } catch( e ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 } catch ( e ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 return false;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                }())
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -71,629 +78,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return {Object} New object with only the own properties (recursively).
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        objectValues = function( obj ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                // Grunt 0.3.x uses an older version of jshint that still has jshint/jshint#392.
-               /*jshint newcap: false */
</del><span class="cx" style="display: block; padding: 0 10px">                 var key, val,
</span><span class="cx" style="display: block; padding: 0 10px">                        vals = QUnit.is( "array", obj ) ? [] : {};
</span><span class="cx" style="display: block; padding: 0 10px">                for ( key in obj ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( hasOwn.call( obj, key ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                val = obj[key];
-                               vals[key] = val === Object(val) ? objectValues(val) : val;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         val = obj[ key ];
+                               vals[ key ] = val === Object( val ) ? objectValues( val ) : val;
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                return vals;
</span><span class="cx" style="display: block; padding: 0 10px">        };
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function Test( settings ) {
-       extend( this, settings );
-       this.assertions = [];
-       this.testNumber = ++Test.count;
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+QUnit = {};
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-Test.count = 0;
-
-Test.prototype = {
-       init: function() {
-               var a, b, li,
-                       tests = id( "qunit-tests" );
-
-               if ( tests ) {
-                       b = document.createElement( "strong" );
-                       b.innerHTML = this.nameHtml;
-
-                       // `a` initialized at top of scope
-                       a = document.createElement( "a" );
-                       a.innerHTML = "Rerun";
-                       a.href = QUnit.url({ testNumber: this.testNumber });
-
-                       li = document.createElement( "li" );
-                       li.appendChild( b );
-                       li.appendChild( a );
-                       li.className = "running";
-                       li.id = this.id = "qunit-test-output" + testId++;
-
-                       tests.appendChild( li );
-               }
-       },
-       setup: function() {
-               if (
-                       // Emit moduleStart when we're switching from one module to another
-                       this.module !== config.previousModule ||
-                               // They could be equal (both undefined) but if the previousModule property doesn't
-                               // yet exist it means this is the first test in a suite that isn't wrapped in a
-                               // module, in which case we'll just emit a moduleStart event for 'undefined'.
-                               // Without this, reporters can get testStart before moduleStart  which is a problem.
-                               !hasOwn.call( config, "previousModule" )
-               ) {
-                       if ( hasOwn.call( config, "previousModule" ) ) {
-                               runLoggingCallbacks( "moduleDone", QUnit, {
-                                       name: config.previousModule,
-                                       failed: config.moduleStats.bad,
-                                       passed: config.moduleStats.all - config.moduleStats.bad,
-                                       total: config.moduleStats.all
-                               });
-                       }
-                       config.previousModule = this.module;
-                       config.moduleStats = { all: 0, bad: 0 };
-                       runLoggingCallbacks( "moduleStart", QUnit, {
-                               name: this.module
-                       });
-               }
-
-               config.current = this;
-
-               this.testEnvironment = extend({
-                       setup: function() {},
-                       teardown: function() {}
-               }, this.moduleTestEnvironment );
-
-               this.started = +new Date();
-               runLoggingCallbacks( "testStart", QUnit, {
-                       name: this.testName,
-                       module: this.module
-               });
-
-               /*jshint camelcase:false */
-
-
-               /**
-                * Expose the current test environment.
-                *
-                * @deprecated since 1.12.0: Use QUnit.config.current.testEnvironment instead.
-                */
-               QUnit.current_testEnvironment = this.testEnvironment;
-
-               /*jshint camelcase:true */
-
-               if ( !config.pollution ) {
-                       saveGlobal();
-               }
-               if ( config.notrycatch ) {
-                       this.testEnvironment.setup.call( this.testEnvironment, QUnit.assert );
-                       return;
-               }
-               try {
-                       this.testEnvironment.setup.call( this.testEnvironment, QUnit.assert );
-               } catch( e ) {
-                       QUnit.pushFailure( "Setup failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
-               }
-       },
-       run: function() {
-               config.current = this;
-
-               var running = id( "qunit-testresult" );
-
-               if ( running ) {
-                       running.innerHTML = "Running: <br/>" + this.nameHtml;
-               }
-
-               if ( this.async ) {
-                       QUnit.stop();
-               }
-
-               this.callbackStarted = +new Date();
-
-               if ( config.notrycatch ) {
-                       this.callback.call( this.testEnvironment, QUnit.assert );
-                       this.callbackRuntime = +new Date() - this.callbackStarted;
-                       return;
-               }
-
-               try {
-                       this.callback.call( this.testEnvironment, QUnit.assert );
-                       this.callbackRuntime = +new Date() - this.callbackStarted;
-               } catch( e ) {
-                       this.callbackRuntime = +new Date() - this.callbackStarted;
-
-                       QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) );
-                       // else next test will carry the responsibility
-                       saveGlobal();
-
-                       // Restart the tests if they're blocking
-                       if ( config.blocking ) {
-                               QUnit.start();
-                       }
-               }
-       },
-       teardown: function() {
-               config.current = this;
-               if ( config.notrycatch ) {
-                       if ( typeof this.callbackRuntime === "undefined" ) {
-                               this.callbackRuntime = +new Date() - this.callbackStarted;
-                       }
-                       this.testEnvironment.teardown.call( this.testEnvironment, QUnit.assert );
-                       return;
-               } else {
-                       try {
-                               this.testEnvironment.teardown.call( this.testEnvironment, QUnit.assert );
-                       } catch( e ) {
-                               QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
-                       }
-               }
-               checkPollution();
-       },
-       finish: function() {
-               config.current = this;
-               if ( config.requireExpects && this.expected === null ) {
-                       QUnit.pushFailure( "Expected number of assertions to be defined, but expect() was not called.", this.stack );
-               } else if ( this.expected !== null && this.expected !== this.assertions.length ) {
-                       QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack );
-               } else if ( this.expected === null && !this.assertions.length ) {
-                       QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack );
-               }
-
-               var i, assertion, a, b, time, li, ol,
-                       test = this,
-                       good = 0,
-                       bad = 0,
-                       tests = id( "qunit-tests" );
-
-               this.runtime = +new Date() - this.started;
-               config.stats.all += this.assertions.length;
-               config.moduleStats.all += this.assertions.length;
-
-               if ( tests ) {
-                       ol = document.createElement( "ol" );
-                       ol.className = "qunit-assert-list";
-
-                       for ( i = 0; i < this.assertions.length; i++ ) {
-                               assertion = this.assertions[i];
-
-                               li = document.createElement( "li" );
-                               li.className = assertion.result ? "pass" : "fail";
-                               li.innerHTML = assertion.message || ( assertion.result ? "okay" : "failed" );
-                               ol.appendChild( li );
-
-                               if ( assertion.result ) {
-                                       good++;
-                               } else {
-                                       bad++;
-                                       config.stats.bad++;
-                                       config.moduleStats.bad++;
-                               }
-                       }
-
-                       // store result when possible
-                       if ( QUnit.config.reorder && defined.sessionStorage ) {
-                               if ( bad ) {
-                                       sessionStorage.setItem( "qunit-test-" + this.module + "-" + this.testName, bad );
-                               } else {
-                                       sessionStorage.removeItem( "qunit-test-" + this.module + "-" + this.testName );
-                               }
-                       }
-
-                       if ( bad === 0 ) {
-                               addClass( ol, "qunit-collapsed" );
-                       }
-
-                       // `b` initialized at top of scope
-                       b = document.createElement( "strong" );
-                       b.innerHTML = this.nameHtml + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
-
-                       addEvent(b, "click", function() {
-                               var next = b.parentNode.lastChild,
-                                       collapsed = hasClass( next, "qunit-collapsed" );
-                               ( collapsed ? removeClass : addClass )( next, "qunit-collapsed" );
-                       });
-
-                       addEvent(b, "dblclick", function( e ) {
-                               var target = e && e.target ? e.target : window.event.srcElement;
-                               if ( target.nodeName.toLowerCase() === "span" || target.nodeName.toLowerCase() === "b" ) {
-                                       target = target.parentNode;
-                               }
-                               if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
-                                       window.location = QUnit.url({ testNumber: test.testNumber });
-                               }
-                       });
-
-                       // `time` initialized at top of scope
-                       time = document.createElement( "span" );
-                       time.className = "runtime";
-                       time.innerHTML = this.runtime + " ms";
-
-                       // `li` initialized at top of scope
-                       li = id( this.id );
-                       li.className = bad ? "fail" : "pass";
-                       li.removeChild( li.firstChild );
-                       a = li.firstChild;
-                       li.appendChild( b );
-                       li.appendChild( a );
-                       li.appendChild( time );
-                       li.appendChild( ol );
-
-               } else {
-                       for ( i = 0; i < this.assertions.length; i++ ) {
-                               if ( !this.assertions[i].result ) {
-                                       bad++;
-                                       config.stats.bad++;
-                                       config.moduleStats.bad++;
-                               }
-                       }
-               }
-
-               runLoggingCallbacks( "testDone", QUnit, {
-                       name: this.testName,
-                       module: this.module,
-                       failed: bad,
-                       passed: this.assertions.length - bad,
-                       total: this.assertions.length,
-                       duration: this.runtime
-               });
-
-               QUnit.reset();
-
-               config.current = undefined;
-       },
-
-       queue: function() {
-               var bad,
-                       test = this;
-
-               synchronize(function() {
-                       test.init();
-               });
-               function run() {
-                       // each of these can by async
-                       synchronize(function() {
-                               test.setup();
-                       });
-                       synchronize(function() {
-                               test.run();
-                       });
-                       synchronize(function() {
-                               test.teardown();
-                       });
-                       synchronize(function() {
-                               test.finish();
-                       });
-               }
-
-               // `bad` initialized at top of scope
-               // defer when previous test run passed, if storage is available
-               bad = QUnit.config.reorder && defined.sessionStorage &&
-                                               +sessionStorage.getItem( "qunit-test-" + this.module + "-" + this.testName );
-
-               if ( bad ) {
-                       run();
-               } else {
-                       synchronize( run, true );
-               }
-       }
-};
-
-// Root QUnit object.
-// `QUnit` initialized at top of scope
-QUnit = {
-
-       // call on start of module test to prepend name to all tests
-       module: function( name, testEnvironment ) {
-               config.currentModule = name;
-               config.currentModuleTestEnvironment = testEnvironment;
-               config.modules[name] = true;
-       },
-
-       asyncTest: function( testName, expected, callback ) {
-               if ( arguments.length === 2 ) {
-                       callback = expected;
-                       expected = null;
-               }
-
-               QUnit.test( testName, expected, callback, true );
-       },
-
-       test: function( testName, expected, callback, async ) {
-               var test,
-                       nameHtml = "<span class='test-name'>" + escapeText( testName ) + "</span>";
-
-               if ( arguments.length === 2 ) {
-                       callback = expected;
-                       expected = null;
-               }
-
-               if ( config.currentModule ) {
-                       nameHtml = "<span class='module-name'>" + escapeText( config.currentModule ) + "</span>: " + nameHtml;
-               }
-
-               test = new Test({
-                       nameHtml: nameHtml,
-                       testName: testName,
-                       expected: expected,
-                       async: async,
-                       callback: callback,
-                       module: config.currentModule,
-                       moduleTestEnvironment: config.currentModuleTestEnvironment,
-                       stack: sourceFromStacktrace( 2 )
-               });
-
-               if ( !validTest( test ) ) {
-                       return;
-               }
-
-               test.queue();
-       },
-
-       // Specify the number of expected assertions to guarantee that failed test (no assertions are run at all) don't slip through.
-       expect: function( asserts ) {
-               if (arguments.length === 1) {
-                       config.current.expected = asserts;
-               } else {
-                       return config.current.expected;
-               }
-       },
-
-       start: function( count ) {
-               // QUnit hasn't been initialized yet.
-               // Note: RequireJS (et al) may delay onLoad
-               if ( config.semaphore === undefined ) {
-                       QUnit.begin(function() {
-                               // This is triggered at the top of QUnit.load, push start() to the event loop, to allow QUnit.load to finish first
-                               setTimeout(function() {
-                                       QUnit.start( count );
-                               });
-                       });
-                       return;
-               }
-
-               config.semaphore -= count || 1;
-               // don't start until equal number of stop-calls
-               if ( config.semaphore > 0 ) {
-                       return;
-               }
-               // ignore if start is called more often then stop
-               if ( config.semaphore < 0 ) {
-                       config.semaphore = 0;
-                       QUnit.pushFailure( "Called start() while already started (QUnit.config.semaphore was 0 already)", null, sourceFromStacktrace(2) );
-                       return;
-               }
-               // A slight delay, to avoid any current callbacks
-               if ( defined.setTimeout ) {
-                       setTimeout(function() {
-                               if ( config.semaphore > 0 ) {
-                                       return;
-                               }
-                               if ( config.timeout ) {
-                                       clearTimeout( config.timeout );
-                               }
-
-                               config.blocking = false;
-                               process( true );
-                       }, 13);
-               } else {
-                       config.blocking = false;
-                       process( true );
-               }
-       },
-
-       stop: function( count ) {
-               config.semaphore += count || 1;
-               config.blocking = true;
-
-               if ( config.testTimeout && defined.setTimeout ) {
-                       clearTimeout( config.timeout );
-                       config.timeout = setTimeout(function() {
-                               QUnit.ok( false, "Test timed out" );
-                               config.semaphore = 1;
-                               QUnit.start();
-                       }, config.testTimeout );
-               }
-       }
-};
-
-// `assert` initialized at top of scope
-// Assert helpers
-// All of these must either call QUnit.push() or manually do:
-// - runLoggingCallbacks( "log", .. );
-// - config.current.assertions.push({ .. });
-// We attach it to the QUnit object *after* we expose the public API,
-// otherwise `assert` will become a global variable in browsers (#341).
-assert = {
-       /**
-        * Asserts rough true-ish result.
-        * @name ok
-        * @function
-        * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
-        */
-       ok: function( result, msg ) {
-               if ( !config.current ) {
-                       throw new Error( "ok() assertion outside test context, was " + sourceFromStacktrace(2) );
-               }
-               result = !!result;
-               msg = msg || (result ? "okay" : "failed" );
-
-               var source,
-                       details = {
-                               module: config.current.module,
-                               name: config.current.testName,
-                               result: result,
-                               message: msg
-                       };
-
-               msg = "<span class='test-message'>" + escapeText( msg ) + "</span>";
-
-               if ( !result ) {
-                       source = sourceFromStacktrace( 2 );
-                       if ( source ) {
-                               details.source = source;
-                               msg += "<table><tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr></table>";
-                       }
-               }
-               runLoggingCallbacks( "log", QUnit, details );
-               config.current.assertions.push({
-                       result: result,
-                       message: msg
-               });
-       },
-
-       /**
-        * Assert that the first two arguments are equal, with an optional message.
-        * Prints out both actual and expected values.
-        * @name equal
-        * @function
-        * @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" );
-        */
-       equal: function( actual, expected, message ) {
-               /*jshint eqeqeq:false */
-               QUnit.push( expected == actual, actual, expected, message );
-       },
-
-       /**
-        * @name notEqual
-        * @function
-        */
-       notEqual: function( actual, expected, message ) {
-               /*jshint eqeqeq:false */
-               QUnit.push( expected != actual, actual, expected, message );
-       },
-
-       /**
-        * @name propEqual
-        * @function
-        */
-       propEqual: function( actual, expected, message ) {
-               actual = objectValues(actual);
-               expected = objectValues(expected);
-               QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
-       },
-
-       /**
-        * @name notPropEqual
-        * @function
-        */
-       notPropEqual: function( actual, expected, message ) {
-               actual = objectValues(actual);
-               expected = objectValues(expected);
-               QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
-       },
-
-       /**
-        * @name deepEqual
-        * @function
-        */
-       deepEqual: function( actual, expected, message ) {
-               QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
-       },
-
-       /**
-        * @name notDeepEqual
-        * @function
-        */
-       notDeepEqual: function( actual, expected, message ) {
-               QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
-       },
-
-       /**
-        * @name strictEqual
-        * @function
-        */
-       strictEqual: function( actual, expected, message ) {
-               QUnit.push( expected === actual, actual, expected, message );
-       },
-
-       /**
-        * @name notStrictEqual
-        * @function
-        */
-       notStrictEqual: function( actual, expected, message ) {
-               QUnit.push( expected !== actual, actual, expected, message );
-       },
-
-       "throws": function( block, expected, message ) {
-               var actual,
-                       expectedOutput = expected,
-                       ok = false;
-
-               // 'expected' is optional
-               if ( typeof expected === "string" ) {
-                       message = expected;
-                       expected = null;
-               }
-
-               config.current.ignoreGlobalErrors = true;
-               try {
-                       block.call( config.current.testEnvironment );
-               } catch (e) {
-                       actual = e;
-               }
-               config.current.ignoreGlobalErrors = false;
-
-               if ( actual ) {
-                       // we don't want to validate thrown error
-                       if ( !expected ) {
-                               ok = true;
-                               expectedOutput = null;
-                       // expected is a regexp
-                       } else if ( QUnit.objectType( expected ) === "regexp" ) {
-                               ok = expected.test( errorString( actual ) );
-                       // expected is a constructor
-                       } else if ( actual instanceof expected ) {
-                               ok = true;
-                       // expected is a validation function which returns true is validation passed
-                       } else if ( expected.call( {}, actual ) === true ) {
-                               expectedOutput = null;
-                               ok = true;
-                       }
-
-                       QUnit.push( ok, actual, expectedOutput, message );
-               } else {
-                       QUnit.pushFailure( message, null, "No exception was thrown." );
-               }
-       }
-};
-
</del><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @deprecated since 1.8.0
- * Kept assertion helpers in root for backwards compatibility.
- */
-extend( QUnit, assert );
-
-/**
- * @deprecated since 1.9.0
- * Kept root "raises()" for backwards compatibility.
- * (Note that we don't introduce assert.raises).
- */
-QUnit.raises = assert[ "throws" ];
-
-/**
- * @deprecated since 1.0.0, replaced with error pushes since 1.3.0
- * Kept to avoid TypeErrors for undefined methods.
- */
-QUnit.equals = function() {
-       QUnit.push( false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead" );
-};
-QUnit.same = function() {
-       QUnit.push( false, false, false, "QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead" );
-};
-
-// We want access to the constructor's prototype
-(function() {
-       function F() {}
-       F.prototype = QUnit;
-       QUnit = new F();
-       // Make F QUnit's constructor so that we can add to the prototype later
-       QUnit.constructor = F;
-}());
-
-/**
</del><span class="cx" style="display: block; padding: 0 10px">  * Config object: Maintain internal state
</span><span class="cx" style="display: block; padding: 0 10px">  * Later exposed as QUnit.config
</span><span class="cx" style="display: block; padding: 0 10px">  * `config` initialized at top of scope
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -705,10 +103,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">        // block until document ready
</span><span class="cx" style="display: block; padding: 0 10px">        blocking: true,
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // when enabled, show only failing tests
-       // gets persisted through sessionStorage and can be changed in UI via checkbox
-       hidepassed: false,
-
</del><span class="cx" style="display: block; padding: 0 10px">         // by default, run previously failed tests first
</span><span class="cx" style="display: block; padding: 0 10px">        // very useful in combination with "Hide passed tests" checked
</span><span class="cx" style="display: block; padding: 0 10px">        reorder: true,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -716,165 +110,233 @@
</span><span class="cx" style="display: block; padding: 0 10px">        // by default, modify document.title when suite is done
</span><span class="cx" style="display: block; padding: 0 10px">        altertitle: true,
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        // by default, scroll to top of the page when suite is done
+       scrolltop: true,
+
</ins><span class="cx" style="display: block; padding: 0 10px">         // when enabled, all tests must call expect()
</span><span class="cx" style="display: block; padding: 0 10px">        requireExpects: false,
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        // depth up-to which object will be dumped
+       maxDepth: 5,
+
</ins><span class="cx" style="display: block; padding: 0 10px">         // add checkboxes that are persisted in the query-string
</span><span class="cx" style="display: block; padding: 0 10px">        // when enabled, the id is set to `true` as a `QUnit.config` property
</span><span class="cx" style="display: block; padding: 0 10px">        urlConfig: [
</span><span class="cx" style="display: block; padding: 0 10px">                {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        id: "hidepassed",
+                       label: "Hide passed tests",
+                       tooltip: "Only show tests and assertions that fail. Stored as query-strings."
+               },
+               {
</ins><span class="cx" style="display: block; padding: 0 10px">                         id: "noglobals",
</span><span class="cx" style="display: block; padding: 0 10px">                        label: "Check for Globals",
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        tooltip: "Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings."
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 tooltip: "Enabling this will test if any test introduces new properties on the " +
+                               "`window` object. Stored as query-strings."
</ins><span class="cx" style="display: block; padding: 0 10px">                 },
</span><span class="cx" style="display: block; padding: 0 10px">                {
</span><span class="cx" style="display: block; padding: 0 10px">                        id: "notrycatch",
</span><span class="cx" style="display: block; padding: 0 10px">                        label: "No try-catch",
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings."
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging " +
+                               "exceptions in IE reasonable. Stored as query-strings."
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px">        ],
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        // Set of all modules.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        modules: {},
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ modules: [],
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // logging callback queues
-       begin: [],
-       done: [],
-       log: [],
-       testStart: [],
-       testDone: [],
-       moduleStart: [],
-       moduleDone: []
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // The first unnamed module
+       currentModule: {
+               name: "",
+               tests: []
+       },
+
+       callbacks: {}
</ins><span class="cx" style="display: block; padding: 0 10px"> };
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Export global variables, unless an 'exports' object exists,
-// in that case we assume we're in CommonJS (dealt with on the bottom of the script)
-if ( typeof exports === "undefined" ) {
-       extend( window, QUnit.constructor.prototype );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+// Push a loose unnamed module to the modules collection
+config.modules.push( config.currentModule );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // Expose QUnit object
-       window.QUnit = QUnit;
-}
-
</del><span class="cx" style="display: block; padding: 0 10px"> // Initialize more QUnit.config and QUnit.urlParams
</span><span class="cx" style="display: block; padding: 0 10px"> (function() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        var i,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var i, current,
</ins><span class="cx" style="display: block; padding: 0 10px">                 location = window.location || { search: "", protocol: "file:" },
</span><span class="cx" style="display: block; padding: 0 10px">                params = location.search.slice( 1 ).split( "&" ),
</span><span class="cx" style="display: block; padding: 0 10px">                length = params.length,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                urlParams = {},
-               current;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         urlParams = {};
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        if ( params[ 0 ] ) {
</span><span class="cx" style="display: block; padding: 0 10px">                for ( i = 0; i < length; i++ ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        current = params[ i ].split( "=" );
</span><span class="cx" style="display: block; padding: 0 10px">                        current[ 0 ] = decodeURIComponent( current[ 0 ] );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                         // allow just a key to turn on a flag, e.g., test.html?noglobals
</span><span class="cx" style="display: block; padding: 0 10px">                        current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        urlParams[ current[ 0 ] ] = current[ 1 ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ( urlParams[ current[ 0 ] ] ) {
+                               urlParams[ current[ 0 ] ] = [].concat( urlParams[ current[ 0 ] ], current[ 1 ] );
+                       } else {
+                               urlParams[ current[ 0 ] ] = current[ 1 ];
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        if ( urlParams.filter === true ) {
+               delete urlParams.filter;
+       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">         QUnit.urlParams = urlParams;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        // String search anywhere in moduleName+testName
</span><span class="cx" style="display: block; padding: 0 10px">        config.filter = urlParams.filter;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // Exact match of the module name
-       config.module = urlParams.module;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( urlParams.maxDepth ) {
+               config.maxDepth = parseInt( urlParams.maxDepth, 10 ) === -1 ?
+                       Number.POSITIVE_INFINITY :
+                       urlParams.maxDepth;
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        config.testNumber = parseInt( urlParams.testNumber, 10 ) || null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ config.testId = [];
+       if ( urlParams.testId ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                // Ensure that urlParams.testId is an array
+               urlParams.testId = decodeURIComponent( urlParams.testId ).split( "," );
+               for ( i = 0; i < urlParams.testId.length; i++ ) {
+                       config.testId.push( urlParams.testId[ i ] );
+               }
+       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">         // Figure out if we're running the tests from a server or not
</span><span class="cx" style="display: block; padding: 0 10px">        QUnit.isLocal = location.protocol === "file:";
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+       // Expose the current QUnit version
+       QUnit.version = "1.18.0";
</ins><span class="cx" style="display: block; padding: 0 10px"> }());
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Extend QUnit object,
-// these after set here because they should not be exposed as global functions
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+// Root QUnit object.
+// `QUnit` initialized at top of scope
</ins><span class="cx" style="display: block; padding: 0 10px"> extend( QUnit, {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        assert: assert,
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        config: config,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // call on start of module test to prepend name to all tests
+       module: function( name, testEnvironment ) {
+               var currentModule = {
+                       name: name,
+                       testEnvironment: testEnvironment,
+                       tests: []
+               };
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // Initialize the configuration options
-       init: function() {
-               extend( config, {
-                       stats: { all: 0, bad: 0 },
-                       moduleStats: { all: 0, bad: 0 },
-                       started: +new Date(),
-                       updateRate: 1000,
-                       blocking: false,
-                       autostart: true,
-                       autorun: false,
-                       filter: "",
-                       queue: [],
-                       semaphore: 1
-               });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // DEPRECATED: handles setup/teardown functions,
+               // beforeEach and afterEach should be used instead
+               if ( testEnvironment && testEnvironment.setup ) {
+                       testEnvironment.beforeEach = testEnvironment.setup;
+                       delete testEnvironment.setup;
+               }
+               if ( testEnvironment && testEnvironment.teardown ) {
+                       testEnvironment.afterEach = testEnvironment.teardown;
+                       delete testEnvironment.teardown;
+               }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                var tests, banner, result,
-                       qunit = id( "qunit" );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         config.modules.push( currentModule );
+               config.currentModule = currentModule;
+       },
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( qunit ) {
-                       qunit.innerHTML =
-                               "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
-                               "<h2 id='qunit-banner'></h2>" +
-                               "<div id='qunit-testrunner-toolbar'></div>" +
-                               "<h2 id='qunit-userAgent'></h2>" +
-                               "<ol id='qunit-tests'></ol>";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // DEPRECATED: QUnit.asyncTest() will be removed in QUnit 2.0.
+       asyncTest: function( testName, expected, callback ) {
+               if ( arguments.length === 2 ) {
+                       callback = expected;
+                       expected = null;
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                tests = id( "qunit-tests" );
-               banner = id( "qunit-banner" );
-               result = id( "qunit-testresult" );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         QUnit.test( testName, expected, callback, true );
+       },
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( tests ) {
-                       tests.innerHTML = "";
-               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ test: function( testName, expected, callback, async ) {
+               var test;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( banner ) {
-                       banner.className = "";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ( arguments.length === 2 ) {
+                       callback = expected;
+                       expected = null;
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( result ) {
-                       result.parentNode.removeChild( result );
-               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         test = new Test({
+                       testName: testName,
+                       expected: expected,
+                       async: async,
+                       callback: callback
+               });
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( tests ) {
-                       result = document.createElement( "p" );
-                       result.id = "qunit-testresult";
-                       result.className = "result";
-                       tests.parentNode.insertBefore( result, tests );
-                       result.innerHTML = "Running...<br/>&nbsp;";
-               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         test.queue();
</ins><span class="cx" style="display: block; padding: 0 10px">         },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // Resets the test setup. Useful for tests that modify the DOM.
-       /*
-       DEPRECATED: Use multiple tests instead of resetting inside a test.
-       Use testStart or testDone for custom cleanup.
-       This method will throw an error in 2.0, and will be removed in 2.1
-       */
-       reset: function() {
-               var fixture = id( "qunit-fixture" );
-               if ( fixture ) {
-                       fixture.innerHTML = config.fixture;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ skip: function( testName ) {
+               var test = new Test({
+                       testName: testName,
+                       skip: true
+               });
+
+               test.queue();
+       },
+
+       // DEPRECATED: The functionality of QUnit.start() will be altered in QUnit 2.0.
+       // In QUnit 2.0, invoking it will ONLY affect the `QUnit.config.autostart` blocking behavior.
+       start: function( count ) {
+               var globalStartAlreadyCalled = globalStartCalled;
+
+               if ( !config.current ) {
+                       globalStartCalled = true;
+
+                       if ( runStarted ) {
+                               throw new Error( "Called start() outside of a test context while already started" );
+                       } else if ( globalStartAlreadyCalled || count > 1 ) {
+                               throw new Error( "Called start() outside of a test context too many times" );
+                       } else if ( config.autostart ) {
+                               throw new Error( "Called start() outside of a test context when " +
+                                       "QUnit.config.autostart was true" );
+                       } else if ( !config.pageLoaded ) {
+
+                               // The page isn't completely loaded yet, so bail out and let `QUnit.load` handle it
+                               config.autostart = true;
+                               return;
+                       }
+               } else {
+
+                       // If a test is running, adjust its semaphore
+                       config.current.semaphore -= count || 1;
+
+                       // Don't start until equal number of stop-calls
+                       if ( config.current.semaphore > 0 ) {
+                               return;
+                       }
+
+                       // throw an Error if start is called more often than stop
+                       if ( config.current.semaphore < 0 ) {
+                               config.current.semaphore = 0;
+
+                               QUnit.pushFailure(
+                                       "Called start() while already started (test's semaphore was 0 already)",
+                                       sourceFromStacktrace( 2 )
+                               );
+                               return;
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+               resumeProcessing();
</ins><span class="cx" style="display: block; padding: 0 10px">         },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // Trigger an event on an element.
-       // @example triggerEvent( document.body, "click" );
-       triggerEvent: function( elem, type, event ) {
-               if ( document.createEvent ) {
-                       event = document.createEvent( "MouseEvents" );
-                       event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,
-                               0, 0, 0, 0, 0, false, false, false, false, 0, null);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // DEPRECATED: QUnit.stop() will be removed in QUnit 2.0.
+       stop: function( count ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        elem.dispatchEvent( event );
-               } else if ( elem.fireEvent ) {
-                       elem.fireEvent( "on" + type );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // If there isn't a test running, don't allow QUnit.stop() to be called
+               if ( !config.current ) {
+                       throw new Error( "Called stop() outside of a test context" );
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+               // If a test is running, adjust its semaphore
+               config.current.semaphore += count || 1;
+
+               pauseProcessing();
</ins><span class="cx" style="display: block; padding: 0 10px">         },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        config: config,
+
</ins><span class="cx" style="display: block; padding: 0 10px">         // Safe object type checking
</span><span class="cx" style="display: block; padding: 0 10px">        is: function( type, obj ) {
</span><span class="cx" style="display: block; padding: 0 10px">                return QUnit.objectType( obj ) === type;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -882,19 +344,20 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        objectType: function( obj ) {
</span><span class="cx" style="display: block; padding: 0 10px">                if ( typeof obj === "undefined" ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                return "undefined";
-               // consider: typeof null === object
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 return "undefined";
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+               // Consider: typeof null === object
</ins><span class="cx" style="display: block; padding: 0 10px">                 if ( obj === null ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                return "null";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 return "null";
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                var match = toString.call( obj ).match(/^\[object\s(.*)\]$/),
-                       type = match && match[1] || "";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         var match = toString.call( obj ).match( /^\[object\s(.*)\]$/ ),
+                       type = match && match[ 1 ] || "";
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                switch ( type ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        case "Number":
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if ( isNaN(obj) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         if ( isNaN( obj ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         return "nan";
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                return "number";
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -912,309 +375,66 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return undefined;
</span><span class="cx" style="display: block; padding: 0 10px">        },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        push: function( result, actual, expected, message ) {
-               if ( !config.current ) {
-                       throw new Error( "assertion outside test context, was " + sourceFromStacktrace() );
-               }
-
-               var output, source,
-                       details = {
-                               module: config.current.module,
-                               name: config.current.testName,
-                               result: result,
-                               message: message,
-                               actual: actual,
-                               expected: expected
-                       };
-
-               message = escapeText( message ) || ( result ? "okay" : "failed" );
-               message = "<span class='test-message'>" + message + "</span>";
-               output = message;
-
-               if ( !result ) {
-                       expected = escapeText( QUnit.jsDump.parse(expected) );
-                       actual = escapeText( QUnit.jsDump.parse(actual) );
-                       output += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" + expected + "</pre></td></tr>";
-
-                       if ( actual !== expected ) {
-                               output += "<tr class='test-actual'><th>Result: </th><td><pre>" + actual + "</pre></td></tr>";
-                               output += "<tr class='test-diff'><th>Diff: </th><td><pre>" + QUnit.diff( expected, actual ) + "</pre></td></tr>";
-                       }
-
-                       source = sourceFromStacktrace();
-
-                       if ( source ) {
-                               details.source = source;
-                               output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
-                       }
-
-                       output += "</table>";
-               }
-
-               runLoggingCallbacks( "log", QUnit, details );
-
-               config.current.assertions.push({
-                       result: !!result,
-                       message: output
-               });
-       },
-
-       pushFailure: function( message, source, actual ) {
-               if ( !config.current ) {
-                       throw new Error( "pushFailure() assertion outside test context, was " + sourceFromStacktrace(2) );
-               }
-
-               var output,
-                       details = {
-                               module: config.current.module,
-                               name: config.current.testName,
-                               result: false,
-                               message: message
-                       };
-
-               message = escapeText( message ) || "error";
-               message = "<span class='test-message'>" + message + "</span>";
-               output = message;
-
-               output += "<table>";
-
-               if ( actual ) {
-                       output += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeText( actual ) + "</pre></td></tr>";
-               }
-
-               if ( source ) {
-                       details.source = source;
-                       output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
-               }
-
-               output += "</table>";
-
-               runLoggingCallbacks( "log", QUnit, details );
-
-               config.current.assertions.push({
-                       result: false,
-                       message: output
-               });
-       },
-
-       url: function( params ) {
-               params = extend( extend( {}, QUnit.urlParams ), params );
-               var key,
-                       querystring = "?";
-
-               for ( key in params ) {
-                       if ( hasOwn.call( params, key ) ) {
-                               querystring += encodeURIComponent( key ) + "=" +
-                                       encodeURIComponent( params[ key ] ) + "&";
-                       }
-               }
-               return window.location.protocol + "//" + window.location.host +
-                       window.location.pathname + querystring.slice( 0, -1 );
-       },
-
</del><span class="cx" style="display: block; padding: 0 10px">         extend: extend,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        id: id,
-       addEvent: addEvent,
-       addClass: addClass,
-       hasClass: hasClass,
-       removeClass: removeClass
-       // load, equiv, jsDump, diff: Attached later
-});
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * @deprecated: Created for backwards compatibility with test runner that set the hook function
- * into QUnit.{hook}, instead of invoking it and passing the hook function.
- * QUnit.constructor is set to the empty F() above so that we can add to it's prototype here.
- * Doing this allows us to tell if the following methods have been overwritten on the actual
- * QUnit object.
- */
-extend( QUnit.constructor.prototype, {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ load: function() {
+               config.pageLoaded = true;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // Logging callbacks; all receive a single argument with the listed properties
-       // run test/logs.html for any related changes
-       begin: registerLoggingCallback( "begin" ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // Initialize the configuration options
+               extend( config, {
+                       stats: { all: 0, bad: 0 },
+                       moduleStats: { all: 0, bad: 0 },
+                       started: 0,
+                       updateRate: 1000,
+                       autostart: true,
+                       filter: ""
+               }, true );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // done: { failed, passed, total, runtime }
-       done: registerLoggingCallback( "done" ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         config.blocking = false;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // log: { result, actual, expected, message }
-       log: registerLoggingCallback( "log" ),
-
-       // testStart: { name }
-       testStart: registerLoggingCallback( "testStart" ),
-
-       // testDone: { name, failed, passed, total, duration }
-       testDone: registerLoggingCallback( "testDone" ),
-
-       // moduleStart: { name }
-       moduleStart: registerLoggingCallback( "moduleStart" ),
-
-       // moduleDone: { name, failed, passed, total }
-       moduleDone: registerLoggingCallback( "moduleDone" )
-});
-
-if ( typeof document === "undefined" || document.readyState === "complete" ) {
-       config.autorun = true;
-}
-
-QUnit.load = function() {
-       runLoggingCallbacks( "begin", QUnit, {} );
-
-       // Initialize the config, saving the execution queue
-       var banner, filter, i, label, len, main, ol, toolbar, userAgent, val,
-               urlConfigCheckboxesContainer, urlConfigCheckboxes, moduleFilter,
-               numModules = 0,
-               moduleNames = [],
-               moduleFilterHtml = "",
-               urlConfigHtml = "",
-               oldconfig = extend( {}, config );
-
-       QUnit.init();
-       extend(config, oldconfig);
-
-       config.blocking = false;
-
-       len = config.urlConfig.length;
-
-       for ( i = 0; i < len; i++ ) {
-               val = config.urlConfig[i];
-               if ( typeof val === "string" ) {
-                       val = {
-                               id: val,
-                               label: val,
-                               tooltip: "[no tooltip available]"
-                       };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ( config.autostart ) {
+                       resumeProcessing();
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                config[ val.id ] = QUnit.urlParams[ val.id ];
-               urlConfigHtml += "<input id='qunit-urlconfig-" + escapeText( val.id ) +
-                       "' name='" + escapeText( val.id ) +
-                       "' type='checkbox'" + ( config[ val.id ] ? " checked='checked'" : "" ) +
-                       " title='" + escapeText( val.tooltip ) +
-                       "'><label for='qunit-urlconfig-" + escapeText( val.id ) +
-                       "' title='" + escapeText( val.tooltip ) + "'>" + val.label + "</label>";
</del><span class="cx" style="display: block; padding: 0 10px">         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        for ( i in config.modules ) {
-               if ( config.modules.hasOwnProperty( i ) ) {
-                       moduleNames.push(i);
-               }
-       }
-       numModules = moduleNames.length;
-       moduleNames.sort( function( a, b ) {
-               return a.localeCompare( b );
-       });
-       moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' " +
-               ( config.module === undefined  ? "selected='selected'" : "" ) +
-               ">< All Modules ></option>";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+});
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+// Register logging callbacks
+(function() {
+       var i, l, key,
+               callbacks = [ "begin", "done", "log", "testStart", "testDone",
+                       "moduleStart", "moduleDone" ];
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        for ( i = 0; i < numModules; i++) {
-                       moduleFilterHtml += "<option value='" + escapeText( encodeURIComponent(moduleNames[i]) ) + "' " +
-                               ( config.module === moduleNames[i] ? "selected='selected'" : "" ) +
-                               ">" + escapeText(moduleNames[i]) + "</option>";
-       }
-       moduleFilterHtml += "</select>";
-
-       // `userAgent` initialized at top of scope
-       userAgent = id( "qunit-userAgent" );
-       if ( userAgent ) {
-               userAgent.innerHTML = navigator.userAgent;
-       }
-
-       // `banner` initialized at top of scope
-       banner = id( "qunit-header" );
-       if ( banner ) {
-               banner.innerHTML = "<a href='" + QUnit.url({ filter: undefined, module: undefined, testNumber: undefined }) + "'>" + banner.innerHTML + "</a> ";
-       }
-
-       // `toolbar` initialized at top of scope
-       toolbar = id( "qunit-testrunner-toolbar" );
-       if ( toolbar ) {
-               // `filter` initialized at top of scope
-               filter = document.createElement( "input" );
-               filter.type = "checkbox";
-               filter.id = "qunit-filter-pass";
-
-               addEvent( filter, "click", function() {
-                       var tmp,
-                               ol = document.getElementById( "qunit-tests" );
-
-                       if ( filter.checked ) {
-                               ol.className = ol.className + " hidepass";
-                       } else {
-                               tmp = " " + ol.className.replace( /[\n\t\r]/g, " " ) + " ";
-                               ol.className = tmp.replace( / hidepass /, " " );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ function registerLoggingCallback( key ) {
+               var loggingCallback = function( callback ) {
+                       if ( QUnit.objectType( callback ) !== "function" ) {
+                               throw new Error(
+                                       "QUnit logging methods require a callback function as their first parameters."
+                               );
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if ( defined.sessionStorage ) {
-                               if (filter.checked) {
-                                       sessionStorage.setItem( "qunit-filter-passed-tests", "true" );
-                               } else {
-                                       sessionStorage.removeItem( "qunit-filter-passed-tests" );
-                               }
-                       }
-               });
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem( "qunit-filter-passed-tests" ) ) {
-                       filter.checked = true;
-                       // `ol` initialized at top of scope
-                       ol = document.getElementById( "qunit-tests" );
-                       ol.className = ol.className + " hidepass";
-               }
-               toolbar.appendChild( filter );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 config.callbacks[ key ].push( callback );
+               };
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                // `label` initialized at top of scope
-               label = document.createElement( "label" );
-               label.setAttribute( "for", "qunit-filter-pass" );
-               label.setAttribute( "title", "Only show tests and assertions that fail. Stored in sessionStorage." );
-               label.innerHTML = "Hide passed tests";
-               toolbar.appendChild( label );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // DEPRECATED: This will be removed on QUnit 2.0.0+
+               // Stores the registered functions allowing restoring
+               // at verifyLoggingCallbacks() if modified
+               loggingCallbacks[ key ] = loggingCallback;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                urlConfigCheckboxesContainer = document.createElement("span");
-               urlConfigCheckboxesContainer.innerHTML = urlConfigHtml;
-               urlConfigCheckboxes = urlConfigCheckboxesContainer.getElementsByTagName("input");
-               // For oldIE support:
-               // * Add handlers to the individual elements instead of the container
-               // * Use "click" instead of "change"
-               // * Fallback from event.target to event.srcElement
-               addEvents( urlConfigCheckboxes, "click", function( event ) {
-                       var params = {},
-                               target = event.target || event.srcElement;
-                       params[ target.name ] = target.checked ? true : undefined;
-                       window.location = QUnit.url( params );
-               });
-               toolbar.appendChild( urlConfigCheckboxesContainer );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         return loggingCallback;
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if (numModules > 1) {
-                       moduleFilter = document.createElement( "span" );
-                       moduleFilter.setAttribute( "id", "qunit-modulefilter-container" );
-                       moduleFilter.innerHTML = moduleFilterHtml;
-                       addEvent( moduleFilter.lastChild, "change", function() {
-                               var selectBox = moduleFilter.getElementsByTagName("select")[0],
-                                       selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for ( i = 0, l = callbacks.length; i < l; i++ ) {
+               key = callbacks[ i ];
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                window.location = QUnit.url({
-                                       module: ( selectedModule === "" ) ? undefined : selectedModule,
-                                       // Remove any existing filters
-                                       filter: undefined,
-                                       testNumber: undefined
-                               });
-                       });
-                       toolbar.appendChild(moduleFilter);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // Initialize key collection of logging callback
+               if ( QUnit.objectType( config.callbacks[ key ] ) === "undefined" ) {
+                       config.callbacks[ key ] = [];
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        }
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // `main` initialized at top of scope
-       main = id( "qunit-fixture" );
-       if ( main ) {
-               config.fixture = main.innerHTML;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         QUnit[ key ] = registerLoggingCallback( key );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+})();
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( config.autostart ) {
-               QUnit.start();
-       }
-};
-
-addEvent( window, "load", QUnit.load );
-
</del><span class="cx" style="display: block; padding: 0 10px"> // `onErrorFnPrev` initialized at top of scope
</span><span class="cx" style="display: block; padding: 0 10px"> // Preserve other handlers
</span><span class="cx" style="display: block; padding: 0 10px"> onErrorFnPrev = window.onerror;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1222,7 +442,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Cover uncaught exceptions
</span><span class="cx" style="display: block; padding: 0 10px"> // Returning true will suppress the default browser handler,
</span><span class="cx" style="display: block; padding: 0 10px"> // returning false will let it run.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-window.onerror = function ( error, filePath, linerNr ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+window.onerror = function( error, filePath, linerNr ) {
</ins><span class="cx" style="display: block; padding: 0 10px">         var ret = false;
</span><span class="cx" style="display: block; padding: 0 10px">        if ( onErrorFnPrev ) {
</span><span class="cx" style="display: block; padding: 0 10px">                ret = onErrorFnPrev( error, filePath, linerNr );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1237,9 +457,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                        QUnit.pushFailure( error, filePath + ":" + linerNr );
</span><span class="cx" style="display: block; padding: 0 10px">                } else {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        QUnit.test( "global failure", extend( function() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 QUnit.test( "global failure", extend(function() {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 QUnit.pushFailure( error, filePath + ":" + linerNr );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        }, { validTest: validTest } ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 }, { validTest: true } ) );
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px">                return false;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1248,71 +468,27 @@
</span><span class="cx" style="display: block; padding: 0 10px"> };
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> function done() {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        var runtime, passed;
+
</ins><span class="cx" style="display: block; padding: 0 10px">         config.autorun = true;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        // Log the last module results
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( config.currentModule ) {
-               runLoggingCallbacks( "moduleDone", QUnit, {
-                       name: config.currentModule,
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( config.previousModule ) {
+               runLoggingCallbacks( "moduleDone", {
+                       name: config.previousModule.name,
+                       tests: config.previousModule.tests,
</ins><span class="cx" style="display: block; padding: 0 10px">                         failed: config.moduleStats.bad,
</span><span class="cx" style="display: block; padding: 0 10px">                        passed: config.moduleStats.all - config.moduleStats.bad,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        total: config.moduleStats.all
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 total: config.moduleStats.all,
+                       runtime: now() - config.moduleStats.started
</ins><span class="cx" style="display: block; padding: 0 10px">                 });
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px">        delete config.previousModule;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        var i, key,
-               banner = id( "qunit-banner" ),
-               tests = id( "qunit-tests" ),
-               runtime = +new Date() - config.started,
-               passed = config.stats.all - config.stats.bad,
-               html = [
-                       "Tests completed in ",
-                       runtime,
-                       " milliseconds.<br/>",
-                       "<span class='passed'>",
-                       passed,
-                       "</span> assertions of <span class='total'>",
-                       config.stats.all,
-                       "</span> passed, <span class='failed'>",
-                       config.stats.bad,
-                       "</span> failed."
-               ].join( "" );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ runtime = now() - config.started;
+       passed = config.stats.all - config.stats.bad;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( banner ) {
-               banner.className = ( config.stats.bad ? "qunit-fail" : "qunit-pass" );
-       }
-
-       if ( tests ) {
-               id( "qunit-testresult" ).innerHTML = html;
-       }
-
-       if ( config.altertitle && typeof document !== "undefined" && document.title ) {
-               // show ✖ for good, ✔ for bad suite result in title
-               // use escape sequences in case file gets loaded with non-utf-8-charset
-               document.title = [
-                       ( config.stats.bad ? "\u2716" : "\u2714" ),
-                       document.title.replace( /^[\u2714\u2716] /i, "" )
-               ].join( " " );
-       }
-
-       // clear own sessionStorage items if all tests passed
-       if ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) {
-               // `key` & `i` initialized at top of scope
-               for ( i = 0; i < sessionStorage.length; i++ ) {
-                       key = sessionStorage.key( i++ );
-                       if ( key.indexOf( "qunit-test-" ) === 0 ) {
-                               sessionStorage.removeItem( key );
-                       }
-               }
-       }
-
-       // scroll back to top to show results
-       if ( window.scrollTo ) {
-               window.scrollTo(0, 0);
-       }
-
-       runLoggingCallbacks( "done", QUnit, {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ runLoggingCallbacks( "done", {
</ins><span class="cx" style="display: block; padding: 0 10px">                 failed: config.stats.bad,
</span><span class="cx" style="display: block; padding: 0 10px">                passed: passed,
</span><span class="cx" style="display: block; padding: 0 10px">                total: config.stats.all,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1320,60 +496,16 @@
</span><span class="cx" style="display: block; padding: 0 10px">        });
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/** @return Boolean: true if this test should be ran */
-function validTest( test ) {
-       var include,
-               filter = config.filter && config.filter.toLowerCase(),
-               module = config.module && config.module.toLowerCase(),
-               fullName = (test.module + ": " + test.testName).toLowerCase();
-
-       // Internally-generated tests are always valid
-       if ( test.callback && test.callback.validTest === validTest ) {
-               delete test.callback.validTest;
-               return true;
-       }
-
-       if ( config.testNumber ) {
-               return test.testNumber === config.testNumber;
-       }
-
-       if ( module && ( !test.module || test.module.toLowerCase() !== module ) ) {
-               return false;
-       }
-
-       if ( !filter ) {
-               return true;
-       }
-
-       include = filter.charAt( 0 ) !== "!";
-       if ( !include ) {
-               filter = filter.slice( 1 );
-       }
-
-       // If the filter matches, we need to honour include
-       if ( fullName.indexOf( filter ) !== -1 ) {
-               return include;
-       }
-
-       // Otherwise, do the opposite
-       return !include;
-}
-
-// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions)
-// Later Safari and IE10 are supposed to support error.stack as well
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+// Doesn't support IE6 to IE9, it will return undefined on these browsers
</ins><span class="cx" style="display: block; padding: 0 10px"> // See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
</span><span class="cx" style="display: block; padding: 0 10px"> function extractStacktrace( e, offset ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        offset = offset === undefined ? 3 : offset;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ offset = offset === undefined ? 4 : offset;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        var stack, include, i;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( e.stacktrace ) {
-               // Opera
-               return e.stacktrace.split( "\n" )[ offset + 3 ];
-       } else if ( e.stack ) {
-               // Firefox, Chrome
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( e.stack ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                 stack = e.stack.split( "\n" );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if (/^error$/i.test( stack[0] ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ( /^error$/i.test( stack[ 0 ] ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         stack.shift();
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                if ( fileName ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1389,51 +521,43 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                return stack[ offset ];
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+       // Support: Safari <=6 only
</ins><span class="cx" style="display: block; padding: 0 10px">         } else if ( e.sourceURL ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                // Safari, PhantomJS
-               // hopefully one day Safari provides actual stacktraces
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                 // exclude useless self-reference for generated Error objects
</span><span class="cx" style="display: block; padding: 0 10px">                if ( /qunit.js$/.test( e.sourceURL ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                 // for actual exceptions, this is useful
</span><span class="cx" style="display: block; padding: 0 10px">                return e.sourceURL + ":" + e.line;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> function sourceFromStacktrace( offset ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        try {
-               throw new Error();
-       } catch ( e ) {
-               return extractStacktrace( e, offset );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var error = new Error();
+
+       // Support: Safari <=7 only, IE <=10 - 11 only
+       // Not all browsers generate the `stack` property for `new Error()`, see also #636
+       if ( !error.stack ) {
+               try {
+                       throw error;
+               } catch ( err ) {
+                       error = err;
+               }
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-}
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * Escape text for attribute or text content.
- */
-function escapeText( s ) {
-       if ( !s ) {
-               return "";
-       }
-       s = s + "";
-       // Both single quotes and double quotes (for attributes)
-       return s.replace( /['"<>&]/g, function( s ) {
-               switch( s ) {
-                       case "'":
-                               return "&#039;";
-                       case "\"":
-                               return "&quot;";
-                       case "<":
-                               return "&lt;";
-                       case ">":
-                               return "&gt;";
-                       case "&":
-                               return "&amp;";
-               }
-       });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return extractStacktrace( error, offset );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> function synchronize( callback, last ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        if ( QUnit.objectType( callback ) === "array" ) {
+               while ( callback.length ) {
+                       synchronize( callback.shift() );
+               }
+               return;
+       }
</ins><span class="cx" style="display: block; padding: 0 10px">         config.queue.push( callback );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        if ( config.autorun && !config.blocking ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1445,11 +569,17 @@
</span><span class="cx" style="display: block; padding: 0 10px">        function next() {
</span><span class="cx" style="display: block; padding: 0 10px">                process( last );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        var start = new Date().getTime();
-       config.depth = config.depth ? config.depth + 1 : 1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ var start = now();
+       config.depth = ( config.depth || 0 ) + 1;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        while ( config.queue.length && !config.blocking ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ( !defined.setTimeout || config.updateRate <= 0 ||
+                               ( ( now() - start ) < config.updateRate ) ) {
+                       if ( config.current ) {
+
+                               // Reset async tracking for each phase of the Test lifecycle
+                               config.current.usedAsync = false;
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px">                         config.queue.shift()();
</span><span class="cx" style="display: block; padding: 0 10px">                } else {
</span><span class="cx" style="display: block; padding: 0 10px">                        setTimeout( next, 13 );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1462,6 +592,79 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function begin() {
+       var i, l,
+               modulesLog = [];
+
+       // If the test run hasn't officially begun yet
+       if ( !config.started ) {
+
+               // Record the time of the test run's beginning
+               config.started = now();
+
+               verifyLoggingCallbacks();
+
+               // Delete the loose unnamed module if unused.
+               if ( config.modules[ 0 ].name === "" && config.modules[ 0 ].tests.length === 0 ) {
+                       config.modules.shift();
+               }
+
+               // Avoid unnecessary information by not logging modules' test environments
+               for ( i = 0, l = config.modules.length; i < l; i++ ) {
+                       modulesLog.push({
+                               name: config.modules[ i ].name,
+                               tests: config.modules[ i ].tests
+                       });
+               }
+
+               // The test run is officially beginning now
+               runLoggingCallbacks( "begin", {
+                       totalTests: Test.count,
+                       modules: modulesLog
+               });
+       }
+
+       config.blocking = false;
+       process( true );
+}
+
+function resumeProcessing() {
+       runStarted = true;
+
+       // A slight delay to allow this iteration of the event loop to finish (more assertions, etc.)
+       if ( defined.setTimeout ) {
+               setTimeout(function() {
+                       if ( config.current && config.current.semaphore > 0 ) {
+                               return;
+                       }
+                       if ( config.timeout ) {
+                               clearTimeout( config.timeout );
+                       }
+
+                       begin();
+               }, 13 );
+       } else {
+               begin();
+       }
+}
+
+function pauseProcessing() {
+       config.blocking = true;
+
+       if ( config.testTimeout && defined.setTimeout ) {
+               clearTimeout( config.timeout );
+               config.timeout = setTimeout(function() {
+                       if ( config.current ) {
+                               config.current.semaphore = 0;
+                               QUnit.pushFailure( "Test timed out", sourceFromStacktrace( 2 ) );
+                       } else {
+                               throw new Error( "Test timed out" );
+                       }
+                       resumeProcessing();
+               }, config.testTimeout );
+       }
+}
+
</ins><span class="cx" style="display: block; padding: 0 10px"> function saveGlobal() {
</span><span class="cx" style="display: block; padding: 0 10px">        config.pollution = [];
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1487,12 +690,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        newGlobals = diff( config.pollution, old );
</span><span class="cx" style="display: block; padding: 0 10px">        if ( newGlobals.length > 0 ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join(", ") );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join( ", " ) );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        deletedGlobals = diff( old, config.pollution );
</span><span class="cx" style="display: block; padding: 0 10px">        if ( deletedGlobals.length > 0 ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join(", ") );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join( ", " ) );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1503,7 +706,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        for ( i = 0; i < result.length; i++ ) {
</span><span class="cx" style="display: block; padding: 0 10px">                for ( j = 0; j < b.length; j++ ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if ( result[i] === b[j] ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ( result[ i ] === b[ j ] ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 result.splice( i, 1 );
</span><span class="cx" style="display: block; padding: 0 10px">                                i--;
</span><span class="cx" style="display: block; padding: 0 10px">                                break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1513,14 +716,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">        return result;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function extend( a, b ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function extend( a, b, undefOnly ) {
</ins><span class="cx" style="display: block; padding: 0 10px">         for ( var prop in b ) {
</span><span class="cx" style="display: block; padding: 0 10px">                if ( hasOwn.call( b, prop ) ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                         // Avoid "Member not found" error in IE8 caused by messing with window.constructor
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( !( prop === "constructor" && a === window ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                if ( b[ prop ] === undefined ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        delete a[ prop ];
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                } else {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         } else if ( !( undefOnly && typeof a[ prop ] !== "undefined" ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         a[ prop ] = b[ prop ];
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1530,77 +734,680 @@
</span><span class="cx" style="display: block; padding: 0 10px">        return a;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * @param {HTMLElement} elem
- * @param {string} type
- * @param {Function} fn
- */
-function addEvent( elem, type, fn ) {
-       // Standards-based browsers
-       if ( elem.addEventListener ) {
-               elem.addEventListener( type, fn, false );
-       // IE
-       } else {
-               elem.attachEvent( "on" + type, fn );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function runLoggingCallbacks( key, args ) {
+       var i, l, callbacks;
+
+       callbacks = config.callbacks[ key ];
+       for ( i = 0, l = callbacks.length; i < l; i++ ) {
+               callbacks[ i ]( args );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * @param {Array|NodeList} elems
- * @param {string} type
- * @param {Function} fn
- */
-function addEvents( elems, type, fn ) {
-       var i = elems.length;
-       while ( i-- ) {
-               addEvent( elems[i], type, fn );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+// DEPRECATED: This will be removed on 2.0.0+
+// This function verifies if the loggingCallbacks were modified by the user
+// If so, it will restore it, assign the given callback and print a console warning
+function verifyLoggingCallbacks() {
+       var loggingCallback, userCallback;
+
+       for ( loggingCallback in loggingCallbacks ) {
+               if ( QUnit[ loggingCallback ] !== loggingCallbacks[ loggingCallback ] ) {
+
+                       userCallback = QUnit[ loggingCallback ];
+
+                       // Restore the callback function
+                       QUnit[ loggingCallback ] = loggingCallbacks[ loggingCallback ];
+
+                       // Assign the deprecated given callback
+                       QUnit[ loggingCallback ]( userCallback );
+
+                       if ( window.console && window.console.warn ) {
+                               window.console.warn(
+                                       "QUnit." + loggingCallback + " was replaced with a new value.\n" +
+                                       "Please, check out the documentation on how to apply logging callbacks.\n" +
+                                       "Reference: http://api.qunitjs.com/category/callbacks/"
+                               );
+                       }
+               }
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function hasClass( elem, name ) {
-       return (" " + elem.className + " ").indexOf(" " + name + " ") > -1;
-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+// from jquery.js
+function inArray( elem, array ) {
+       if ( array.indexOf ) {
+               return array.indexOf( elem );
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function addClass( elem, name ) {
-       if ( !hasClass( elem, name ) ) {
-               elem.className += (elem.className ? " " : "") + name;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for ( var i = 0, length = array.length; i < length; i++ ) {
+               if ( array[ i ] === elem ) {
+                       return i;
+               }
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+       return -1;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function removeClass( elem, name ) {
-       var set = " " + elem.className + " ";
-       // Class name may appear multiple times
-       while ( set.indexOf(" " + name + " ") > -1 ) {
-               set = set.replace(" " + name + " " , " ");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function Test( settings ) {
+       var i, l;
+
+       ++Test.count;
+
+       extend( this, settings );
+       this.assertions = [];
+       this.semaphore = 0;
+       this.usedAsync = false;
+       this.module = config.currentModule;
+       this.stack = sourceFromStacktrace( 3 );
+
+       // Register unique strings
+       for ( i = 0, l = this.module.tests; i < l.length; i++ ) {
+               if ( this.module.tests[ i ].name === this.testName ) {
+                       this.testName += " ";
+               }
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // If possible, trim it for prettiness, but not necessarily
-       elem.className = typeof set.trim === "function" ? set.trim() : set.replace(/^\s+|\s+$/g, "");
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+       this.testId = generateHash( this.module.name, this.testName );
+
+       this.module.tests.push({
+               name: this.testName,
+               testId: this.testId
+       });
+
+       if ( settings.skip ) {
+
+               // Skipped tests will fully ignore any sent callback
+               this.callback = function() {};
+               this.async = false;
+               this.expected = 0;
+       } else {
+               this.assert = new Assert( this );
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function id( name ) {
-       return !!( typeof document !== "undefined" && document && document.getElementById ) &&
-               document.getElementById( name );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+Test.count = 0;
+
+Test.prototype = {
+       before: function() {
+               if (
+
+                       // Emit moduleStart when we're switching from one module to another
+                       this.module !== config.previousModule ||
+
+                               // They could be equal (both undefined) but if the previousModule property doesn't
+                               // yet exist it means this is the first test in a suite that isn't wrapped in a
+                               // module, in which case we'll just emit a moduleStart event for 'undefined'.
+                               // Without this, reporters can get testStart before moduleStart  which is a problem.
+                               !hasOwn.call( config, "previousModule" )
+               ) {
+                       if ( hasOwn.call( config, "previousModule" ) ) {
+                               runLoggingCallbacks( "moduleDone", {
+                                       name: config.previousModule.name,
+                                       tests: config.previousModule.tests,
+                                       failed: config.moduleStats.bad,
+                                       passed: config.moduleStats.all - config.moduleStats.bad,
+                                       total: config.moduleStats.all,
+                                       runtime: now() - config.moduleStats.started
+                               });
+                       }
+                       config.previousModule = this.module;
+                       config.moduleStats = { all: 0, bad: 0, started: now() };
+                       runLoggingCallbacks( "moduleStart", {
+                               name: this.module.name,
+                               tests: this.module.tests
+                       });
+               }
+
+               config.current = this;
+
+               this.testEnvironment = extend( {}, this.module.testEnvironment );
+               delete this.testEnvironment.beforeEach;
+               delete this.testEnvironment.afterEach;
+
+               this.started = now();
+               runLoggingCallbacks( "testStart", {
+                       name: this.testName,
+                       module: this.module.name,
+                       testId: this.testId
+               });
+
+               if ( !config.pollution ) {
+                       saveGlobal();
+               }
+       },
+
+       run: function() {
+               var promise;
+
+               config.current = this;
+
+               if ( this.async ) {
+                       QUnit.stop();
+               }
+
+               this.callbackStarted = now();
+
+               if ( config.notrycatch ) {
+                       promise = this.callback.call( this.testEnvironment, this.assert );
+                       this.resolvePromise( promise );
+                       return;
+               }
+
+               try {
+                       promise = this.callback.call( this.testEnvironment, this.assert );
+                       this.resolvePromise( promise );
+               } catch ( e ) {
+                       this.pushFailure( "Died on test #" + ( this.assertions.length + 1 ) + " " +
+                               this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) );
+
+                       // else next test will carry the responsibility
+                       saveGlobal();
+
+                       // Restart the tests if they're blocking
+                       if ( config.blocking ) {
+                               QUnit.start();
+                       }
+               }
+       },
+
+       after: function() {
+               checkPollution();
+       },
+
+       queueHook: function( hook, hookName ) {
+               var promise,
+                       test = this;
+               return function runHook() {
+                       config.current = test;
+                       if ( config.notrycatch ) {
+                               promise = hook.call( test.testEnvironment, test.assert );
+                               test.resolvePromise( promise, hookName );
+                               return;
+                       }
+                       try {
+                               promise = hook.call( test.testEnvironment, test.assert );
+                               test.resolvePromise( promise, hookName );
+                       } catch ( error ) {
+                               test.pushFailure( hookName + " failed on " + test.testName + ": " +
+                                       ( error.message || error ), extractStacktrace( error, 0 ) );
+                       }
+               };
+       },
+
+       // Currently only used for module level hooks, can be used to add global level ones
+       hooks: function( handler ) {
+               var hooks = [];
+
+               // Hooks are ignored on skipped tests
+               if ( this.skip ) {
+                       return hooks;
+               }
+
+               if ( this.module.testEnvironment &&
+                               QUnit.objectType( this.module.testEnvironment[ handler ] ) === "function" ) {
+                       hooks.push( this.queueHook( this.module.testEnvironment[ handler ], handler ) );
+               }
+
+               return hooks;
+       },
+
+       finish: function() {
+               config.current = this;
+               if ( config.requireExpects && this.expected === null ) {
+                       this.pushFailure( "Expected number of assertions to be defined, but expect() was " +
+                               "not called.", this.stack );
+               } else if ( this.expected !== null && this.expected !== this.assertions.length ) {
+                       this.pushFailure( "Expected " + this.expected + " assertions, but " +
+                               this.assertions.length + " were run", this.stack );
+               } else if ( this.expected === null && !this.assertions.length ) {
+                       this.pushFailure( "Expected at least one assertion, but none were run - call " +
+                               "expect(0) to accept zero assertions.", this.stack );
+               }
+
+               var i,
+                       bad = 0;
+
+               this.runtime = now() - this.started;
+               config.stats.all += this.assertions.length;
+               config.moduleStats.all += this.assertions.length;
+
+               for ( i = 0; i < this.assertions.length; i++ ) {
+                       if ( !this.assertions[ i ].result ) {
+                               bad++;
+                               config.stats.bad++;
+                               config.moduleStats.bad++;
+                       }
+               }
+
+               runLoggingCallbacks( "testDone", {
+                       name: this.testName,
+                       module: this.module.name,
+                       skipped: !!this.skip,
+                       failed: bad,
+                       passed: this.assertions.length - bad,
+                       total: this.assertions.length,
+                       runtime: this.runtime,
+
+                       // HTML Reporter use
+                       assertions: this.assertions,
+                       testId: this.testId,
+
+                       // DEPRECATED: this property will be removed in 2.0.0, use runtime instead
+                       duration: this.runtime
+               });
+
+               // QUnit.reset() is deprecated and will be replaced for a new
+               // fixture reset function on QUnit 2.0/2.1.
+               // It's still called here for backwards compatibility handling
+               QUnit.reset();
+
+               config.current = undefined;
+       },
+
+       queue: function() {
+               var bad,
+                       test = this;
+
+               if ( !this.valid() ) {
+                       return;
+               }
+
+               function run() {
+
+                       // each of these can by async
+                       synchronize([
+                               function() {
+                                       test.before();
+                               },
+
+                               test.hooks( "beforeEach" ),
+
+                               function() {
+                                       test.run();
+                               },
+
+                               test.hooks( "afterEach" ).reverse(),
+
+                               function() {
+                                       test.after();
+                               },
+                               function() {
+                                       test.finish();
+                               }
+                       ]);
+               }
+
+               // `bad` initialized at top of scope
+               // defer when previous test run passed, if storage is available
+               bad = QUnit.config.reorder && defined.sessionStorage &&
+                               +sessionStorage.getItem( "qunit-test-" + this.module.name + "-" + this.testName );
+
+               if ( bad ) {
+                       run();
+               } else {
+                       synchronize( run, true );
+               }
+       },
+
+       push: function( result, actual, expected, message ) {
+               var source,
+                       details = {
+                               module: this.module.name,
+                               name: this.testName,
+                               result: result,
+                               message: message,
+                               actual: actual,
+                               expected: expected,
+                               testId: this.testId,
+                               runtime: now() - this.started
+                       };
+
+               if ( !result ) {
+                       source = sourceFromStacktrace();
+
+                       if ( source ) {
+                               details.source = source;
+                       }
+               }
+
+               runLoggingCallbacks( "log", details );
+
+               this.assertions.push({
+                       result: !!result,
+                       message: message
+               });
+       },
+
+       pushFailure: function( message, source, actual ) {
+               if ( !this instanceof Test ) {
+                       throw new Error( "pushFailure() assertion outside test context, was " +
+                               sourceFromStacktrace( 2 ) );
+               }
+
+               var details = {
+                               module: this.module.name,
+                               name: this.testName,
+                               result: false,
+                               message: message || "error",
+                               actual: actual || null,
+                               testId: this.testId,
+                               runtime: now() - this.started
+                       };
+
+               if ( source ) {
+                       details.source = source;
+               }
+
+               runLoggingCallbacks( "log", details );
+
+               this.assertions.push({
+                       result: false,
+                       message: message
+               });
+       },
+
+       resolvePromise: function( promise, phase ) {
+               var then, message,
+                       test = this;
+               if ( promise != null ) {
+                       then = promise.then;
+                       if ( QUnit.objectType( then ) === "function" ) {
+                               QUnit.stop();
+                               then.call(
+                                       promise,
+                                       QUnit.start,
+                                       function( error ) {
+                                               message = "Promise rejected " +
+                                                       ( !phase ? "during" : phase.replace( /Each$/, "" ) ) +
+                                                       " " + test.testName + ": " + ( error.message || error );
+                                               test.pushFailure( message, extractStacktrace( error, 0 ) );
+
+                                               // else next test will carry the responsibility
+                                               saveGlobal();
+
+                                               // Unblock
+                                               QUnit.start();
+                                       }
+                               );
+                       }
+               }
+       },
+
+       valid: function() {
+               var include,
+                       filter = config.filter && config.filter.toLowerCase(),
+                       module = QUnit.urlParams.module && QUnit.urlParams.module.toLowerCase(),
+                       fullName = ( this.module.name + ": " + this.testName ).toLowerCase();
+
+               // Internally-generated tests are always valid
+               if ( this.callback && this.callback.validTest ) {
+                       return true;
+               }
+
+               if ( config.testId.length > 0 && inArray( this.testId, config.testId ) < 0 ) {
+                       return false;
+               }
+
+               if ( module && ( !this.module.name || this.module.name.toLowerCase() !== module ) ) {
+                       return false;
+               }
+
+               if ( !filter ) {
+                       return true;
+               }
+
+               include = filter.charAt( 0 ) !== "!";
+               if ( !include ) {
+                       filter = filter.slice( 1 );
+               }
+
+               // If the filter matches, we need to honour include
+               if ( fullName.indexOf( filter ) !== -1 ) {
+                       return include;
+               }
+
+               // Otherwise, do the opposite
+               return !include;
+       }
+
+};
+
+// Resets the test setup. Useful for tests that modify the DOM.
+/*
+DEPRECATED: Use multiple tests instead of resetting inside a test.
+Use testStart or testDone for custom cleanup.
+This method will throw an error in 2.0, and will be removed in 2.1
+*/
+QUnit.reset = function() {
+
+       // Return on non-browser environments
+       // This is necessary to not break on node tests
+       if ( typeof window === "undefined" ) {
+               return;
+       }
+
+       var fixture = defined.document && document.getElementById &&
+                       document.getElementById( "qunit-fixture" );
+
+       if ( fixture ) {
+               fixture.innerHTML = config.fixture;
+       }
+};
+
+QUnit.pushFailure = function() {
+       if ( !QUnit.config.current ) {
+               throw new Error( "pushFailure() assertion outside test context, in " +
+                       sourceFromStacktrace( 2 ) );
+       }
+
+       // Gets current test obj
+       var currentTest = QUnit.config.current;
+
+       return currentTest.pushFailure.apply( currentTest, arguments );
+};
+
+// Based on Java's String.hashCode, a simple but not
+// rigorously collision resistant hashing function
+function generateHash( module, testName ) {
+       var hex,
+               i = 0,
+               hash = 0,
+               str = module + "\x1C" + testName,
+               len = str.length;
+
+       for ( ; i < len; i++ ) {
+               hash  = ( ( hash << 5 ) - hash ) + str.charCodeAt( i );
+               hash |= 0;
+       }
+
+       // Convert the possibly negative integer hash code into an 8 character hex string, which isn't
+       // strictly necessary but increases user understanding that the id is a SHA-like hash
+       hex = ( 0x100000000 + hash ).toString( 16 );
+       if ( hex.length < 8 ) {
+               hex = "0000000" + hex;
+       }
+
+       return hex.slice( -8 );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function registerLoggingCallback( key ) {
-       return function( callback ) {
-               config[key].push( callback );
-       };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function Assert( testContext ) {
+       this.test = testContext;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// Supports deprecated method of completely overwriting logging callbacks
-function runLoggingCallbacks( key, scope, args ) {
-       var i, callbacks;
-       if ( QUnit.hasOwnProperty( key ) ) {
-               QUnit[ key ].call(scope, args );
-       } else {
-               callbacks = config[ key ];
-               for ( i = 0; i < callbacks.length; i++ ) {
-                       callbacks[ i ].call( scope, args );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+// Assert helpers
+QUnit.assert = Assert.prototype = {
+
+       // Specify the number of expected assertions to guarantee that failed test
+       // (no assertions are run at all) don't slip through.
+       expect: function( asserts ) {
+               if ( arguments.length === 1 ) {
+                       this.test.expected = asserts;
+               } else {
+                       return this.test.expected;
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        },
+
+       // Increment this Test's semaphore counter, then return a single-use function that
+       // decrements that counter a maximum of once.
+       async: function() {
+               var test = this.test,
+                       popped = false;
+
+               test.semaphore += 1;
+               test.usedAsync = true;
+               pauseProcessing();
+
+               return function done() {
+                       if ( !popped ) {
+                               test.semaphore -= 1;
+                               popped = true;
+                               resumeProcessing();
+                       } else {
+                               test.pushFailure( "Called the callback returned from `assert.async` more than once",
+                                       sourceFromStacktrace( 2 ) );
+                       }
+               };
+       },
+
+       // Exports test.push() to the user API
+       push: function( /* result, actual, expected, message */ ) {
+               var assert = this,
+                       currentTest = ( assert instanceof Assert && assert.test ) || QUnit.config.current;
+
+               // Backwards compatibility fix.
+               // Allows the direct use of global exported assertions and QUnit.assert.*
+               // Although, it's use is not recommended as it can leak assertions
+               // to other tests from async tests, because we only get a reference to the current test,
+               // not exactly the test where assertion were intended to be called.
+               if ( !currentTest ) {
+                       throw new Error( "assertion outside test context, in " + sourceFromStacktrace( 2 ) );
+               }
+
+               if ( currentTest.usedAsync === true && currentTest.semaphore === 0 ) {
+                       currentTest.pushFailure( "Assertion after the final `assert.async` was resolved",
+                               sourceFromStacktrace( 2 ) );
+
+                       // Allow this assertion to continue running anyway...
+               }
+
+               if ( !( assert instanceof Assert ) ) {
+                       assert = currentTest.assert;
+               }
+               return assert.test.push.apply( assert.test, arguments );
+       },
+
+       ok: function( result, message ) {
+               message = message || ( result ? "okay" : "failed, expected argument to be truthy, was: " +
+                       QUnit.dump.parse( result ) );
+               this.push( !!result, result, true, message );
+       },
+
+       notOk: function( result, message ) {
+               message = message || ( !result ? "okay" : "failed, expected argument to be falsy, was: " +
+                       QUnit.dump.parse( result ) );
+               this.push( !result, result, false, message );
+       },
+
+       equal: function( actual, expected, message ) {
+               /*jshint eqeqeq:false */
+               this.push( expected == actual, actual, expected, message );
+       },
+
+       notEqual: function( actual, expected, message ) {
+               /*jshint eqeqeq:false */
+               this.push( expected != actual, actual, expected, message );
+       },
+
+       propEqual: function( actual, expected, message ) {
+               actual = objectValues( actual );
+               expected = objectValues( expected );
+               this.push( QUnit.equiv( actual, expected ), actual, expected, message );
+       },
+
+       notPropEqual: function( actual, expected, message ) {
+               actual = objectValues( actual );
+               expected = objectValues( expected );
+               this.push( !QUnit.equiv( actual, expected ), actual, expected, message );
+       },
+
+       deepEqual: function( actual, expected, message ) {
+               this.push( QUnit.equiv( actual, expected ), actual, expected, message );
+       },
+
+       notDeepEqual: function( actual, expected, message ) {
+               this.push( !QUnit.equiv( actual, expected ), actual, expected, message );
+       },
+
+       strictEqual: function( actual, expected, message ) {
+               this.push( expected === actual, actual, expected, message );
+       },
+
+       notStrictEqual: function( actual, expected, message ) {
+               this.push( expected !== actual, actual, expected, message );
+       },
+
+       "throws": function( block, expected, message ) {
+               var actual, expectedType,
+                       expectedOutput = expected,
+                       ok = false,
+                       currentTest = ( this instanceof Assert && this.test ) || QUnit.config.current;
+
+               // 'expected' is optional unless doing string comparison
+               if ( message == null && typeof expected === "string" ) {
+                       message = expected;
+                       expected = null;
+               }
+
+               currentTest.ignoreGlobalErrors = true;
+               try {
+                       block.call( currentTest.testEnvironment );
+               } catch (e) {
+                       actual = e;
+               }
+               currentTest.ignoreGlobalErrors = false;
+
+               if ( actual ) {
+                       expectedType = QUnit.objectType( expected );
+
+                       // we don't want to validate thrown error
+                       if ( !expected ) {
+                               ok = true;
+                               expectedOutput = null;
+
+                       // expected is a regexp
+                       } else if ( expectedType === "regexp" ) {
+                               ok = expected.test( errorString( actual ) );
+
+                       // expected is a string
+                       } else if ( expectedType === "string" ) {
+                               ok = expected === errorString( actual );
+
+                       // expected is a constructor, maybe an Error constructor
+                       } else if ( expectedType === "function" && actual instanceof expected ) {
+                               ok = true;
+
+                       // expected is an Error object
+                       } else if ( expectedType === "object" ) {
+                               ok = actual instanceof expected.constructor &&
+                                       actual.name === expected.name &&
+                                       actual.message === expected.message;
+
+                       // expected is a validation function which returns true if validation passed
+                       } else if ( expectedType === "function" && expected.call( {}, actual ) === true ) {
+                               expectedOutput = null;
+                               ok = true;
+                       }
+               }
+
+               currentTest.assert.push( ok, actual, expectedOutput, message );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-}
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+};
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+// Provide an alternative to assert.throws(), for enviroments that consider throws a reserved word
+// Known to us are: Closure Compiler, Narwhal
+(function() {
+       /*jshint sub:true */
+       Assert.prototype.raises = Assert.prototype[ "throws" ];
+}());
+
</ins><span class="cx" style="display: block; padding: 0 10px"> // Test for equality any JavaScript type.
</span><span class="cx" style="display: block; padding: 0 10px"> // Author: Philippe Rathé <prathe@gmail.com>
</span><span class="cx" style="display: block; padding: 0 10px"> QUnit.equiv = (function() {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1619,22 +1426,26 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        // the real equiv function
</span><span class="cx" style="display: block; padding: 0 10px">        var innerEquiv,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                 // stack to decide between skip/abort functions
</span><span class="cx" style="display: block; padding: 0 10px">                callers = [],
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                 // stack to avoiding loops from circular referencing
</span><span class="cx" style="display: block; padding: 0 10px">                parents = [],
</span><span class="cx" style="display: block; padding: 0 10px">                parentsB = [],
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                getProto = Object.getPrototypeOf || function ( obj ) {
-                       /*jshint camelcase:false */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         getProto = Object.getPrototypeOf || function( obj ) {
+                       /* jshint camelcase: false, proto: true */
</ins><span class="cx" style="display: block; padding: 0 10px">                         return obj.__proto__;
</span><span class="cx" style="display: block; padding: 0 10px">                },
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                callbacks = (function () {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         callbacks = (function() {
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // for string, boolean, number and null
</span><span class="cx" style="display: block; padding: 0 10px">                        function useStrictEquality( b, a ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                                 /*jshint eqeqeq:false */
</span><span class="cx" style="display: block; padding: 0 10px">                                if ( b instanceof a.constructor || a instanceof b.constructor ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                                         // to catch short annotation VS 'new' annotation of a
</span><span class="cx" style="display: block; padding: 0 10px">                                        // declaration
</span><span class="cx" style="display: block; padding: 0 10px">                                        // e.g. var i = 1;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1662,10 +1473,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                "regexp": function( b, a ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        return QUnit.objectType( b ) === "regexp" &&
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 // the regex itself
</span><span class="cx" style="display: block; padding: 0 10px">                                                a.source === b.source &&
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 // and its modifiers
</span><span class="cx" style="display: block; padding: 0 10px">                                                a.global === b.global &&
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 // (gmi) ...
</span><span class="cx" style="display: block; padding: 0 10px">                                                a.ignoreCase === b.ignoreCase &&
</span><span class="cx" style="display: block; padding: 0 10px">                                                a.multiline === b.multiline &&
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1676,7 +1490,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                // - abort otherwise,
</span><span class="cx" style="display: block; padding: 0 10px">                                // initial === would have catch identical references anyway
</span><span class="cx" style="display: block; padding: 0 10px">                                "function": function() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        var caller = callers[callers.length - 1];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 var caller = callers[ callers.length - 1 ];
</ins><span class="cx" style="display: block; padding: 0 10px">                                         return caller !== Object && typeof caller !== "undefined";
</span><span class="cx" style="display: block; padding: 0 10px">                                },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1700,10 +1514,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        for ( i = 0; i < len; i++ ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                loop = false;
</span><span class="cx" style="display: block; padding: 0 10px">                                                for ( j = 0; j < parents.length; j++ ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        aCircular = parents[j] === a[i];
-                                                       bCircular = parentsB[j] === b[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 aCircular = parents[ j ] === a[ i ];
+                                                       bCircular = parentsB[ j ] === b[ i ];
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         if ( aCircular || bCircular ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                if ( a[i] === b[i] || aCircular && bCircular ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         if ( a[ i ] === b[ i ] || aCircular && bCircular ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                         loop = true;
</span><span class="cx" style="display: block; padding: 0 10px">                                                                } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        parents.pop();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1712,7 +1526,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                if ( !loop && !innerEquiv(a[i], b[i]) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         if ( !loop && !innerEquiv( a[ i ], b[ i ] ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         parents.pop();
</span><span class="cx" style="display: block; padding: 0 10px">                                                        parentsB.pop();
</span><span class="cx" style="display: block; padding: 0 10px">                                                        return false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1724,6 +1538,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                "object": function( b, a ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                                         /*jshint forin:false */
</span><span class="cx" style="display: block; padding: 0 10px">                                        var i, j, loop, aCircular, bCircular,
</span><span class="cx" style="display: block; padding: 0 10px">                                                // Default to true
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1734,11 +1549,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        // comparing constructors is more strict than using
</span><span class="cx" style="display: block; padding: 0 10px">                                        // instanceof
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ( a.constructor !== b.constructor ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 // Allow objects with no prototype to be equivalent to
</span><span class="cx" style="display: block; padding: 0 10px">                                                // objects with Object as their constructor.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                if ( !(( getProto(a) === null && getProto(b) === Object.prototype ) ||
-                                                       ( getProto(b) === null && getProto(a) === Object.prototype ) ) ) {
-                                                               return false;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         if ( !( ( getProto( a ) === null && getProto( b ) === Object.prototype ) ||
+                                                       ( getProto( b ) === null && getProto( a ) === Object.prototype ) ) ) {
+                                                       return false;
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1753,10 +1569,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        for ( i in a ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                loop = false;
</span><span class="cx" style="display: block; padding: 0 10px">                                                for ( j = 0; j < parents.length; j++ ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        aCircular = parents[j] === a[i];
-                                                       bCircular = parentsB[j] === b[i];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 aCircular = parents[ j ] === a[ i ];
+                                                       bCircular = parentsB[ j ] === b[ i ];
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         if ( aCircular || bCircular ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                if ( a[i] === b[i] || aCircular && bCircular ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         if ( a[ i ] === b[ i ] || aCircular && bCircular ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                         loop = true;
</span><span class="cx" style="display: block; padding: 0 10px">                                                                } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        eq = false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1764,8 +1580,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                aProperties.push(i);
-                                               if ( !loop && !innerEquiv(a[i], b[i]) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         aProperties.push( i );
+                                               if ( !loop && !innerEquiv( a[ i ], b[ i ] ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         eq = false;
</span><span class="cx" style="display: block; padding: 0 10px">                                                        break;
</span><span class="cx" style="display: block; padding: 0 10px">                                                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1791,35 +1607,30 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        return true; // end transition
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                return (function( a, b ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         return ( (function( a, b ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         if ( a === b ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                return true; // catch the most you can
</span><span class="cx" style="display: block; padding: 0 10px">                        } else if ( a === null || b === null || typeof a === "undefined" ||
</span><span class="cx" style="display: block; padding: 0 10px">                                        typeof b === "undefined" ||
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        QUnit.objectType(a) !== QUnit.objectType(b) ) {
-                               return false; // don't lose time with error prone cases
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 QUnit.objectType( a ) !== QUnit.objectType( b ) ) {
+
+                               // don't lose time with error prone cases
+                               return false;
</ins><span class="cx" style="display: block; padding: 0 10px">                         } else {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                return bindCallbacks(a, callbacks, [ b, a ]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         return bindCallbacks( a, callbacks, [ b, a ] );
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // apply transition with (1..n) arguments
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                }( args[0], args[1] ) && innerEquiv.apply( this, args.splice(1, args.length - 1 )) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         }( args[ 0 ], args[ 1 ] ) ) &&
+                       innerEquiv.apply( this, args.splice( 1, args.length - 1 ) ) );
</ins><span class="cx" style="display: block; padding: 0 10px">         };
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        return innerEquiv;
</span><span class="cx" style="display: block; padding: 0 10px"> }());
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/**
- * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |
- * http://flesler.blogspot.com Licensed under BSD
- * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008
- *
- * @projectDescription Advanced and extensible data dumping for Javascript.
- * @version 1.0.0
- * @author Ariel Flesler
- * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}
- */
-QUnit.jsDump = (function() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+// Based on jsDump by Ariel Flesler
+// http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html
+QUnit.dump = (function() {
</ins><span class="cx" style="display: block; padding: 0 10px">         function quote( str ) {
</span><span class="cx" style="display: block; padding: 0 10px">                return "\"" + str.toString().replace( /"/g, "\\\"" ) + "\"";
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1827,48 +1638,57 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return o + "";
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px">        function join( pre, arr, post ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                var s = jsDump.separator(),
-                       base = jsDump.indent(),
-                       inner = jsDump.indent(1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         var s = dump.separator(),
+                       base = dump.indent(),
+                       inner = dump.indent( 1 );
</ins><span class="cx" style="display: block; padding: 0 10px">                 if ( arr.join ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        arr = arr.join( "," + s + inner );
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                if ( !arr ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return pre + post;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                return [ pre, inner + arr, base + post ].join(s);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         return [ pre, inner + arr, base + post ].join( s );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px">        function array( arr, stack ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                var i = arr.length, ret = new Array(i);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         var i = arr.length,
+                       ret = new Array( i );
+
+               if ( dump.maxDepth && dump.depth > dump.maxDepth ) {
+                       return "[object Array]";
+               }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 this.up();
</span><span class="cx" style="display: block; padding: 0 10px">                while ( i-- ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        ret[i] = this.parse( arr[i] , undefined , stack);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 ret[ i ] = this.parse( arr[ i ], undefined, stack );
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px">                this.down();
</span><span class="cx" style="display: block; padding: 0 10px">                return join( "[", ret, "]" );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        var reName = /^function (\w+)/,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                jsDump = {
-                       // type is used mostly internally, you can fix a (custom)type in advance
-                       parse: function( obj, type, stack ) {
-                               stack = stack || [ ];
-                               var inStack, res,
-                                       parser = this.parsers[ type || this.typeOf(obj) ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         dump = {
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                type = typeof parser;
-                               inStack = inArray( obj, stack );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // objType is used mostly internally, you can fix a (custom) type in advance
+                       parse: function( obj, objType, stack ) {
+                               stack = stack || [];
+                               var res, parser, parserType,
+                                       inStack = inArray( obj, stack );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                if ( inStack !== -1 ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        return "recursion(" + (inStack - stack.length) + ")";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 return "recursion(" + ( inStack - stack.length ) + ")";
</ins><span class="cx" style="display: block; padding: 0 10px">                                 }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if ( type === "function" )  {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+                               objType = objType || this.typeOf( obj  );
+                               parser = this.parsers[ objType ];
+                               parserType = typeof parser;
+
+                               if ( parserType === "function" ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         stack.push( obj );
</span><span class="cx" style="display: block; padding: 0 10px">                                        res = parser.call( this, obj, stack );
</span><span class="cx" style="display: block; padding: 0 10px">                                        stack.pop();
</span><span class="cx" style="display: block; padding: 0 10px">                                        return res;
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                return ( type === "string" ) ? parser : this.parsers.error;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         return ( parserType === "string" ) ? parser : this.parsers.error;
</ins><span class="cx" style="display: block; padding: 0 10px">                         },
</span><span class="cx" style="display: block; padding: 0 10px">                        typeOf: function( obj ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                var type;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1876,23 +1696,29 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        type = "null";
</span><span class="cx" style="display: block; padding: 0 10px">                                } else if ( typeof obj === "undefined" ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        type = "undefined";
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                } else if ( QUnit.is( "regexp", obj) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         } else if ( QUnit.is( "regexp", obj ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         type = "regexp";
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                } else if ( QUnit.is( "date", obj) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         } else if ( QUnit.is( "date", obj ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         type = "date";
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                } else if ( QUnit.is( "function", obj) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         } else if ( QUnit.is( "function", obj ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         type = "function";
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                } else if ( typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined" ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         } else if ( obj.setInterval !== undefined &&
+                                               obj.document !== undefined &&
+                                               obj.nodeType === undefined ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         type = "window";
</span><span class="cx" style="display: block; padding: 0 10px">                                } else if ( obj.nodeType === 9 ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        type = "document";
</span><span class="cx" style="display: block; padding: 0 10px">                                } else if ( obj.nodeType ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        type = "node";
</span><span class="cx" style="display: block; padding: 0 10px">                                } else if (
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                                         // native arrays
</span><span class="cx" style="display: block; padding: 0 10px">                                        toString.call( obj ) === "[object Array]" ||
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                                         // NodeList objects
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        ( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === "undefined" ) ) )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 ( typeof obj.length === "number" && obj.item !== undefined &&
+                                       ( obj.length ? obj.item( 0 ) === obj[ 0 ] : ( obj.item( 0 ) === null &&
+                                       obj[ 0 ] === undefined ) ) )
</ins><span class="cx" style="display: block; padding: 0 10px">                                 ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        type = "array";
</span><span class="cx" style="display: block; padding: 0 10px">                                } else if ( obj.constructor === Error.prototype.constructor ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1903,7 +1729,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                return type;
</span><span class="cx" style="display: block; padding: 0 10px">                        },
</span><span class="cx" style="display: block; padding: 0 10px">                        separator: function() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                return this.multiline ? this.HTML ? "<br />" : "\n" : this.HTML ? "&nbsp;" : " ";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         return this.multiline ? this.HTML ? "<br />" : "\n" : this.HTML ? "&#160;" : " ";
</ins><span class="cx" style="display: block; padding: 0 10px">                         },
</span><span class="cx" style="display: block; padding: 0 10px">                        // extra can be a number, shortcut for increasing-calling-decreasing
</span><span class="cx" style="display: block; padding: 0 10px">                        indent: function( extra ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1912,9 +1738,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                var chr = this.indentChar;
</span><span class="cx" style="display: block; padding: 0 10px">                                if ( this.HTML ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        chr = chr.replace( /\t/g, "   " ).replace( / /g, "&nbsp;" );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 chr = chr.replace( /\t/g, "   " ).replace( / /g, "&#160;" );
</ins><span class="cx" style="display: block; padding: 0 10px">                                 }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                return new Array( this.depth + ( extra || 0 ) ).join(chr);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         return new Array( this.depth + ( extra || 0 ) ).join( chr );
</ins><span class="cx" style="display: block; padding: 0 10px">                         },
</span><span class="cx" style="display: block; padding: 0 10px">                        up: function( a ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                this.depth += a || 1;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1923,7 +1749,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                this.depth -= a || 1;
</span><span class="cx" style="display: block; padding: 0 10px">                        },
</span><span class="cx" style="display: block; padding: 0 10px">                        setParser: function( name, parser ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                this.parsers[name] = parser;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         this.parsers[ name ] = parser;
</ins><span class="cx" style="display: block; padding: 0 10px">                         },
</span><span class="cx" style="display: block; padding: 0 10px">                        // The next 3 are exposed so you can use them
</span><span class="cx" style="display: block; padding: 0 10px">                        quote: quote,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1931,11 +1757,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        join: join,
</span><span class="cx" style="display: block; padding: 0 10px">                        //
</span><span class="cx" style="display: block; padding: 0 10px">                        depth: 1,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        // This is the list of parsers, to modify them, use jsDump.setParser
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 maxDepth: QUnit.config.maxDepth,
+
+                       // This is the list of parsers, to modify them, use dump.setParser
</ins><span class="cx" style="display: block; padding: 0 10px">                         parsers: {
</span><span class="cx" style="display: block; padding: 0 10px">                                window: "[Window]",
</span><span class="cx" style="display: block; padding: 0 10px">                                document: "[Document]",
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                error: function(error) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         error: function( error ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         return "Error(\"" + error.message + "\")";
</span><span class="cx" style="display: block; padding: 0 10px">                                },
</span><span class="cx" style="display: block; padding: 0 10px">                                unknown: "[Unknown]",
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1943,52 +1771,71 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                "undefined": "undefined",
</span><span class="cx" style="display: block; padding: 0 10px">                                "function": function( fn ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        var ret = "function",
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 // functions never have name in IE
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         name = "name" in fn ? fn.name : ( reName.exec( fn ) || [] )[ 1 ];
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ( name ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                ret += " " + name;
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                        ret += "( ";
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        ret = [ ret, QUnit.jsDump.parse( fn, "functionArgs" ), "){" ].join( "" );
-                                       return join( ret, QUnit.jsDump.parse(fn,"functionCode" ), "}" );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 ret = [ ret, dump.parse( fn, "functionArgs" ), "){" ].join( "" );
+                                       return join( ret, dump.parse( fn, "functionCode" ), "}" );
</ins><span class="cx" style="display: block; padding: 0 10px">                                 },
</span><span class="cx" style="display: block; padding: 0 10px">                                array: array,
</span><span class="cx" style="display: block; padding: 0 10px">                                nodelist: array,
</span><span class="cx" style="display: block; padding: 0 10px">                                "arguments": array,
</span><span class="cx" style="display: block; padding: 0 10px">                                object: function( map, stack ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        /*jshint forin:false */
-                                       var ret = [ ], keys, key, val, i;
-                                       QUnit.jsDump.up();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 var keys, key, val, i, nonEnumerableProperties,
+                                               ret = [];
+
+                                       if ( dump.maxDepth && dump.depth > dump.maxDepth ) {
+                                               return "[object Object]";
+                                       }
+
+                                       dump.up();
</ins><span class="cx" style="display: block; padding: 0 10px">                                         keys = [];
</span><span class="cx" style="display: block; padding: 0 10px">                                        for ( key in map ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                keys.push( key );
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+                                       // Some properties are not always enumerable on Error objects.
+                                       nonEnumerableProperties = [ "message", "name" ];
+                                       for ( i in nonEnumerableProperties ) {
+                                               key = nonEnumerableProperties[ i ];
+                                               if ( key in map && inArray( key, keys ) < 0 ) {
+                                                       keys.push( key );
+                                               }
+                                       }
</ins><span class="cx" style="display: block; padding: 0 10px">                                         keys.sort();
</span><span class="cx" style="display: block; padding: 0 10px">                                        for ( i = 0; i < keys.length; i++ ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                key = keys[ i ];
</span><span class="cx" style="display: block; padding: 0 10px">                                                val = map[ key ];
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                ret.push( QUnit.jsDump.parse( key, "key" ) + ": " + QUnit.jsDump.parse( val, undefined, stack ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         ret.push( dump.parse( key, "key" ) + ": " +
+                                                       dump.parse( val, undefined, stack ) );
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        QUnit.jsDump.down();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 dump.down();
</ins><span class="cx" style="display: block; padding: 0 10px">                                         return join( "{", ret, "}" );
</span><span class="cx" style="display: block; padding: 0 10px">                                },
</span><span class="cx" style="display: block; padding: 0 10px">                                node: function( node ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        var len, i, val,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                open = QUnit.jsDump.HTML ? "&lt;" : "<",
-                                               close = QUnit.jsDump.HTML ? "&gt;" : ">",
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         open = dump.HTML ? "&lt;" : "<",
+                                               close = dump.HTML ? "&gt;" : ">",
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 tag = node.nodeName.toLowerCase(),
</span><span class="cx" style="display: block; padding: 0 10px">                                                ret = open + tag,
</span><span class="cx" style="display: block; padding: 0 10px">                                                attrs = node.attributes;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ( attrs ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                for ( i = 0, len = attrs.length; i < len; i++ ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        val = attrs[i].nodeValue;
-                                                       // IE6 includes all attributes in .attributes, even ones not explicitly set.
-                                                       // Those have values like undefined, null, 0, false, "" or "inherit".
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 val = attrs[ i ].nodeValue;
+
+                                                       // IE6 includes all attributes in .attributes, even ones not explicitly
+                                                       // set. Those have values like undefined, null, 0, false, "" or
+                                                       // "inherit".
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         if ( val && val !== "inherit" ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                ret += " " + attrs[i].nodeName + "=" + QUnit.jsDump.parse( val, "attribute" );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         ret += " " + attrs[ i ].nodeName + "=" +
+                                                                       dump.parse( val, "attribute" );
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         }
</span><span class="cx" style="display: block; padding: 0 10px">                                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2001,6 +1848,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        return ret + open + "/" + tag + close;
</span><span class="cx" style="display: block; padding: 0 10px">                                },
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // function calls it internally, it's the arguments part of the function
</span><span class="cx" style="display: block; padding: 0 10px">                                functionArgs: function( fn ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        var args,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2010,10 +1858,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                return "";
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        args = new Array(l);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 args = new Array( l );
</ins><span class="cx" style="display: block; padding: 0 10px">                                         while ( l-- ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 // 97 is 'a'
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                args[l] = String.fromCharCode(97+l);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         args[ l ] = String.fromCharCode( 97 + l );
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><span class="cx" style="display: block; padding: 0 10px">                                        return " " + args.join( ", " ) + " ";
</span><span class="cx" style="display: block; padding: 0 10px">                                },
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2037,176 +1886,1943 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        multiline: true
</span><span class="cx" style="display: block; padding: 0 10px">                };
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        return jsDump;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return dump;
</ins><span class="cx" style="display: block; padding: 0 10px"> }());
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// from jquery.js
-function inArray( elem, array ) {
-       if ( array.indexOf ) {
-               return array.indexOf( elem );
-       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+// back compat
+QUnit.jsDump = QUnit.dump;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        for ( var i = 0, length = array.length; i < length; i++ ) {
-               if ( array[ i ] === elem ) {
-                       return i;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+// For browser, export only select globals
+if ( typeof window !== "undefined" ) {
+
+       // Deprecated
+       // Extend assert methods to QUnit and Global scope through Backwards compatibility
+       (function() {
+               var i,
+                       assertions = Assert.prototype;
+
+               function applyCurrent( current ) {
+                       return function() {
+                               var assert = new Assert( QUnit.config.current );
+                               current.apply( assert, arguments );
+                       };
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        }
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        return -1;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         for ( i in assertions ) {
+                       QUnit[ i ] = applyCurrent( assertions[ i ] );
+               }
+       })();
+
+       (function() {
+               var i, l,
+                       keys = [
+                               "test",
+                               "module",
+                               "expect",
+                               "asyncTest",
+                               "start",
+                               "stop",
+                               "ok",
+                               "notOk",
+                               "equal",
+                               "notEqual",
+                               "propEqual",
+                               "notPropEqual",
+                               "deepEqual",
+                               "notDeepEqual",
+                               "strictEqual",
+                               "notStrictEqual",
+                               "throws"
+                       ];
+
+               for ( i = 0, l = keys.length; i < l; i++ ) {
+                       window[ keys[ i ] ] = QUnit[ keys[ i ] ];
+               }
+       })();
+
+       window.QUnit = QUnit;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+// For nodejs
+if ( typeof module !== "undefined" && module && module.exports ) {
+       module.exports = QUnit;
+
+       // For consistency with CommonJS environments' exports
+       module.exports.QUnit = QUnit;
+}
+
+// For CommonJS with exports, but without module.exports, like Rhino
+if ( typeof exports !== "undefined" && exports ) {
+       exports.QUnit = QUnit;
+}
+
+if ( typeof define === "function" && define.amd ) {
+       define( function() {
+               return QUnit;
+       } );
+       QUnit.config.autostart = false;
+}
+
+// Get a reference to the global object, like window in browsers
+}( (function() {
+       return this;
+})() ));
+
+/*istanbul ignore next */
+// jscs:disable maximumLineLength
</ins><span class="cx" style="display: block; padding: 0 10px"> /*
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Javascript Diff Algorithm
- *  By John Resig (http://ejohn.org/)
- *  Modified by Chu Alan "sprite"
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * This file is a modified version of google-diff-match-patch's JavaScript implementation
+ * (https://code.google.com/p/google-diff-match-patch/source/browse/trunk/javascript/diff_match_patch_uncompressed.js),
+ * modifications are licensed as more fully set forth in LICENSE.txt.
</ins><span class="cx" style="display: block; padding: 0 10px">  *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Released under the MIT license.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * The original source of google-diff-match-patch is attributable and licensed as follows:
</ins><span class="cx" style="display: block; padding: 0 10px">  *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Copyright 2006 Google Inc.
+ * http://code.google.com/p/google-diff-match-patch/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
</ins><span class="cx" style="display: block; padding: 0 10px">  * More Info:
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- *  http://ejohn.org/projects/javascript-diff-algorithm/
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *  https://code.google.com/p/google-diff-match-patch/
</ins><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * Usage: QUnit.diff(expected, actual)
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) == "the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over"
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) === "the  quick <del>brown </del> fox jump<ins>s</ins><del>ed</del over"
</ins><span class="cx" style="display: block; padding: 0 10px">  */
</span><span class="cx" style="display: block; padding: 0 10px"> QUnit.diff = (function() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        /*jshint eqeqeq:false, eqnull:true */
-       function diff( o, n ) {
-               var i,
-                       ns = {},
-                       os = {};
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                for ( i = 0; i < n.length; i++ ) {
-                       if ( !hasOwn.call( ns, n[i] ) ) {
-                               ns[ n[i] ] = {
-                                       rows: [],
-                                       o: null
-                               };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+    function DiffMatchPatch() {
+
+        // Defaults.
+        // Redefine these in your program to override the defaults.
+
+        // Number of seconds to map a diff before giving up (0 for infinity).
+        this.DiffTimeout = 1.0;
+        // Cost of an empty edit operation in terms of edit characters.
+        this.DiffEditCost = 4;
+    }
+
+    //  DIFF FUNCTIONS
+
+    /**
+     * The data structure representing a diff is an array of tuples:
+     * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]
+     * which means: delete 'Hello', add 'Goodbye' and keep ' world.'
+     */
+    var DIFF_DELETE = -1,
+               DIFF_INSERT = 1,
+               DIFF_EQUAL = 0;
+
+    /**
+     * Find the differences between two texts.  Simplifies the problem by stripping
+     * any common prefix or suffix off the texts before diffing.
+     * @param {string} text1 Old string to be diffed.
+     * @param {string} text2 New string to be diffed.
+     * @param {boolean=} optChecklines Optional speedup flag. If present and false,
+     *     then don't run a line-level diff first to identify the changed areas.
+     *     Defaults to true, which does a faster, slightly less optimal diff.
+     * @param {number} optDeadline Optional time when the diff should be complete
+     *     by.  Used internally for recursive calls.  Users should set DiffTimeout
+     *     instead.
+     * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+     */
+    DiffMatchPatch.prototype.DiffMain = function( text1, text2, optChecklines, optDeadline ) {
+        var deadline, checklines, commonlength,
+                       commonprefix, commonsuffix, diffs;
+        // Set a deadline by which time the diff must be complete.
+        if ( typeof optDeadline === "undefined" ) {
+            if ( this.DiffTimeout <= 0 ) {
+                optDeadline = Number.MAX_VALUE;
+            } else {
+                optDeadline = ( new Date() ).getTime() + this.DiffTimeout * 1000;
+            }
+        }
+        deadline = optDeadline;
+
+        // Check for null inputs.
+        if ( text1 === null || text2 === null ) {
+            throw new Error( "Null input. (DiffMain)" );
+        }
+
+        // Check for equality (speedup).
+        if ( text1 === text2 ) {
+            if ( text1 ) {
+                return [
+                    [ DIFF_EQUAL, text1 ]
+                ];
+            }
+            return [];
+        }
+
+        if ( typeof optChecklines === "undefined" ) {
+            optChecklines = true;
+        }
+
+        checklines = optChecklines;
+
+        // Trim off common prefix (speedup).
+        commonlength = this.diffCommonPrefix( text1, text2 );
+        commonprefix = text1.substring( 0, commonlength );
+        text1 = text1.substring( commonlength );
+        text2 = text2.substring( commonlength );
+
+        // Trim off common suffix (speedup).
+        /////////
+        commonlength = this.diffCommonSuffix( text1, text2 );
+        commonsuffix = text1.substring( text1.length - commonlength );
+        text1 = text1.substring( 0, text1.length - commonlength );
+        text2 = text2.substring( 0, text2.length - commonlength );
+
+        // Compute the diff on the middle block.
+        diffs = this.diffCompute( text1, text2, checklines, deadline );
+
+        // Restore the prefix and suffix.
+        if ( commonprefix ) {
+            diffs.unshift( [ DIFF_EQUAL, commonprefix ] );
+        }
+        if ( commonsuffix ) {
+            diffs.push( [ DIFF_EQUAL, commonsuffix ] );
+        }
+        this.diffCleanupMerge( diffs );
+        return diffs;
+    };
+
+    /**
+     * Reduce the number of edits by eliminating operationally trivial equalities.
+     * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+     */
+    DiffMatchPatch.prototype.diffCleanupEfficiency = function( diffs ) {
+        var changes, equalities, equalitiesLength, lastequality,
+                       pointer, preIns, preDel, postIns, postDel;
+        changes = false;
+        equalities = []; // Stack of indices where equalities are found.
+        equalitiesLength = 0; // Keeping our own length var is faster in JS.
+        /** @type {?string} */
+        lastequality = null;
+        // Always equal to diffs[equalities[equalitiesLength - 1]][1]
+        pointer = 0; // Index of current position.
+        // Is there an insertion operation before the last equality.
+        preIns = false;
+        // Is there a deletion operation before the last equality.
+        preDel = false;
+        // Is there an insertion operation after the last equality.
+        postIns = false;
+        // Is there a deletion operation after the last equality.
+        postDel = false;
+        while ( pointer < diffs.length ) {
+            if ( diffs[ pointer ][ 0 ] === DIFF_EQUAL ) { // Equality found.
+                if ( diffs[ pointer ][ 1 ].length < this.DiffEditCost && ( postIns || postDel ) ) {
+                    // Candidate found.
+                    equalities[ equalitiesLength++ ] = pointer;
+                    preIns = postIns;
+                    preDel = postDel;
+                    lastequality = diffs[ pointer ][ 1 ];
+                } else {
+                    // Not a candidate, and can never become one.
+                    equalitiesLength = 0;
+                    lastequality = null;
+                }
+                postIns = postDel = false;
+            } else { // An insertion or deletion.
+                if ( diffs[ pointer ][ 0 ] === DIFF_DELETE ) {
+                    postDel = true;
+                } else {
+                    postIns = true;
+                }
+                /*
+                 * Five types to be split:
+                 * <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del>
+                 * <ins>A</ins>X<ins>C</ins><del>D</del>
+                 * <ins>A</ins><del>B</del>X<ins>C</ins>
+                 * <ins>A</del>X<ins>C</ins><del>D</del>
+                 * <ins>A</ins><del>B</del>X<del>C</del>
+                 */
+                if ( lastequality && ( ( preIns && preDel && postIns && postDel ) ||
+                        ( ( lastequality.length < this.DiffEditCost / 2 ) &&
+                            ( preIns + preDel + postIns + postDel ) === 3 ) ) ) {
+                    // Duplicate record.
+                    diffs.splice( equalities[equalitiesLength - 1], 0, [ DIFF_DELETE, lastequality ] );
+                    // Change second copy to insert.
+                    diffs[ equalities[ equalitiesLength - 1 ] + 1 ][ 0 ] = DIFF_INSERT;
+                    equalitiesLength--; // Throw away the equality we just deleted;
+                    lastequality = null;
+                    if (preIns && preDel) {
+                        // No changes made which could affect previous entry, keep going.
+                        postIns = postDel = true;
+                        equalitiesLength = 0;
+                    } else {
+                        equalitiesLength--; // Throw away the previous equality.
+                        pointer = equalitiesLength > 0 ? equalities[ equalitiesLength - 1 ] : -1;
+                        postIns = postDel = false;
+                    }
+                    changes = true;
+                }
+            }
+            pointer++;
+        }
+
+        if ( changes ) {
+            this.diffCleanupMerge( diffs );
+        }
+    };
+
+    /**
+     * Convert a diff array into a pretty HTML report.
+     * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+     * @param {integer} string to be beautified.
+     * @return {string} HTML representation.
+     */
+    DiffMatchPatch.prototype.diffPrettyHtml = function( diffs ) {
+        var op, data, x, html = [];
+        for ( x = 0; x < diffs.length; x++ ) {
+            op = diffs[x][0]; // Operation (insert, delete, equal)
+            data = diffs[x][1]; // Text of change.
+            switch ( op ) {
+                case DIFF_INSERT:
+                    html[x] = "<ins>" + data + "</ins>";
+                    break;
+                case DIFF_DELETE:
+                    html[x] = "<del>" + data + "</del>";
+                    break;
+                case DIFF_EQUAL:
+                    html[x] = "<span>" + data + "</span>";
+                    break;
+            }
+        }
+        return html.join("");
+    };
+
+    /**
+     * Determine the common prefix of two strings.
+     * @param {string} text1 First string.
+     * @param {string} text2 Second string.
+     * @return {number} The number of characters common to the start of each
+     *     string.
+     */
+    DiffMatchPatch.prototype.diffCommonPrefix = function( text1, text2 ) {
+        var pointermid, pointermax, pointermin, pointerstart;
+        // Quick check for common null cases.
+        if ( !text1 || !text2 || text1.charAt(0) !== text2.charAt(0) ) {
+            return 0;
+        }
+        // Binary search.
+        // Performance analysis: http://neil.fraser.name/news/2007/10/09/
+        pointermin = 0;
+        pointermax = Math.min( text1.length, text2.length );
+        pointermid = pointermax;
+        pointerstart = 0;
+        while ( pointermin < pointermid ) {
+            if ( text1.substring( pointerstart, pointermid ) === text2.substring( pointerstart, pointermid ) ) {
+                pointermin = pointermid;
+                pointerstart = pointermin;
+            } else {
+                pointermax = pointermid;
+            }
+            pointermid = Math.floor( ( pointermax - pointermin ) / 2 + pointermin );
+        }
+        return pointermid;
+    };
+
+    /**
+     * Determine the common suffix of two strings.
+     * @param {string} text1 First string.
+     * @param {string} text2 Second string.
+     * @return {number} The number of characters common to the end of each string.
+     */
+    DiffMatchPatch.prototype.diffCommonSuffix = function( text1, text2 ) {
+        var pointermid, pointermax, pointermin, pointerend;
+        // Quick check for common null cases.
+        if (!text1 || !text2 || text1.charAt(text1.length - 1) !== text2.charAt(text2.length - 1)) {
+            return 0;
+        }
+        // Binary search.
+        // Performance analysis: http://neil.fraser.name/news/2007/10/09/
+        pointermin = 0;
+        pointermax = Math.min(text1.length, text2.length);
+        pointermid = pointermax;
+        pointerend = 0;
+        while ( pointermin < pointermid ) {
+            if (text1.substring( text1.length - pointermid, text1.length - pointerend ) ===
+                text2.substring( text2.length - pointermid, text2.length - pointerend ) ) {
+                pointermin = pointermid;
+                pointerend = pointermin;
+            } else {
+                pointermax = pointermid;
+            }
+            pointermid = Math.floor( ( pointermax - pointermin ) / 2 + pointermin );
+        }
+        return pointermid;
+    };
+
+    /**
+     * Find the differences between two texts.  Assumes that the texts do not
+     * have any common prefix or suffix.
+     * @param {string} text1 Old string to be diffed.
+     * @param {string} text2 New string to be diffed.
+     * @param {boolean} checklines Speedup flag.  If false, then don't run a
+     *     line-level diff first to identify the changed areas.
+     *     If true, then run a faster, slightly less optimal diff.
+     * @param {number} deadline Time when the diff should be complete by.
+     * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+     * @private
+     */
+    DiffMatchPatch.prototype.diffCompute = function( text1, text2, checklines, deadline ) {
+        var diffs, longtext, shorttext, i, hm,
+                       text1A, text2A, text1B, text2B,
+                       midCommon, diffsA, diffsB;
+
+        if ( !text1 ) {
+            // Just add some text (speedup).
+            return [
+                [ DIFF_INSERT, text2 ]
+            ];
+        }
+
+        if (!text2) {
+            // Just delete some text (speedup).
+            return [
+                [ DIFF_DELETE, text1 ]
+            ];
+        }
+
+        longtext = text1.length > text2.length ? text1 : text2;
+        shorttext = text1.length > text2.length ? text2 : text1;
+        i = longtext.indexOf( shorttext );
+        if ( i !== -1 ) {
+            // Shorter text is inside the longer text (speedup).
+            diffs = [
+                [ DIFF_INSERT, longtext.substring( 0, i ) ],
+                [ DIFF_EQUAL, shorttext ],
+                [ DIFF_INSERT, longtext.substring( i + shorttext.length ) ]
+            ];
+            // Swap insertions for deletions if diff is reversed.
+            if ( text1.length > text2.length ) {
+                diffs[0][0] = diffs[2][0] = DIFF_DELETE;
+            }
+            return diffs;
+        }
+
+        if ( shorttext.length === 1 ) {
+            // Single character string.
+            // After the previous speedup, the character can't be an equality.
+            return [
+                [ DIFF_DELETE, text1 ],
+                [ DIFF_INSERT, text2 ]
+            ];
+        }
+
+        // Check to see if the problem can be split in two.
+        hm = this.diffHalfMatch(text1, text2);
+        if (hm) {
+            // A half-match was found, sort out the return data.
+            text1A = hm[0];
+            text1B = hm[1];
+            text2A = hm[2];
+            text2B = hm[3];
+            midCommon = hm[4];
+            // Send both pairs off for separate processing.
+            diffsA = this.DiffMain(text1A, text2A, checklines, deadline);
+            diffsB = this.DiffMain(text1B, text2B, checklines, deadline);
+            // Merge the results.
+            return diffsA.concat([
+                [ DIFF_EQUAL, midCommon ]
+            ], diffsB);
+        }
+
+        if (checklines && text1.length > 100 && text2.length > 100) {
+            return this.diffLineMode(text1, text2, deadline);
+        }
+
+        return this.diffBisect(text1, text2, deadline);
+    };
+
+    /**
+     * Do the two texts share a substring which is at least half the length of the
+     * longer text?
+     * This speedup can produce non-minimal diffs.
+     * @param {string} text1 First string.
+     * @param {string} text2 Second string.
+     * @return {Array.<string>} Five element Array, containing the prefix of
+     *     text1, the suffix of text1, the prefix of text2, the suffix of
+     *     text2 and the common middle.  Or null if there was no match.
+     * @private
+     */
+    DiffMatchPatch.prototype.diffHalfMatch = function(text1, text2) {
+        var longtext, shorttext, dmp,
+                       text1A, text2B, text2A, text1B, midCommon,
+                       hm1, hm2, hm;
+        if (this.DiffTimeout <= 0) {
+            // Don't risk returning a non-optimal diff if we have unlimited time.
+            return null;
+        }
+        longtext = text1.length > text2.length ? text1 : text2;
+        shorttext = text1.length > text2.length ? text2 : text1;
+        if (longtext.length < 4 || shorttext.length * 2 < longtext.length) {
+            return null; // Pointless.
+        }
+        dmp = this; // 'this' becomes 'window' in a closure.
+
+        /**
+         * Does a substring of shorttext exist within longtext such that the substring
+         * is at least half the length of longtext?
+         * Closure, but does not reference any external variables.
+         * @param {string} longtext Longer string.
+         * @param {string} shorttext Shorter string.
+         * @param {number} i Start index of quarter length substring within longtext.
+         * @return {Array.<string>} Five element Array, containing the prefix of
+         *     longtext, the suffix of longtext, the prefix of shorttext, the suffix
+         *     of shorttext and the common middle.  Or null if there was no match.
+         * @private
+         */
+        function diffHalfMatchI(longtext, shorttext, i) {
+            var seed, j, bestCommon, prefixLength, suffixLength,
+                               bestLongtextA, bestLongtextB, bestShorttextA, bestShorttextB;
+            // Start with a 1/4 length substring at position i as a seed.
+            seed = longtext.substring(i, i + Math.floor(longtext.length / 4));
+            j = -1;
+            bestCommon = "";
+            while ((j = shorttext.indexOf(seed, j + 1)) !== -1) {
+                prefixLength = dmp.diffCommonPrefix(longtext.substring(i),
+                    shorttext.substring(j));
+                suffixLength = dmp.diffCommonSuffix(longtext.substring(0, i),
+                    shorttext.substring(0, j));
+                if (bestCommon.length < suffixLength + prefixLength) {
+                    bestCommon = shorttext.substring(j - suffixLength, j) +
+                        shorttext.substring(j, j + prefixLength);
+                    bestLongtextA = longtext.substring(0, i - suffixLength);
+                    bestLongtextB = longtext.substring(i + prefixLength);
+                    bestShorttextA = shorttext.substring(0, j - suffixLength);
+                    bestShorttextB = shorttext.substring(j + prefixLength);
+                }
+            }
+            if (bestCommon.length * 2 >= longtext.length) {
+                return [ bestLongtextA, bestLongtextB,
+                    bestShorttextA, bestShorttextB, bestCommon
+                ];
+            } else {
+                return null;
+            }
+        }
+
+        // First check if the second quarter is the seed for a half-match.
+        hm1 = diffHalfMatchI(longtext, shorttext,
+            Math.ceil(longtext.length / 4));
+        // Check again based on the third quarter.
+        hm2 = diffHalfMatchI(longtext, shorttext,
+            Math.ceil(longtext.length / 2));
+        if (!hm1 && !hm2) {
+            return null;
+        } else if (!hm2) {
+            hm = hm1;
+        } else if (!hm1) {
+            hm = hm2;
+        } else {
+            // Both matched.  Select the longest.
+            hm = hm1[4].length > hm2[4].length ? hm1 : hm2;
+        }
+
+        // A half-match was found, sort out the return data.
+        text1A, text1B, text2A, text2B;
+        if (text1.length > text2.length) {
+            text1A = hm[0];
+            text1B = hm[1];
+            text2A = hm[2];
+            text2B = hm[3];
+        } else {
+            text2A = hm[0];
+            text2B = hm[1];
+            text1A = hm[2];
+            text1B = hm[3];
+        }
+        midCommon = hm[4];
+        return [ text1A, text1B, text2A, text2B, midCommon ];
+    };
+
+    /**
+     * Do a quick line-level diff on both strings, then rediff the parts for
+     * greater accuracy.
+     * This speedup can produce non-minimal diffs.
+     * @param {string} text1 Old string to be diffed.
+     * @param {string} text2 New string to be diffed.
+     * @param {number} deadline Time when the diff should be complete by.
+     * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+     * @private
+     */
+    DiffMatchPatch.prototype.diffLineMode = function(text1, text2, deadline) {
+        var a, diffs, linearray, pointer, countInsert,
+                       countDelete, textInsert, textDelete, j;
+        // Scan the text on a line-by-line basis first.
+        a = this.diffLinesToChars(text1, text2);
+        text1 = a.chars1;
+        text2 = a.chars2;
+        linearray = a.lineArray;
+
+        diffs = this.DiffMain(text1, text2, false, deadline);
+
+        // Convert the diff back to original text.
+        this.diffCharsToLines(diffs, linearray);
+        // Eliminate freak matches (e.g. blank lines)
+        this.diffCleanupSemantic(diffs);
+
+        // Rediff any replacement blocks, this time character-by-character.
+        // Add a dummy entry at the end.
+        diffs.push( [ DIFF_EQUAL, "" ] );
+        pointer = 0;
+        countDelete = 0;
+        countInsert = 0;
+        textDelete = "";
+        textInsert = "";
+        while (pointer < diffs.length) {
+            switch ( diffs[pointer][0] ) {
+                case DIFF_INSERT:
+                    countInsert++;
+                    textInsert += diffs[pointer][1];
+                    break;
+                case DIFF_DELETE:
+                    countDelete++;
+                    textDelete += diffs[pointer][1];
+                    break;
+                case DIFF_EQUAL:
+                    // Upon reaching an equality, check for prior redundancies.
+                    if (countDelete >= 1 && countInsert >= 1) {
+                        // Delete the offending records and add the merged ones.
+                        diffs.splice(pointer - countDelete - countInsert,
+                            countDelete + countInsert);
+                        pointer = pointer - countDelete - countInsert;
+                        a = this.DiffMain(textDelete, textInsert, false, deadline);
+                        for (j = a.length - 1; j >= 0; j--) {
+                            diffs.splice( pointer, 0, a[j] );
+                        }
+                        pointer = pointer + a.length;
+                    }
+                    countInsert = 0;
+                    countDelete = 0;
+                    textDelete = "";
+                    textInsert = "";
+                    break;
+            }
+            pointer++;
+        }
+        diffs.pop(); // Remove the dummy entry at the end.
+
+        return diffs;
+    };
+
+    /**
+     * Find the 'middle snake' of a diff, split the problem in two
+     * and return the recursively constructed diff.
+     * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations.
+     * @param {string} text1 Old string to be diffed.
+     * @param {string} text2 New string to be diffed.
+     * @param {number} deadline Time at which to bail if not yet complete.
+     * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+     * @private
+     */
+    DiffMatchPatch.prototype.diffBisect = function(text1, text2, deadline) {
+        var text1Length, text2Length, maxD, vOffset, vLength,
+                       v1, v2, x, delta, front, k1start, k1end, k2start,
+                       k2end, k2Offset, k1Offset, x1, x2, y1, y2, d, k1, k2;
+        // Cache the text lengths to prevent multiple calls.
+        text1Length = text1.length;
+        text2Length = text2.length;
+        maxD = Math.ceil((text1Length + text2Length) / 2);
+        vOffset = maxD;
+        vLength = 2 * maxD;
+        v1 = new Array(vLength);
+        v2 = new Array(vLength);
+        // Setting all elements to -1 is faster in Chrome & Firefox than mixing
+        // integers and undefined.
+        for (x = 0; x < vLength; x++) {
+            v1[x] = -1;
+            v2[x] = -1;
+        }
+        v1[vOffset + 1] = 0;
+        v2[vOffset + 1] = 0;
+        delta = text1Length - text2Length;
+        // If the total number of characters is odd, then the front path will collide
+        // with the reverse path.
+        front = (delta % 2 !== 0);
+        // Offsets for start and end of k loop.
+        // Prevents mapping of space beyond the grid.
+        k1start = 0;
+        k1end = 0;
+        k2start = 0;
+        k2end = 0;
+        for (d = 0; d < maxD; d++) {
+            // Bail out if deadline is reached.
+            if ((new Date()).getTime() > deadline) {
+                break;
+            }
+
+            // Walk the front path one step.
+            for (k1 = -d + k1start; k1 <= d - k1end; k1 += 2) {
+                k1Offset = vOffset + k1;
+                if ( k1 === -d || ( k1 !== d && v1[ k1Offset - 1 ] < v1[ k1Offset + 1 ] ) ) {
+                    x1 = v1[k1Offset + 1];
+                } else {
+                    x1 = v1[k1Offset - 1] + 1;
+                }
+                y1 = x1 - k1;
+                while (x1 < text1Length && y1 < text2Length &&
+                    text1.charAt(x1) === text2.charAt(y1)) {
+                    x1++;
+                    y1++;
+                }
+                v1[k1Offset] = x1;
+                if (x1 > text1Length) {
+                    // Ran off the right of the graph.
+                    k1end += 2;
+                } else if (y1 > text2Length) {
+                    // Ran off the bottom of the graph.
+                    k1start += 2;
+                } else if (front) {
+                    k2Offset = vOffset + delta - k1;
+                    if (k2Offset >= 0 && k2Offset < vLength && v2[k2Offset] !== -1) {
+                        // Mirror x2 onto top-left coordinate system.
+                        x2 = text1Length - v2[k2Offset];
+                        if (x1 >= x2) {
+                            // Overlap detected.
+                            return this.diffBisectSplit(text1, text2, x1, y1, deadline);
+                        }
+                    }
+                }
+            }
+
+            // Walk the reverse path one step.
+            for (k2 = -d + k2start; k2 <= d - k2end; k2 += 2) {
+                k2Offset = vOffset + k2;
+                if ( k2 === -d || (k2 !== d && v2[ k2Offset - 1 ] < v2[ k2Offset + 1 ] ) ) {
+                    x2 = v2[k2Offset + 1];
+                } else {
+                    x2 = v2[k2Offset - 1] + 1;
+                }
+                y2 = x2 - k2;
+                while (x2 < text1Length && y2 < text2Length &&
+                    text1.charAt(text1Length - x2 - 1) ===
+                    text2.charAt(text2Length - y2 - 1)) {
+                    x2++;
+                    y2++;
+                }
+                v2[k2Offset] = x2;
+                if (x2 > text1Length) {
+                    // Ran off the left of the graph.
+                    k2end += 2;
+                } else if (y2 > text2Length) {
+                    // Ran off the top of the graph.
+                    k2start += 2;
+                } else if (!front) {
+                    k1Offset = vOffset + delta - k2;
+                    if (k1Offset >= 0 && k1Offset < vLength && v1[k1Offset] !== -1) {
+                        x1 = v1[k1Offset];
+                        y1 = vOffset + x1 - k1Offset;
+                        // Mirror x2 onto top-left coordinate system.
+                        x2 = text1Length - x2;
+                        if (x1 >= x2) {
+                            // Overlap detected.
+                            return this.diffBisectSplit(text1, text2, x1, y1, deadline);
+                        }
+                    }
+                }
+            }
+        }
+        // Diff took too long and hit the deadline or
+        // number of diffs equals number of characters, no commonality at all.
+        return [
+            [ DIFF_DELETE, text1 ],
+            [ DIFF_INSERT, text2 ]
+        ];
+    };
+
+    /**
+     * Given the location of the 'middle snake', split the diff in two parts
+     * and recurse.
+     * @param {string} text1 Old string to be diffed.
+     * @param {string} text2 New string to be diffed.
+     * @param {number} x Index of split point in text1.
+     * @param {number} y Index of split point in text2.
+     * @param {number} deadline Time at which to bail if not yet complete.
+     * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+     * @private
+     */
+    DiffMatchPatch.prototype.diffBisectSplit = function( text1, text2, x, y, deadline ) {
+        var text1a, text1b, text2a, text2b, diffs, diffsb;
+        text1a = text1.substring(0, x);
+        text2a = text2.substring(0, y);
+        text1b = text1.substring(x);
+        text2b = text2.substring(y);
+
+        // Compute both diffs serially.
+        diffs = this.DiffMain(text1a, text2a, false, deadline);
+        diffsb = this.DiffMain(text1b, text2b, false, deadline);
+
+        return diffs.concat(diffsb);
+    };
+
+    /**
+     * Reduce the number of edits by eliminating semantically trivial equalities.
+     * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+     */
+    DiffMatchPatch.prototype.diffCleanupSemantic = function(diffs) {
+        var changes, equalities, equalitiesLength, lastequality,
+                       pointer, lengthInsertions2, lengthDeletions2, lengthInsertions1,
+                       lengthDeletions1, deletion, insertion, overlapLength1, overlapLength2;
+        changes = false;
+        equalities = []; // Stack of indices where equalities are found.
+        equalitiesLength = 0; // Keeping our own length var is faster in JS.
+        /** @type {?string} */
+        lastequality = null;
+        // Always equal to diffs[equalities[equalitiesLength - 1]][1]
+        pointer = 0; // Index of current position.
+        // Number of characters that changed prior to the equality.
+        lengthInsertions1 = 0;
+        lengthDeletions1 = 0;
+        // Number of characters that changed after the equality.
+        lengthInsertions2 = 0;
+        lengthDeletions2 = 0;
+        while (pointer < diffs.length) {
+            if (diffs[pointer][0] === DIFF_EQUAL) { // Equality found.
+                equalities[equalitiesLength++] = pointer;
+                lengthInsertions1 = lengthInsertions2;
+                lengthDeletions1 = lengthDeletions2;
+                lengthInsertions2 = 0;
+                lengthDeletions2 = 0;
+                lastequality = diffs[pointer][1];
+            } else { // An insertion or deletion.
+                if (diffs[pointer][0] === DIFF_INSERT) {
+                    lengthInsertions2 += diffs[pointer][1].length;
+                } else {
+                    lengthDeletions2 += diffs[pointer][1].length;
+                }
+                // Eliminate an equality that is smaller or equal to the edits on both
+                // sides of it.
+                if (lastequality && (lastequality.length <=
+                        Math.max(lengthInsertions1, lengthDeletions1)) &&
+                    (lastequality.length <= Math.max(lengthInsertions2,
+                        lengthDeletions2))) {
+                    // Duplicate record.
+                    diffs.splice( equalities[ equalitiesLength - 1 ], 0, [ DIFF_DELETE, lastequality ] );
+                    // Change second copy to insert.
+                    diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;
+                    // Throw away the equality we just deleted.
+                    equalitiesLength--;
+                    // Throw away the previous equality (it needs to be reevaluated).
+                    equalitiesLength--;
+                    pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1;
+                    lengthInsertions1 = 0; // Reset the counters.
+                    lengthDeletions1 = 0;
+                    lengthInsertions2 = 0;
+                    lengthDeletions2 = 0;
+                    lastequality = null;
+                    changes = true;
+                }
+            }
+            pointer++;
+        }
+
+        // Normalize the diff.
+        if (changes) {
+            this.diffCleanupMerge(diffs);
+        }
+
+        // Find any overlaps between deletions and insertions.
+        // e.g: <del>abcxxx</del><ins>xxxdef</ins>
+        //   -> <del>abc</del>xxx<ins>def</ins>
+        // e.g: <del>xxxabc</del><ins>defxxx</ins>
+        //   -> <ins>def</ins>xxx<del>abc</del>
+        // Only extract an overlap if it is as big as the edit ahead or behind it.
+        pointer = 1;
+        while (pointer < diffs.length) {
+            if (diffs[pointer - 1][0] === DIFF_DELETE &&
+                diffs[pointer][0] === DIFF_INSERT) {
+                deletion = diffs[pointer - 1][1];
+                insertion = diffs[pointer][1];
+                overlapLength1 = this.diffCommonOverlap(deletion, insertion);
+                overlapLength2 = this.diffCommonOverlap(insertion, deletion);
+                if (overlapLength1 >= overlapLength2) {
+                    if (overlapLength1 >= deletion.length / 2 ||
+                        overlapLength1 >= insertion.length / 2) {
+                        // Overlap found.  Insert an equality and trim the surrounding edits.
+                        diffs.splice( pointer, 0, [ DIFF_EQUAL, insertion.substring( 0, overlapLength1 ) ] );
+                        diffs[pointer - 1][1] =
+                            deletion.substring(0, deletion.length - overlapLength1);
+                        diffs[pointer + 1][1] = insertion.substring(overlapLength1);
+                        pointer++;
+                    }
+                } else {
+                    if (overlapLength2 >= deletion.length / 2 ||
+                        overlapLength2 >= insertion.length / 2) {
+                        // Reverse overlap found.
+                        // Insert an equality and swap and trim the surrounding edits.
+                        diffs.splice( pointer, 0, [ DIFF_EQUAL, deletion.substring( 0, overlapLength2 ) ] );
+                        diffs[pointer - 1][0] = DIFF_INSERT;
+                        diffs[pointer - 1][1] =
+                            insertion.substring(0, insertion.length - overlapLength2);
+                        diffs[pointer + 1][0] = DIFF_DELETE;
+                        diffs[pointer + 1][1] =
+                            deletion.substring(overlapLength2);
+                        pointer++;
+                    }
+                }
+                pointer++;
+            }
+            pointer++;
+        }
+    };
+
+    /**
+     * Determine if the suffix of one string is the prefix of another.
+     * @param {string} text1 First string.
+     * @param {string} text2 Second string.
+     * @return {number} The number of characters common to the end of the first
+     *     string and the start of the second string.
+     * @private
+     */
+    DiffMatchPatch.prototype.diffCommonOverlap = function(text1, text2) {
+        var text1Length, text2Length, textLength,
+                       best, length, pattern, found;
+        // Cache the text lengths to prevent multiple calls.
+        text1Length = text1.length;
+        text2Length = text2.length;
+        // Eliminate the null case.
+        if (text1Length === 0 || text2Length === 0) {
+            return 0;
+        }
+        // Truncate the longer string.
+        if (text1Length > text2Length) {
+            text1 = text1.substring(text1Length - text2Length);
+        } else if (text1Length < text2Length) {
+            text2 = text2.substring(0, text1Length);
+        }
+        textLength = Math.min(text1Length, text2Length);
+        // Quick check for the worst case.
+        if (text1 === text2) {
+            return textLength;
+        }
+
+        // Start by looking for a single character match
+        // and increase length until no match is found.
+        // Performance analysis: http://neil.fraser.name/news/2010/11/04/
+        best = 0;
+        length = 1;
+        while (true) {
+            pattern = text1.substring(textLength - length);
+            found = text2.indexOf(pattern);
+            if (found === -1) {
+                return best;
+            }
+            length += found;
+            if (found === 0 || text1.substring(textLength - length) ===
+                text2.substring(0, length)) {
+                best = length;
+                length++;
+            }
+        }
+    };
+
+    /**
+     * Split two texts into an array of strings.  Reduce the texts to a string of
+     * hashes where each Unicode character represents one line.
+     * @param {string} text1 First string.
+     * @param {string} text2 Second string.
+     * @return {{chars1: string, chars2: string, lineArray: !Array.<string>}}
+     *     An object containing the encoded text1, the encoded text2 and
+     *     the array of unique strings.
+     *     The zeroth element of the array of unique strings is intentionally blank.
+     * @private
+     */
+    DiffMatchPatch.prototype.diffLinesToChars = function(text1, text2) {
+        var lineArray, lineHash, chars1, chars2;
+        lineArray = []; // e.g. lineArray[4] === 'Hello\n'
+        lineHash = {}; // e.g. lineHash['Hello\n'] === 4
+
+        // '\x00' is a valid character, but various debuggers don't like it.
+        // So we'll insert a junk entry to avoid generating a null character.
+        lineArray[0] = "";
+
+        /**
+         * Split a text into an array of strings.  Reduce the texts to a string of
+         * hashes where each Unicode character represents one line.
+         * Modifies linearray and linehash through being a closure.
+         * @param {string} text String to encode.
+         * @return {string} Encoded string.
+         * @private
+         */
+        function diffLinesToCharsMunge(text) {
+            var chars, lineStart, lineEnd, lineArrayLength, line;
+            chars = "";
+            // Walk the text, pulling out a substring for each line.
+            // text.split('\n') would would temporarily double our memory footprint.
+            // Modifying text would create many large strings to garbage collect.
+            lineStart = 0;
+            lineEnd = -1;
+            // Keeping our own length variable is faster than looking it up.
+            lineArrayLength = lineArray.length;
+            while (lineEnd < text.length - 1) {
+                lineEnd = text.indexOf("\n", lineStart);
+                if (lineEnd === -1) {
+                    lineEnd = text.length - 1;
+                }
+                line = text.substring(lineStart, lineEnd + 1);
+                lineStart = lineEnd + 1;
+
+                if (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) :
+                    (lineHash[line] !== undefined)) {
+                    chars += String.fromCharCode( lineHash[ line ] );
+                } else {
+                    chars += String.fromCharCode(lineArrayLength);
+                    lineHash[line] = lineArrayLength;
+                    lineArray[lineArrayLength++] = line;
+                }
+            }
+            return chars;
+        }
+
+        chars1 = diffLinesToCharsMunge(text1);
+        chars2 = diffLinesToCharsMunge(text2);
+        return {
+            chars1: chars1,
+            chars2: chars2,
+            lineArray: lineArray
+        };
+    };
+
+    /**
+     * Rehydrate the text in a diff from a string of line hashes to real lines of
+     * text.
+     * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+     * @param {!Array.<string>} lineArray Array of unique strings.
+     * @private
+     */
+    DiffMatchPatch.prototype.diffCharsToLines = function( diffs, lineArray ) {
+        var x, chars, text, y;
+        for ( x = 0; x < diffs.length; x++ ) {
+            chars = diffs[x][1];
+            text = [];
+            for ( y = 0; y < chars.length; y++ ) {
+                text[y] = lineArray[chars.charCodeAt(y)];
+            }
+            diffs[x][1] = text.join("");
+        }
+    };
+
+    /**
+     * Reorder and merge like edit sections.  Merge equalities.
+     * Any edit section can move as long as it doesn't cross an equality.
+     * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+     */
+    DiffMatchPatch.prototype.diffCleanupMerge = function(diffs) {
+        var pointer, countDelete, countInsert, textInsert, textDelete,
+                       commonlength, changes;
+        diffs.push( [ DIFF_EQUAL, "" ] ); // Add a dummy entry at the end.
+        pointer = 0;
+        countDelete = 0;
+        countInsert = 0;
+        textDelete = "";
+        textInsert = "";
+        commonlength;
+        while (pointer < diffs.length) {
+            switch ( diffs[ pointer ][ 0 ] ) {
+                case DIFF_INSERT:
+                    countInsert++;
+                    textInsert += diffs[pointer][1];
+                    pointer++;
+                    break;
+                case DIFF_DELETE:
+                    countDelete++;
+                    textDelete += diffs[pointer][1];
+                    pointer++;
+                    break;
+                case DIFF_EQUAL:
+                    // Upon reaching an equality, check for prior redundancies.
+                    if (countDelete + countInsert > 1) {
+                        if (countDelete !== 0 && countInsert !== 0) {
+                            // Factor out any common prefixies.
+                            commonlength = this.diffCommonPrefix(textInsert, textDelete);
+                            if (commonlength !== 0) {
+                                if ((pointer - countDelete - countInsert) > 0 &&
+                                    diffs[pointer - countDelete - countInsert - 1][0] ===
+                                    DIFF_EQUAL) {
+                                    diffs[pointer - countDelete - countInsert - 1][1] +=
+                                        textInsert.substring(0, commonlength);
+                                } else {
+                                    diffs.splice( 0, 0, [ DIFF_EQUAL,
+                                        textInsert.substring( 0, commonlength )
+                                     ] );
+                                    pointer++;
+                                }
+                                textInsert = textInsert.substring(commonlength);
+                                textDelete = textDelete.substring(commonlength);
+                            }
+                            // Factor out any common suffixies.
+                            commonlength = this.diffCommonSuffix(textInsert, textDelete);
+                            if (commonlength !== 0) {
+                                diffs[pointer][1] = textInsert.substring(textInsert.length -
+                                    commonlength) + diffs[pointer][1];
+                                textInsert = textInsert.substring(0, textInsert.length -
+                                    commonlength);
+                                textDelete = textDelete.substring(0, textDelete.length -
+                                    commonlength);
+                            }
+                        }
+                        // Delete the offending records and add the merged ones.
+                        if (countDelete === 0) {
+                            diffs.splice( pointer - countInsert,
+                                countDelete + countInsert, [ DIFF_INSERT, textInsert ] );
+                        } else if (countInsert === 0) {
+                            diffs.splice( pointer - countDelete,
+                                countDelete + countInsert, [ DIFF_DELETE, textDelete ] );
+                        } else {
+                            diffs.splice( pointer - countDelete - countInsert,
+                                countDelete + countInsert, [ DIFF_DELETE, textDelete ], [ DIFF_INSERT, textInsert ] );
+                        }
+                        pointer = pointer - countDelete - countInsert +
+                            (countDelete ? 1 : 0) + (countInsert ? 1 : 0) + 1;
+                    } else if (pointer !== 0 && diffs[pointer - 1][0] === DIFF_EQUAL) {
+                        // Merge this equality with the previous one.
+                        diffs[pointer - 1][1] += diffs[pointer][1];
+                        diffs.splice(pointer, 1);
+                    } else {
+                        pointer++;
+                    }
+                    countInsert = 0;
+                    countDelete = 0;
+                    textDelete = "";
+                    textInsert = "";
+                    break;
+            }
+        }
+        if (diffs[diffs.length - 1][1] === "") {
+            diffs.pop(); // Remove the dummy entry at the end.
+        }
+
+        // Second pass: look for single edits surrounded on both sides by equalities
+        // which can be shifted sideways to eliminate an equality.
+        // e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC
+        changes = false;
+        pointer = 1;
+        // Intentionally ignore the first and last element (don't need checking).
+        while (pointer < diffs.length - 1) {
+            if (diffs[pointer - 1][0] === DIFF_EQUAL &&
+                diffs[pointer + 1][0] === DIFF_EQUAL) {
+                // This is a single edit surrounded by equalities.
+                if ( diffs[ pointer ][ 1 ].substring( diffs[ pointer ][ 1 ].length -
+                        diffs[ pointer - 1 ][ 1 ].length ) === diffs[ pointer - 1 ][ 1 ] ) {
+                    // Shift the edit over the previous equality.
+                    diffs[pointer][1] = diffs[pointer - 1][1] +
+                        diffs[pointer][1].substring(0, diffs[pointer][1].length -
+                            diffs[pointer - 1][1].length);
+                    diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1];
+                    diffs.splice(pointer - 1, 1);
+                    changes = true;
+                } else if ( diffs[ pointer ][ 1 ].substring( 0, diffs[ pointer + 1 ][ 1 ].length ) ===
+                    diffs[ pointer + 1 ][ 1 ] ) {
+                    // Shift the edit over the next equality.
+                    diffs[pointer - 1][1] += diffs[pointer + 1][1];
+                    diffs[pointer][1] =
+                        diffs[pointer][1].substring(diffs[pointer + 1][1].length) +
+                        diffs[pointer + 1][1];
+                    diffs.splice(pointer + 1, 1);
+                    changes = true;
+                }
+            }
+            pointer++;
+        }
+        // If shifts were made, the diff needs reordering and another shift sweep.
+        if (changes) {
+            this.diffCleanupMerge(diffs);
+        }
+    };
+
+    return function(o, n) {
+               var diff, output, text;
+        diff = new DiffMatchPatch();
+        output = diff.DiffMain(o, n);
+        //console.log(output);
+        diff.diffCleanupEfficiency(output);
+        text = diff.diffPrettyHtml(output);
+
+        return text;
+    };
+}());
+// jscs:enable
+
+(function() {
+
+// Deprecated QUnit.init - Ref #530
+// Re-initialize the configuration options
+QUnit.init = function() {
+       var tests, banner, result, qunit,
+               config = QUnit.config;
+
+       config.stats = { all: 0, bad: 0 };
+       config.moduleStats = { all: 0, bad: 0 };
+       config.started = 0;
+       config.updateRate = 1000;
+       config.blocking = false;
+       config.autostart = true;
+       config.autorun = false;
+       config.filter = "";
+       config.queue = [];
+
+       // Return on non-browser environments
+       // This is necessary to not break on node tests
+       if ( typeof window === "undefined" ) {
+               return;
+       }
+
+       qunit = id( "qunit" );
+       if ( qunit ) {
+               qunit.innerHTML =
+                       "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
+                       "<h2 id='qunit-banner'></h2>" +
+                       "<div id='qunit-testrunner-toolbar'></div>" +
+                       "<h2 id='qunit-userAgent'></h2>" +
+                       "<ol id='qunit-tests'></ol>";
+       }
+
+       tests = id( "qunit-tests" );
+       banner = id( "qunit-banner" );
+       result = id( "qunit-testresult" );
+
+       if ( tests ) {
+               tests.innerHTML = "";
+       }
+
+       if ( banner ) {
+               banner.className = "";
+       }
+
+       if ( result ) {
+               result.parentNode.removeChild( result );
+       }
+
+       if ( tests ) {
+               result = document.createElement( "p" );
+               result.id = "qunit-testresult";
+               result.className = "result";
+               tests.parentNode.insertBefore( result, tests );
+               result.innerHTML = "Running...<br />&#160;";
+       }
+};
+
+// Don't load the HTML Reporter on non-Browser environments
+if ( typeof window === "undefined" ) {
+       return;
+}
+
+var config = QUnit.config,
+       hasOwn = Object.prototype.hasOwnProperty,
+       defined = {
+               document: window.document !== undefined,
+               sessionStorage: (function() {
+                       var x = "qunit-test-string";
+                       try {
+                               sessionStorage.setItem( x, x );
+                               sessionStorage.removeItem( x );
+                               return true;
+                       } catch ( e ) {
+                               return false;
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        ns[ n[i] ].rows.push( i );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         }())
+       },
+       modulesList = [];
+
+/**
+* Escape text for attribute or text content.
+*/
+function escapeText( s ) {
+       if ( !s ) {
+               return "";
+       }
+       s = s + "";
+
+       // Both single quotes and double quotes (for attributes)
+       return s.replace( /['"<>&]/g, function( s ) {
+               switch ( s ) {
+               case "'":
+                       return "&#039;";
+               case "\"":
+                       return "&quot;";
+               case "<":
+                       return "&lt;";
+               case ">":
+                       return "&gt;";
+               case "&":
+                       return "&amp;";
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        });
+}
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                for ( i = 0; i < o.length; i++ ) {
-                       if ( !hasOwn.call( os, o[i] ) ) {
-                               os[ o[i] ] = {
-                                       rows: [],
-                                       n: null
-                               };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * @param {HTMLElement} elem
+ * @param {string} type
+ * @param {Function} fn
+ */
+function addEvent( elem, type, fn ) {
+       if ( elem.addEventListener ) {
+
+               // Standards-based browsers
+               elem.addEventListener( type, fn, false );
+       } else if ( elem.attachEvent ) {
+
+               // support: IE <9
+               elem.attachEvent( "on" + type, function() {
+                       var event = window.event;
+                       if ( !event.target ) {
+                               event.target = event.srcElement || document;
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        os[ o[i] ].rows.push( i );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+                       fn.call( elem, event );
+               });
+       }
+}
+
+/**
+ * @param {Array|NodeList} elems
+ * @param {string} type
+ * @param {Function} fn
+ */
+function addEvents( elems, type, fn ) {
+       var i = elems.length;
+       while ( i-- ) {
+               addEvent( elems[ i ], type, fn );
+       }
+}
+
+function hasClass( elem, name ) {
+       return ( " " + elem.className + " " ).indexOf( " " + name + " " ) >= 0;
+}
+
+function addClass( elem, name ) {
+       if ( !hasClass( elem, name ) ) {
+               elem.className += ( elem.className ? " " : "" ) + name;
+       }
+}
+
+function toggleClass( elem, name ) {
+       if ( hasClass( elem, name ) ) {
+               removeClass( elem, name );
+       } else {
+               addClass( elem, name );
+       }
+}
+
+function removeClass( elem, name ) {
+       var set = " " + elem.className + " ";
+
+       // Class name may appear multiple times
+       while ( set.indexOf( " " + name + " " ) >= 0 ) {
+               set = set.replace( " " + name + " ", " " );
+       }
+
+       // trim for prettiness
+       elem.className = typeof set.trim === "function" ? set.trim() : set.replace( /^\s+|\s+$/g, "" );
+}
+
+function id( name ) {
+       return defined.document && document.getElementById && document.getElementById( name );
+}
+
+function getUrlConfigHtml() {
+       var i, j, val,
+               escaped, escapedTooltip,
+               selection = false,
+               len = config.urlConfig.length,
+               urlConfigHtml = "";
+
+       for ( i = 0; i < len; i++ ) {
+               val = config.urlConfig[ i ];
+               if ( typeof val === "string" ) {
+                       val = {
+                               id: val,
+                               label: val
+                       };
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                for ( i in ns ) {
-                       if ( hasOwn.call( ns, i ) ) {
-                               if ( ns[i].rows.length === 1 && hasOwn.call( os, i ) && os[i].rows.length === 1 ) {
-                                       n[ ns[i].rows[0] ] = {
-                                               text: n[ ns[i].rows[0] ],
-                                               row: os[i].rows[0]
-                                       };
-                                       o[ os[i].rows[0] ] = {
-                                               text: o[ os[i].rows[0] ],
-                                               row: ns[i].rows[0]
-                                       };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         escaped = escapeText( val.id );
+               escapedTooltip = escapeText( val.tooltip );
+
+               if ( config[ val.id ] === undefined ) {
+                       config[ val.id ] = QUnit.urlParams[ val.id ];
+               }
+
+               if ( !val.value || typeof val.value === "string" ) {
+                       urlConfigHtml += "<input id='qunit-urlconfig-" + escaped +
+                               "' name='" + escaped + "' type='checkbox'" +
+                               ( val.value ? " value='" + escapeText( val.value ) + "'" : "" ) +
+                               ( config[ val.id ] ? " checked='checked'" : "" ) +
+                               " title='" + escapedTooltip + "' /><label for='qunit-urlconfig-" + escaped +
+                               "' title='" + escapedTooltip + "'>" + val.label + "</label>";
+               } else {
+                       urlConfigHtml += "<label for='qunit-urlconfig-" + escaped +
+                               "' title='" + escapedTooltip + "'>" + val.label +
+                               ": </label><select id='qunit-urlconfig-" + escaped +
+                               "' name='" + escaped + "' title='" + escapedTooltip + "'><option></option>";
+
+                       if ( QUnit.is( "array", val.value ) ) {
+                               for ( j = 0; j < val.value.length; j++ ) {
+                                       escaped = escapeText( val.value[ j ] );
+                                       urlConfigHtml += "<option value='" + escaped + "'" +
+                                               ( config[ val.id ] === val.value[ j ] ?
+                                                       ( selection = true ) && " selected='selected'" : "" ) +
+                                               ">" + escaped + "</option>";
</ins><span class="cx" style="display: block; padding: 0 10px">                                 }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        } else {
+                               for ( j in val.value ) {
+                                       if ( hasOwn.call( val.value, j ) ) {
+                                               urlConfigHtml += "<option value='" + escapeText( j ) + "'" +
+                                                       ( config[ val.id ] === j ?
+                                                               ( selection = true ) && " selected='selected'" : "" ) +
+                                                       ">" + escapeText( val.value[ j ] ) + "</option>";
+                                       }
+                               }
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        if ( config[ val.id ] && !selection ) {
+                               escaped = escapeText( config[ val.id ] );
+                               urlConfigHtml += "<option value='" + escaped +
+                                       "' selected='selected' disabled='disabled'>" + escaped + "</option>";
+                       }
+                       urlConfigHtml += "</select>";
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                for ( i = 0; i < n.length - 1; i++ ) {
-                       if ( n[i].text != null && n[ i + 1 ].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null &&
-                                               n[ i + 1 ] == o[ n[i].row + 1 ] ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ return urlConfigHtml;
+}
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                n[ i + 1 ] = {
-                                       text: n[ i + 1 ],
-                                       row: n[i].row + 1
-                               };
-                               o[ n[i].row + 1 ] = {
-                                       text: o[ n[i].row + 1 ],
-                                       row: i + 1
-                               };
-                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+// Handle "click" events on toolbar checkboxes and "change" for select menus.
+// Updates the URL with the new state of `config.urlConfig` values.
+function toolbarChanged() {
+       var updatedUrl, value,
+               field = this,
+               params = {};
+
+       // Detect if field is a select menu or a checkbox
+       if ( "selectedIndex" in field ) {
+               value = field.options[ field.selectedIndex ].value || undefined;
+       } else {
+               value = field.checked ? ( field.defaultValue || true ) : undefined;
+       }
+
+       params[ field.name ] = value;
+       updatedUrl = setUrl( params );
+
+       if ( "hidepassed" === field.name && "replaceState" in window.history ) {
+               config[ field.name ] = value || false;
+               if ( value ) {
+                       addClass( id( "qunit-tests" ), "hidepass" );
+               } else {
+                       removeClass( id( "qunit-tests" ), "hidepass" );
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                for ( i = n.length - 1; i > 0; i-- ) {
-                       if ( n[i].text != null && n[ i - 1 ].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null &&
-                                               n[ i - 1 ] == o[ n[i].row - 1 ]) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // It is not necessary to refresh the whole page
+               window.history.replaceState( null, "", updatedUrl );
+       } else {
+               window.location = updatedUrl;
+       }
+}
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                n[ i - 1 ] = {
-                                       text: n[ i - 1 ],
-                                       row: n[i].row - 1
-                               };
-                               o[ n[i].row - 1 ] = {
-                                       text: o[ n[i].row - 1 ],
-                                       row: i - 1
-                               };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function setUrl( params ) {
+       var key,
+               querystring = "?";
+
+       params = QUnit.extend( QUnit.extend( {}, QUnit.urlParams ), params );
+
+       for ( key in params ) {
+               if ( hasOwn.call( params, key ) ) {
+                       if ( params[ key ] === undefined ) {
+                               continue;
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        querystring += encodeURIComponent( key );
+                       if ( params[ key ] !== true ) {
+                               querystring += "=" + encodeURIComponent( params[ key ] );
+                       }
+                       querystring += "&";
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        }
+       return location.protocol + "//" + location.host +
+               location.pathname + querystring.slice( 0, -1 );
+}
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                return {
-                       o: o,
-                       n: n
-               };
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function applyUrlParams() {
+       var selectedModule,
+               modulesList = id( "qunit-modulefilter" ),
+               filter = id( "qunit-filter-input" ).value;
+
+       selectedModule = modulesList ?
+               decodeURIComponent( modulesList.options[ modulesList.selectedIndex ].value ) :
+               undefined;
+
+       window.location = setUrl({
+               module: ( selectedModule === "" ) ? undefined : selectedModule,
+               filter: ( filter === "" ) ? undefined : filter,
+
+               // Remove testId filter
+               testId: undefined
+       });
+}
+
+function toolbarUrlConfigContainer() {
+       var urlConfigContainer = document.createElement( "span" );
+
+       urlConfigContainer.innerHTML = getUrlConfigHtml();
+       addClass( urlConfigContainer, "qunit-url-config" );
+
+       // For oldIE support:
+       // * Add handlers to the individual elements instead of the container
+       // * Use "click" instead of "change" for checkboxes
+       addEvents( urlConfigContainer.getElementsByTagName( "input" ), "click", toolbarChanged );
+       addEvents( urlConfigContainer.getElementsByTagName( "select" ), "change", toolbarChanged );
+
+       return urlConfigContainer;
+}
+
+function toolbarLooseFilter() {
+       var filter = document.createElement( "form" ),
+               label = document.createElement( "label" ),
+               input = document.createElement( "input" ),
+               button = document.createElement( "button" );
+
+       addClass( filter, "qunit-filter" );
+
+       label.innerHTML = "Filter: ";
+
+       input.type = "text";
+       input.value = config.filter || "";
+       input.name = "filter";
+       input.id = "qunit-filter-input";
+
+       button.innerHTML = "Go";
+
+       label.appendChild( input );
+
+       filter.appendChild( label );
+       filter.appendChild( button );
+       addEvent( filter, "submit", function( ev ) {
+               applyUrlParams();
+
+               if ( ev && ev.preventDefault ) {
+                       ev.preventDefault();
+               }
+
+               return false;
+       });
+
+       return filter;
+}
+
+function toolbarModuleFilterHtml() {
+       var i,
+               moduleFilterHtml = "";
+
+       if ( !modulesList.length ) {
+               return false;
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        return function( o, n ) {
-               o = o.replace( /\s+$/, "" );
-               n = n.replace( /\s+$/, "" );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ modulesList.sort(function( a, b ) {
+               return a.localeCompare( b );
+       });
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                var i, pre,
-                       str = "",
-                       out = diff( o === "" ? [] : o.split(/\s+/), n === "" ? [] : n.split(/\s+/) ),
-                       oSpace = o.match(/\s+/g),
-                       nSpace = n.match(/\s+/g);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label>" +
+               "<select id='qunit-modulefilter' name='modulefilter'><option value='' " +
+               ( QUnit.urlParams.module === undefined ? "selected='selected'" : "" ) +
+               ">< All Modules ></option>";
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( oSpace == null ) {
-                       oSpace = [ " " ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ for ( i = 0; i < modulesList.length; i++ ) {
+               moduleFilterHtml += "<option value='" +
+                       escapeText( encodeURIComponent( modulesList[ i ] ) ) + "' " +
+                       ( QUnit.urlParams.module === modulesList[ i ] ? "selected='selected'" : "" ) +
+                       ">" + escapeText( modulesList[ i ] ) + "</option>";
+       }
+       moduleFilterHtml += "</select>";
+
+       return moduleFilterHtml;
+}
+
+function toolbarModuleFilter() {
+       var toolbar = id( "qunit-testrunner-toolbar" ),
+               moduleFilter = document.createElement( "span" ),
+               moduleFilterHtml = toolbarModuleFilterHtml();
+
+       if ( !toolbar || !moduleFilterHtml ) {
+               return false;
+       }
+
+       moduleFilter.setAttribute( "id", "qunit-modulefilter-container" );
+       moduleFilter.innerHTML = moduleFilterHtml;
+
+       addEvent( moduleFilter.lastChild, "change", applyUrlParams );
+
+       toolbar.appendChild( moduleFilter );
+}
+
+function appendToolbar() {
+       var toolbar = id( "qunit-testrunner-toolbar" );
+
+       if ( toolbar ) {
+               toolbar.appendChild( toolbarUrlConfigContainer() );
+               toolbar.appendChild( toolbarLooseFilter() );
+       }
+}
+
+function appendHeader() {
+       var header = id( "qunit-header" );
+
+       if ( header ) {
+               header.innerHTML = "<a href='" +
+                       setUrl({ filter: undefined, module: undefined, testId: undefined }) +
+                       "'>" + header.innerHTML + "</a> ";
+       }
+}
+
+function appendBanner() {
+       var banner = id( "qunit-banner" );
+
+       if ( banner ) {
+               banner.className = "";
+       }
+}
+
+function appendTestResults() {
+       var tests = id( "qunit-tests" ),
+               result = id( "qunit-testresult" );
+
+       if ( result ) {
+               result.parentNode.removeChild( result );
+       }
+
+       if ( tests ) {
+               tests.innerHTML = "";
+               result = document.createElement( "p" );
+               result.id = "qunit-testresult";
+               result.className = "result";
+               tests.parentNode.insertBefore( result, tests );
+               result.innerHTML = "Running...<br />&#160;";
+       }
+}
+
+function storeFixture() {
+       var fixture = id( "qunit-fixture" );
+       if ( fixture ) {
+               config.fixture = fixture.innerHTML;
+       }
+}
+
+function appendUserAgent() {
+       var userAgent = id( "qunit-userAgent" );
+
+       if ( userAgent ) {
+               userAgent.innerHTML = "";
+               userAgent.appendChild(
+                       document.createTextNode(
+                               "QUnit " + QUnit.version  + "; " + navigator.userAgent
+                       )
+               );
+       }
+}
+
+function appendTestsList( modules ) {
+       var i, l, x, z, test, moduleObj;
+
+       for ( i = 0, l = modules.length; i < l; i++ ) {
+               moduleObj = modules[ i ];
+
+               if ( moduleObj.name ) {
+                       modulesList.push( moduleObj.name );
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                else {
-                       oSpace.push( " " );
-               }
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( nSpace == null ) {
-                       nSpace = [ " " ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         for ( x = 0, z = moduleObj.tests.length; x < z; x++ ) {
+                       test = moduleObj.tests[ x ];
+
+                       appendTest( test.name, test.testId, moduleObj.name );
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                else {
-                       nSpace.push( " " );
-               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ }
+}
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( out.n.length === 0 ) {
-                       for ( i = 0; i < out.o.length; i++ ) {
-                               str += "<del>" + out.o[i] + oSpace[i] + "</del>";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function appendTest( name, testId, moduleName ) {
+       var title, rerunTrigger, testBlock, assertList,
+               tests = id( "qunit-tests" );
+
+       if ( !tests ) {
+               return;
+       }
+
+       title = document.createElement( "strong" );
+       title.innerHTML = getNameHtml( name, moduleName );
+
+       rerunTrigger = document.createElement( "a" );
+       rerunTrigger.innerHTML = "Rerun";
+       rerunTrigger.href = setUrl({ testId: testId });
+
+       testBlock = document.createElement( "li" );
+       testBlock.appendChild( title );
+       testBlock.appendChild( rerunTrigger );
+       testBlock.id = "qunit-test-output-" + testId;
+
+       assertList = document.createElement( "ol" );
+       assertList.className = "qunit-assert-list";
+
+       testBlock.appendChild( assertList );
+
+       tests.appendChild( testBlock );
+}
+
+// HTML Reporter initialization and load
+QUnit.begin(function( details ) {
+       var qunit = id( "qunit" );
+
+       // Fixture is the only one necessary to run without the #qunit element
+       storeFixture();
+
+       if ( qunit ) {
+               qunit.innerHTML =
+                       "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
+                       "<h2 id='qunit-banner'></h2>" +
+                       "<div id='qunit-testrunner-toolbar'></div>" +
+                       "<h2 id='qunit-userAgent'></h2>" +
+                       "<ol id='qunit-tests'></ol>";
+       }
+
+       appendHeader();
+       appendBanner();
+       appendTestResults();
+       appendUserAgent();
+       appendToolbar();
+       appendTestsList( details.modules );
+       toolbarModuleFilter();
+
+       if ( qunit && config.hidepassed ) {
+               addClass( qunit.lastChild, "hidepass" );
+       }
+});
+
+QUnit.done(function( details ) {
+       var i, key,
+               banner = id( "qunit-banner" ),
+               tests = id( "qunit-tests" ),
+               html = [
+                       "Tests completed in ",
+                       details.runtime,
+                       " milliseconds.<br />",
+                       "<span class='passed'>",
+                       details.passed,
+                       "</span> assertions of <span class='total'>",
+                       details.total,
+                       "</span> passed, <span class='failed'>",
+                       details.failed,
+                       "</span> failed."
+               ].join( "" );
+
+       if ( banner ) {
+               banner.className = details.failed ? "qunit-fail" : "qunit-pass";
+       }
+
+       if ( tests ) {
+               id( "qunit-testresult" ).innerHTML = html;
+       }
+
+       if ( config.altertitle && defined.document && document.title ) {
+
+               // show ✖ for good, ✔ for bad suite result in title
+               // use escape sequences in case file gets loaded with non-utf-8-charset
+               document.title = [
+                       ( details.failed ? "\u2716" : "\u2714" ),
+                       document.title.replace( /^[\u2714\u2716] /i, "" )
+               ].join( " " );
+       }
+
+       // clear own sessionStorage items if all tests passed
+       if ( config.reorder && defined.sessionStorage && details.failed === 0 ) {
+               for ( i = 0; i < sessionStorage.length; i++ ) {
+                       key = sessionStorage.key( i++ );
+                       if ( key.indexOf( "qunit-test-" ) === 0 ) {
+                               sessionStorage.removeItem( key );
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                else {
-                       if ( out.n[0].text == null ) {
-                               for ( n = 0; n < out.o.length && out.o[n].text == null; n++ ) {
-                                       str += "<del>" + out.o[n] + oSpace[n] + "</del>";
-                               }
-                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        for ( i = 0; i < out.n.length; i++ ) {
-                               if (out.n[i].text == null) {
-                                       str += "<ins>" + out.n[i] + nSpace[i] + "</ins>";
-                               }
-                               else {
-                                       // `pre` initialized at top of scope
-                                       pre = "";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // scroll back to top to show results
+       if ( config.scrolltop && window.scrollTo ) {
+               window.scrollTo( 0, 0 );
+       }
+});
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        for ( n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {
-                                               pre += "<del>" + out.o[n] + oSpace[n] + "</del>";
-                                       }
-                                       str += " " + out.n[i].text + nSpace[i] + pre;
-                               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function getNameHtml( name, module ) {
+       var nameHtml = "";
+
+       if ( module ) {
+               nameHtml = "<span class='module-name'>" + escapeText( module ) + "</span>: ";
+       }
+
+       nameHtml += "<span class='test-name'>" + escapeText( name ) + "</span>";
+
+       return nameHtml;
+}
+
+QUnit.testStart(function( details ) {
+       var running, testBlock, bad;
+
+       testBlock = id( "qunit-test-output-" + details.testId );
+       if ( testBlock ) {
+               testBlock.className = "running";
+       } else {
+
+               // Report later registered tests
+               appendTest( details.name, details.testId, details.module );
+       }
+
+       running = id( "qunit-testresult" );
+       if ( running ) {
+               bad = QUnit.config.reorder && defined.sessionStorage &&
+                       +sessionStorage.getItem( "qunit-test-" + details.module + "-" + details.name );
+
+               running.innerHTML = ( bad ?
+                       "Rerunning previously failed test: <br />" :
+                       "Running: <br />" ) +
+                       getNameHtml( details.name, details.module );
+       }
+
+});
+
+QUnit.log(function( details ) {
+       var assertList, assertLi,
+               message, expected, actual,
+               testItem = id( "qunit-test-output-" + details.testId );
+
+       if ( !testItem ) {
+               return;
+       }
+
+       message = escapeText( details.message ) || ( details.result ? "okay" : "failed" );
+       message = "<span class='test-message'>" + message + "</span>";
+       message += "<span class='runtime'>@ " + details.runtime + " ms</span>";
+
+       // pushFailure doesn't provide details.expected
+       // when it calls, it's implicit to also not show expected and diff stuff
+       // Also, we need to check details.expected existence, as it can exist and be undefined
+       if ( !details.result && hasOwn.call( details, "expected" ) ) {
+               expected = escapeText( QUnit.dump.parse( details.expected ) );
+               actual = escapeText( QUnit.dump.parse( details.actual ) );
+               message += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" +
+                       expected +
+                       "</pre></td></tr>";
+
+               if ( actual !== expected ) {
+                       message += "<tr class='test-actual'><th>Result: </th><td><pre>" +
+                               actual + "</pre></td></tr>" +
+                               "<tr class='test-diff'><th>Diff: </th><td><pre>" +
+                               QUnit.diff( expected, actual ) + "</pre></td></tr>";
+               } else {
+                       if ( expected.indexOf( "[object Array]" ) !== -1 ||
+                                       expected.indexOf( "[object Object]" ) !== -1 ) {
+                               message += "<tr class='test-message'><th>Message: </th><td>" +
+                                       "Diff suppressed as the depth of object is more than current max depth (" +
+                                       QUnit.config.maxDepth + ").<p>Hint: Use <code>QUnit.dump.maxDepth</code> to " +
+                                       " run with a higher max depth or <a href='" + setUrl({ maxDepth: -1 }) + "'>" +
+                                       "Rerun</a> without max depth.</p></td></tr>";
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                return str;
-       };
-}());
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ( details.source ) {
+                       message += "<tr class='test-source'><th>Source: </th><td><pre>" +
+                               escapeText( details.source ) + "</pre></td></tr>";
+               }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// for CommonJS environments, export everything
-if ( typeof exports !== "undefined" ) {
-       extend( exports, QUnit.constructor.prototype );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         message += "</table>";
+
+       // this occours when pushFailure is set and we have an extracted stack trace
+       } else if ( !details.result && details.source ) {
+               message += "<table>" +
+                       "<tr class='test-source'><th>Source: </th><td><pre>" +
+                       escapeText( details.source ) + "</pre></td></tr>" +
+                       "</table>";
+       }
+
+       assertList = testItem.getElementsByTagName( "ol" )[ 0 ];
+
+       assertLi = document.createElement( "li" );
+       assertLi.className = details.result ? "pass" : "fail";
+       assertLi.innerHTML = message;
+       assertList.appendChild( assertLi );
+});
+
+QUnit.testDone(function( details ) {
+       var testTitle, time, testItem, assertList,
+               good, bad, testCounts, skipped,
+               tests = id( "qunit-tests" );
+
+       if ( !tests ) {
+               return;
+       }
+
+       testItem = id( "qunit-test-output-" + details.testId );
+
+       assertList = testItem.getElementsByTagName( "ol" )[ 0 ];
+
+       good = details.passed;
+       bad = details.failed;
+
+       // store result when possible
+       if ( config.reorder && defined.sessionStorage ) {
+               if ( bad ) {
+                       sessionStorage.setItem( "qunit-test-" + details.module + "-" + details.name, bad );
+               } else {
+                       sessionStorage.removeItem( "qunit-test-" + details.module + "-" + details.name );
+               }
+       }
+
+       if ( bad === 0 ) {
+               addClass( assertList, "qunit-collapsed" );
+       }
+
+       // testItem.firstChild is the test name
+       testTitle = testItem.firstChild;
+
+       testCounts = bad ?
+               "<b class='failed'>" + bad + "</b>, " + "<b class='passed'>" + good + "</b>, " :
+               "";
+
+       testTitle.innerHTML += " <b class='counts'>(" + testCounts +
+               details.assertions.length + ")</b>";
+
+       if ( details.skipped ) {
+               testItem.className = "skipped";
+               skipped = document.createElement( "em" );
+               skipped.className = "qunit-skipped-label";
+               skipped.innerHTML = "skipped";
+               testItem.insertBefore( skipped, testTitle );
+       } else {
+               addEvent( testTitle, "click", function() {
+                       toggleClass( assertList, "qunit-collapsed" );
+               });
+
+               testItem.className = bad ? "fail" : "pass";
+
+               time = document.createElement( "span" );
+               time.className = "runtime";
+               time.innerHTML = details.runtime + " ms";
+               testItem.insertBefore( time, assertList );
+       }
+});
+
+if ( defined.document ) {
+       if ( document.readyState === "complete" ) {
+               QUnit.load();
+       } else {
+               addEvent( window, "load", QUnit.load );
+       }
+} else {
+       config.pageLoaded = true;
+       config.autorun = true;
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// get at whatever the global object is, like window in browsers
-}( (function() {return this;}.call()) ));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+})();
</ins></span></pre>
</div>
</div>

</body>
</html>