Index: extensions/test/data/unit_test_environment_specific_bindings.js |
diff --git a/extensions/test/data/unit_test_environment_specific_bindings.js b/extensions/test/data/unit_test_environment_specific_bindings.js |
index 245d050d6325400bc5c7722c790620dc9a8d83aa..3636ec71502a06fd242da31d12734a6a43759abc 100644 |
--- a/extensions/test/data/unit_test_environment_specific_bindings.js |
+++ b/extensions/test/data/unit_test_environment_specific_bindings.js |
@@ -3,6 +3,7 @@ |
// found in the LICENSE file. |
var nativesPromise = requireAsync('testNatives'); |
+var sendRequestNatives = requireNative('sendRequest'); |
function registerHooks(api) { |
var chromeTest = api.compiledApi; |
@@ -41,10 +42,106 @@ function exportTests(tests, runTests, exports) { |
exports[test.name] = function() { |
runTests([test]); |
return true; |
- } |
+ }; |
}); |
} |
+/** |
+ * A fake implementation of setTimeout and clearTimeout. |
+ * @constructor |
+ */ |
+function TimeoutManager() { |
+ this.timeouts_ = {}; |
+ this.nextTimeoutId_ = 0; |
+ this.currentTime = 0; |
+ this.autorunEnabled_ = false; |
+} |
+ |
+/** |
+ * Installs setTimeout and clearTimeout into the global object. |
+ */ |
+TimeoutManager.prototype.installGlobals = function() { |
+ var global = sendRequestNatives.GetGlobal({}); |
+ global.setTimeout = this.setTimeout_.bind(this); |
+ global.clearTimeout = this.clearTimeout_.bind(this); |
+}; |
+ |
+/** |
+ * Starts auto-running of timeout callbacks. Until |numCallbacksToRun| callbacks |
+ * have run, any timeout callbacks set by calls to setTimeout (including before |
+ * the call to run) will cause the currentTime to be advanced to the time of |
+ * the timeout. |
+ */ |
+TimeoutManager.prototype.run = function(numCallbacksToRun) { |
+ this.numCallbacksToRun_ = numCallbacksToRun; |
+ Promise.resolve().then(this.autoRun_.bind(this)); |
+}; |
+ |
+/** |
+ * Runs timeout callbacks with earliest timeout. |
+ * @private |
+ */ |
+TimeoutManager.prototype.autoRun_ = function() { |
+ if (this.numCallbacksToRun_ <= 0 || $Object.keys(this.timeouts_).length == 0) |
+ return; |
+ |
+ // Bucket the timeouts by their timeout time. |
+ var timeoutsByTimeout = {}; |
+ var timeoutIds = $Object.keys(this.timeouts_); |
+ for (var i = 0; i < timeoutIds.length; i++) { |
+ var timeout = this.timeouts_[timeoutIds[i]]; |
+ var timeMs = timeout.timeMs; |
+ if (!timeoutsByTimeout[timeMs]) |
+ timeoutsByTimeout[timeMs] = []; |
+ timeoutsByTimeout[timeMs].push(timeout); |
+ } |
+ this.currentTime = |
+ $Function.apply(Math.min, null, $Object.keys((timeoutsByTimeout))); |
+ // Run all timeouts in the earliest timeout bucket. |
+ var timeouts = timeoutsByTimeout[this.currentTime]; |
+ for (var i = 0; i < timeouts.length; i++) { |
+ var currentTimeout = timeouts[i]; |
+ if (!this.timeouts_[currentTimeout.id]) |
+ continue; |
+ this.numCallbacksToRun_--; |
+ delete this.timeouts_[currentTimeout.id]; |
+ try { |
+ currentTimeout.target(); |
+ } catch (e) { |
+ console.log('error calling timeout target ' + e.stack); |
+ } |
+ } |
+ // Continue running any later callbacks. |
+ Promise.resolve().then(this.autoRun_.bind(this)); |
+}; |
+ |
+/** |
+ * A fake implementation of setTimeout. This does not support passing callback |
+ * arguments. |
+ * @private |
+ */ |
+TimeoutManager.prototype.setTimeout_ = function(target, timeoutMs) { |
+ var timeoutId = this.nextTimeoutId_++; |
+ this.timeouts_[timeoutId] = { |
+ id: timeoutId, |
+ target: target, |
+ timeMs: timeoutMs + this.currentTime, |
+ }; |
+ if (this.autorunEnabled_) |
+ Promise.resolve().then(this.autoRun_.bind(this)); |
+ return timeoutId; |
+}; |
+ |
+/** |
+ * A fake implementation of clearTimeout. |
+ * @private |
+ */ |
+TimeoutManager.prototype.clearTimeout_ = function(timeoutId) { |
+ if (this.timeouts_[timeoutId]) |
+ delete this.timeouts_[timeoutId]; |
+}; |
+ |
exports.registerHooks = registerHooks; |
exports.testDone = testDone; |
exports.exportTests = exportTests; |
+exports.TimeoutManager = TimeoutManager; |