text: "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;
  };
  
  };
  