| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| var sendRequestNatives = requireNative('sendRequest'); |
| |
| function registerHooks(api) { |
| var chromeTest = api.compiledApi; |
| var apiFunctions = api.apiFunctions; |
| |
| apiFunctions.setHandleRequest('notifyPass', function() { |
| requireAsync('testNatives').then(function(natives) { |
| natives.NotifyPass(); |
| }); |
| }); |
| |
| apiFunctions.setHandleRequest('notifyFail', function(message) { |
| requireAsync('testNatives').then(function(natives) { |
| natives.NotifyFail(message); |
| }); |
| }); |
| |
| apiFunctions.setHandleRequest('log', function() { |
| requireAsync('testNatives').then(function(natives) { |
| natives.Log($Array.join(arguments, ' ')); |
| }); |
| }); |
| |
| } |
| |
| function testDone(runNextTest) { |
| // Use a promise here to allow previous test contexts to be eligible for |
| // garbage collection. |
| Promise.resolve().then(function() { |
| runNextTest(); |
| }); |
| } |
| |
| function exportTests(tests, runTests, exports) { |
| $Array.forEach(tests, function(test) { |
| 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; |