“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;

};

};