| "use strict"; |
| module.exports = function(Promise, INTERNAL, debug) { |
| var util = require("./util"); |
| var TimeoutError = Promise.TimeoutError; |
| |
| function HandleWrapper(handle) { |
| this.handle = handle; |
| } |
| |
| HandleWrapper.prototype._resultCancelled = function() { |
| clearTimeout(this.handle); |
| }; |
| |
| var afterValue = function(value) { return delay(+this).thenReturn(value); }; |
| var delay = Promise.delay = function (ms, value) { |
| var ret; |
| var handle; |
| if (value !== undefined) { |
| ret = Promise.resolve(value) |
| ._then(afterValue, null, null, ms, undefined); |
| if (debug.cancellation() && value instanceof Promise) { |
| ret._setOnCancel(value); |
| } |
| } else { |
| ret = new Promise(INTERNAL); |
| handle = setTimeout(function() { ret._fulfill(); }, +ms); |
| if (debug.cancellation()) { |
| ret._setOnCancel(new HandleWrapper(handle)); |
| } |
| ret._captureStackTrace(); |
| } |
| ret._setAsyncGuaranteed(); |
| return ret; |
| }; |
| |
| Promise.prototype.delay = function (ms) { |
| return delay(ms, this); |
| }; |
| |
| var afterTimeout = function (promise, message, parent) { |
| var err; |
| if (typeof message !== "string") { |
| if (message instanceof Error) { |
| err = message; |
| } else { |
| err = new TimeoutError("operation timed out"); |
| } |
| } else { |
| err = new TimeoutError(message); |
| } |
| util.markAsOriginatingFromRejection(err); |
| promise._attachExtraTrace(err); |
| promise._reject(err); |
| |
| if (parent != null) { |
| parent.cancel(); |
| } |
| }; |
| |
| function successClear(value) { |
| clearTimeout(this.handle); |
| return value; |
| } |
| |
| function failureClear(reason) { |
| clearTimeout(this.handle); |
| throw reason; |
| } |
| |
| Promise.prototype.timeout = function (ms, message) { |
| ms = +ms; |
| var ret, parent; |
| |
| var handleWrapper = new HandleWrapper(setTimeout(function timeoutTimeout() { |
| if (ret.isPending()) { |
| afterTimeout(ret, message, parent); |
| } |
| }, ms)); |
| |
| if (debug.cancellation()) { |
| parent = this.then(); |
| ret = parent._then(successClear, failureClear, |
| undefined, handleWrapper, undefined); |
| ret._setOnCancel(handleWrapper); |
| } else { |
| ret = this._then(successClear, failureClear, |
| undefined, handleWrapper, undefined); |
| } |
| |
| return ret; |
| }; |
| |
| }; |