diff --git a/lib/reporters/html.js b/lib/reporters/html.js
index aa3f81a10a..f09279be20 100644
--- a/lib/reporters/html.js
+++ b/lib/reporters/html.js
@@ -120,8 +120,6 @@ function HTML(runner, root) {
});
runner.on('test end', function(test){
- window.scrollTo(0, document.body.scrollHeight);
-
// TODO: add to stats
var percent = stats.tests / this.total * 100 | 0;
if (progress) progress.update(percent).draw(ctx);
diff --git a/lib/runner.js b/lib/runner.js
index 3607ce40dc..ea0c28f279 100644
--- a/lib/runner.js
+++ b/lib/runner.js
@@ -8,9 +8,7 @@ var EventEmitter = require('events').EventEmitter
, Test = require('./test')
, utils = require('./utils')
, filter = utils.filter
- , keys = utils.keys
- , noop = function(){}
- , immediately = global.setImmediate || process.nextTick;
+ , keys = utils.keys;
/**
* Non-enumerable globals.
@@ -62,6 +60,14 @@ function Runner(suite) {
this.globals(this.globalProps().concat(['errno']));
}
+/**
+ * Wrapper for setImmediate, process.nextTick, or browser polyfill.
+ *
+ * @param {Function} fn
+ * @api private
+ */
+Runner.immediately = global.setImmediate || process.nextTick;
+
/**
* Inherit from `EventEmitter.prototype`.
*/
@@ -243,7 +249,7 @@ Runner.prototype.hook = function(name, fn){
});
}
- immediately(function(){
+ Runner.immediately(function(){
next(0);
});
};
diff --git a/lib/utils.js b/lib/utils.js
index 3baf12f6a3..2bf0978aa2 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -107,7 +107,7 @@ exports.filter = function(arr, fn){
* @api private
*/
-exports.keys = function(obj) {
+exports.keys = Object.keys || function(obj) {
var keys = []
, has = Object.prototype.hasOwnProperty // for `window` on <=IE8
diff --git a/support/tail.js b/support/tail.js
index 0f9b64a497..7216b998cc 100644
--- a/support/tail.js
+++ b/support/tail.js
@@ -12,34 +12,6 @@ process.exit = function(status){};
process.stdout = {};
global = window;
-/**
- * next tick implementation.
- */
-
-process.nextTick = (function(){
- // postMessage behaves badly on IE8
- if (window.ActiveXObject || !window.postMessage) {
- return function(fn){ fn() };
- }
-
- // based on setZeroTimeout by David Baron
- // - http://dbaron.org/log/20100309-faster-timeouts
- var timeouts = []
- , name = 'mocha-zero-timeout'
-
- window.addEventListener('message', function(e){
- if (e.source == window && e.data == name) {
- if (e.stopPropagation) e.stopPropagation();
- if (timeouts.length) timeouts.shift()();
- }
- }, true);
-
- return function(fn){
- timeouts.push(fn);
- window.postMessage(name, '*');
- }
-})();
-
/**
* Remove uncaughtException listener.
*/
@@ -72,6 +44,31 @@ process.on = function(e, fn){
var Mocha = window.Mocha = require('mocha'),
mocha = window.mocha = new Mocha({ reporter: 'html' });
+ var immediateQueue = []
+ , immediateTimeout;
+
+ function timeslice() {
+ var immediateStart = new Date().getTime();
+ while (immediateQueue.length && (new Date().getTime() - immediateStart) < 100) {
+ immediateQueue.shift()();
+ }
+ if (immediateQueue.length) {
+ immediateTimeout = setTimeout(timeslice, 0);
+ } else {
+ immediateTimeout = null;
+ }
+ }
+
+ /**
+ * High-performance override of Runner.immediately.
+ */
+ Mocha.Runner.immediately = function(callback) {
+ immediateQueue.push(callback);
+ if (!immediateTimeout) {
+ immediateTimeout = setTimeout(timeslice, 0);
+ }
+ };
+
/**
* Override ui to ensure that the ui functions are initialized.
* Normally this would happen in Mocha.prototype.loadFiles.