Skip to content
Snippets Groups Projects
index.js 8.75 MiB
Newer Older
  • Learn to ignore specific revisions
  • Romain CREY's avatar
    Romain CREY committed
            var fn = nodebackForPromise(promise, multiArgs);
            try {
                cb.apply(_receiver, withAppended(arguments, fn));
            } catch(e) {
                promise._rejectCallback(maybeWrapAsError(e), true, true);
            }
            if (!promise._isFateSealed()) promise._setAsyncGuaranteed();
            return promise;
        }
        util.notEnumerableProp(promisified, "__isPromisified__", true);
        return promisified;
    }
    
    var makeNodePromisified = canEvaluate
        ? makeNodePromisifiedEval
        : makeNodePromisifiedClosure;
    
    function promisifyAll(obj, suffix, filter, promisifier, multiArgs) {
        var suffixRegexp = new RegExp(escapeIdentRegex(suffix) + "$");
        var methods =
            promisifiableMethods(obj, suffix, suffixRegexp, filter);
    
        for (var i = 0, len = methods.length; i < len; i+= 2) {
            var key = methods[i];
            var fn = methods[i+1];
            var promisifiedKey = key + suffix;
            if (promisifier === makeNodePromisified) {
                obj[promisifiedKey] =
                    makeNodePromisified(key, THIS, key, fn, suffix, multiArgs);
            } else {
                var promisified = promisifier(fn, function() {
                    return makeNodePromisified(key, THIS, key,
                                               fn, suffix, multiArgs);
                });
                util.notEnumerableProp(promisified, "__isPromisified__", true);
                obj[promisifiedKey] = promisified;
            }
        }
        util.toFastProperties(obj);
        return obj;
    }
    
    function promisify(callback, receiver, multiArgs) {
        return makeNodePromisified(callback, receiver, undefined,
                                    callback, null, multiArgs);
    }
    
    Promise.promisify = function (fn, options) {
        if (typeof fn !== "function") {
            throw new TypeError("expecting a function but got " + util.classString(fn));
        }
        if (isPromisified(fn)) {
            return fn;
        }
        options = Object(options);
        var receiver = options.context === undefined ? THIS : options.context;
        var multiArgs = !!options.multiArgs;
        var ret = promisify(fn, receiver, multiArgs);
        util.copyDescriptors(fn, ret, propsFilter);
        return ret;
    };
    
    Promise.promisifyAll = function (target, options) {
        if (typeof target !== "function" && typeof target !== "object") {
            throw new TypeError("the target of promisifyAll must be an object or a function\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
        }
        options = Object(options);
        var multiArgs = !!options.multiArgs;
        var suffix = options.suffix;
        if (typeof suffix !== "string") suffix = defaultSuffix;
        var filter = options.filter;
        if (typeof filter !== "function") filter = defaultFilter;
        var promisifier = options.promisifier;
        if (typeof promisifier !== "function") promisifier = makeNodePromisified;
    
        if (!util.isIdentifier(suffix)) {
            throw new RangeError("suffix must be a valid identifier\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
        }
    
        var keys = util.inheritedDataKeys(target);
        for (var i = 0; i < keys.length; ++i) {
            var value = target[keys[i]];
            if (keys[i] !== "constructor" &&
                util.isClass(value)) {
                promisifyAll(value.prototype, suffix, filter, promisifier,
                    multiArgs);
                promisifyAll(value, suffix, filter, promisifier, multiArgs);
            }
        }
    
        return promisifyAll(target, suffix, filter, promisifier, multiArgs);
    };
    };
    
    
    
    /***/ }),
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    module.exports = function(
        Promise, PromiseArray, tryConvertToPromise, apiRejection) {
    
    var util = __webpack_require__(27);
    
    Romain CREY's avatar
    Romain CREY committed
    var isObject = util.isObject;
    
    var es5 = __webpack_require__(28);
    
    Romain CREY's avatar
    Romain CREY committed
    var Es6Map;
    if (typeof Map === "function") Es6Map = Map;
    
    var mapToEntries = (function() {
        var index = 0;
        var size = 0;
    
        function extractEntry(value, key) {
            this[index] = value;
            this[index + size] = key;
            index++;
        }
    
        return function mapToEntries(map) {
            size = map.size;
            index = 0;
            var ret = new Array(map.size * 2);
            map.forEach(extractEntry, ret);
            return ret;
        };
    })();
    
    var entriesToMap = function(entries) {
        var ret = new Es6Map();
        var length = entries.length / 2 | 0;
        for (var i = 0; i < length; ++i) {
            var key = entries[length + i];
            var value = entries[i];
            ret.set(key, value);
        }
        return ret;
    };
    
    function PropertiesPromiseArray(obj) {
        var isMap = false;
        var entries;
        if (Es6Map !== undefined && obj instanceof Es6Map) {
            entries = mapToEntries(obj);
            isMap = true;
        } else {
            var keys = es5.keys(obj);
            var len = keys.length;
            entries = new Array(len * 2);
            for (var i = 0; i < len; ++i) {
                var key = keys[i];
                entries[i] = obj[key];
                entries[i + len] = key;
            }
        }
        this.constructor$(entries);
        this._isMap = isMap;
        this._init$(undefined, isMap ? -6 : -3);
    }
    util.inherits(PropertiesPromiseArray, PromiseArray);
    
    PropertiesPromiseArray.prototype._init = function () {};
    
    PropertiesPromiseArray.prototype._promiseFulfilled = function (value, index) {
        this._values[index] = value;
        var totalResolved = ++this._totalResolved;
        if (totalResolved >= this._length) {
            var val;
            if (this._isMap) {
                val = entriesToMap(this._values);
            } else {
                val = {};
                var keyOffset = this.length();
                for (var i = 0, len = this.length(); i < len; ++i) {
                    val[this._values[i + keyOffset]] = this._values[i];
                }
            }
            this._resolve(val);
            return true;
        }
        return false;
    };
    
    PropertiesPromiseArray.prototype.shouldCopyValues = function () {
        return false;
    };
    
    PropertiesPromiseArray.prototype.getActualLength = function (len) {
        return len >> 1;
    };
    
    function props(promises) {
        var ret;
        var castValue = tryConvertToPromise(promises);
    
        if (!isObject(castValue)) {
            return apiRejection("cannot await properties of a non-object\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
        } else if (castValue instanceof Promise) {
            ret = castValue._then(
                Promise.props, undefined, undefined, undefined, undefined);
        } else {
            ret = new PropertiesPromiseArray(castValue).promise();
        }
    
        if (castValue instanceof Promise) {
            ret._propagateFrom(castValue, 2);
        }
        return ret;
    }
    
    Promise.prototype.props = function () {
        return props(this);
    };
    
    Promise.props = function (promises) {
        return props(promises);
    };
    };
    
    
    /***/ }),
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    module.exports = function(
        Promise, INTERNAL, tryConvertToPromise, apiRejection) {
    
    var util = __webpack_require__(27);
    
    Romain CREY's avatar
    Romain CREY committed
    
    var raceLater = function (promise) {
        return promise.then(function(array) {
            return race(array, promise);
        });
    };
    
    function race(promises, parent) {
        var maybePromise = tryConvertToPromise(promises);
    
        if (maybePromise instanceof Promise) {
            return raceLater(maybePromise);
        } else {
            promises = util.asArray(promises);
            if (promises === null)
                return apiRejection("expecting an array or an iterable object but got " + util.classString(promises));
        }
    
        var ret = new Promise(INTERNAL);
        if (parent !== undefined) {
            ret._propagateFrom(parent, 3);
        }
        var fulfill = ret._fulfill;
        var reject = ret._reject;
        for (var i = 0, len = promises.length; i < len; ++i) {
            var val = promises[i];
    
            if (val === undefined && !(i in promises)) {
                continue;
            }
    
            Promise.cast(val)._then(fulfill, reject, undefined, ret, null);
        }
        return ret;
    }
    
    Promise.race = function (promises) {
        return race(promises, undefined);
    };
    
    Promise.prototype.race = function () {
        return race(this, undefined);
    };
    
    };
    
    
    /***/ }),
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    module.exports = function(Promise,
                              PromiseArray,
                              apiRejection,
                              tryConvertToPromise,
                              INTERNAL,
                              debug) {
    var getDomain = Promise._getDomain;
    
    var util = __webpack_require__(27);
    
    Romain CREY's avatar
    Romain CREY committed
    var tryCatch = util.tryCatch;
    
    function ReductionPromiseArray(promises, fn, initialValue, _each) {
        this.constructor$(promises);
        var domain = getDomain();
        this._fn = domain === null ? fn : util.domainBind(domain, fn);
        if (initialValue !== undefined) {
            initialValue = Promise.resolve(initialValue);
            initialValue._attachCancellationCallback(this);
        }
        this._initialValue = initialValue;
        this._currentCancellable = null;
        if(_each === INTERNAL) {
            this._eachValues = Array(this._length);
        } else if (_each === 0) {
            this._eachValues = null;
        } else {
            this._eachValues = undefined;
        }
        this._promise._captureStackTrace();
        this._init$(undefined, -5);
    }
    util.inherits(ReductionPromiseArray, PromiseArray);
    
    ReductionPromiseArray.prototype._gotAccum = function(accum) {
        if (this._eachValues !== undefined && 
            this._eachValues !== null && 
            accum !== INTERNAL) {
            this._eachValues.push(accum);
        }
    };
    
    ReductionPromiseArray.prototype._eachComplete = function(value) {
        if (this._eachValues !== null) {
            this._eachValues.push(value);
        }
        return this._eachValues;
    };
    
    ReductionPromiseArray.prototype._init = function() {};
    
    ReductionPromiseArray.prototype._resolveEmptyArray = function() {
        this._resolve(this._eachValues !== undefined ? this._eachValues
                                                     : this._initialValue);
    };
    
    ReductionPromiseArray.prototype.shouldCopyValues = function () {
        return false;
    };
    
    ReductionPromiseArray.prototype._resolve = function(value) {
        this._promise._resolveCallback(value);
        this._values = null;
    };
    
    ReductionPromiseArray.prototype._resultCancelled = function(sender) {
        if (sender === this._initialValue) return this._cancel();
        if (this._isResolved()) return;
        this._resultCancelled$();
        if (this._currentCancellable instanceof Promise) {
            this._currentCancellable.cancel();
        }
        if (this._initialValue instanceof Promise) {
            this._initialValue.cancel();
        }
    };
    
    ReductionPromiseArray.prototype._iterate = function (values) {
        this._values = values;
        var value;
        var i;
        var length = values.length;
        if (this._initialValue !== undefined) {
            value = this._initialValue;
            i = 0;
        } else {
            value = Promise.resolve(values[0]);
            i = 1;
        }
    
        this._currentCancellable = value;
    
        if (!value.isRejected()) {
            for (; i < length; ++i) {
                var ctx = {
                    accum: null,
                    value: values[i],
                    index: i,
                    length: length,
                    array: this
                };
                value = value._then(gotAccum, undefined, undefined, ctx, undefined);
            }
        }
    
        if (this._eachValues !== undefined) {
            value = value
                ._then(this._eachComplete, undefined, undefined, this, undefined);
        }
        value._then(completed, completed, undefined, value, this);
    };
    
    Promise.prototype.reduce = function (fn, initialValue) {
        return reduce(this, fn, initialValue, null);
    };
    
    Promise.reduce = function (promises, fn, initialValue, _each) {
        return reduce(promises, fn, initialValue, _each);
    };
    
    function completed(valueOrReason, array) {
        if (this.isFulfilled()) {
            array._resolve(valueOrReason);
        } else {
            array._reject(valueOrReason);
        }
    }
    
    function reduce(promises, fn, initialValue, _each) {
        if (typeof fn !== "function") {
            return apiRejection("expecting a function but got " + util.classString(fn));
        }
        var array = new ReductionPromiseArray(promises, fn, initialValue, _each);
        return array.promise();
    }
    
    function gotAccum(accum) {
        this.accum = accum;
        this.array._gotAccum(accum);
        var value = tryConvertToPromise(this.value, this.array._promise);
        if (value instanceof Promise) {
            this.array._currentCancellable = value;
            return value._then(gotValue, undefined, undefined, this, undefined);
        } else {
            return gotValue.call(this, value);
        }
    }
    
    function gotValue(value) {
        var array = this.array;
        var promise = array._promise;
        var fn = tryCatch(array._fn);
        promise._pushContext();
        var ret;
        if (array._eachValues !== undefined) {
            ret = fn.call(promise._boundValue(), value, this.index, this.length);
        } else {
            ret = fn.call(promise._boundValue(),
                                  this.accum, value, this.index, this.length);
        }
        if (ret instanceof Promise) {
            array._currentCancellable = ret;
        }
        var promiseCreated = promise._popContext();
        debug.checkForgottenReturns(
            ret,
            promiseCreated,
            array._eachValues !== undefined ? "Promise.each" : "Promise.reduce",
            promise
        );
        return ret;
    }
    };
    
    
    /***/ }),
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    module.exports =
        function(Promise, PromiseArray, debug) {
    var PromiseInspection = Promise.PromiseInspection;
    
    var util = __webpack_require__(27);
    
    Romain CREY's avatar
    Romain CREY committed
    
    function SettledPromiseArray(values) {
        this.constructor$(values);
    }
    util.inherits(SettledPromiseArray, PromiseArray);
    
    SettledPromiseArray.prototype._promiseResolved = function (index, inspection) {
        this._values[index] = inspection;
        var totalResolved = ++this._totalResolved;
        if (totalResolved >= this._length) {
            this._resolve(this._values);
            return true;
        }
        return false;
    };
    
    SettledPromiseArray.prototype._promiseFulfilled = function (value, index) {
        var ret = new PromiseInspection();
        ret._bitField = 33554432;
        ret._settledValueField = value;
        return this._promiseResolved(index, ret);
    };
    SettledPromiseArray.prototype._promiseRejected = function (reason, index) {
        var ret = new PromiseInspection();
        ret._bitField = 16777216;
        ret._settledValueField = reason;
        return this._promiseResolved(index, ret);
    };
    
    Promise.settle = function (promises) {
        debug.deprecated(".settle()", ".reflect()");
        return new SettledPromiseArray(promises).promise();
    };
    
    Promise.prototype.settle = function () {
        return Promise.settle(this);
    };
    };
    
    
    /***/ }),
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    module.exports =
    function(Promise, PromiseArray, apiRejection) {
    
    var util = __webpack_require__(27);
    var RangeError = __webpack_require__(32).RangeError;
    var AggregateError = __webpack_require__(32).AggregateError;
    
    Romain CREY's avatar
    Romain CREY committed
    var isArray = util.isArray;
    var CANCELLATION = {};
    
    
    function SomePromiseArray(values) {
        this.constructor$(values);
        this._howMany = 0;
        this._unwrap = false;
        this._initialized = false;
    }
    util.inherits(SomePromiseArray, PromiseArray);
    
    SomePromiseArray.prototype._init = function () {
        if (!this._initialized) {
            return;
        }
        if (this._howMany === 0) {
            this._resolve([]);
            return;
        }
        this._init$(undefined, -5);
        var isArrayResolved = isArray(this._values);
        if (!this._isResolved() &&
            isArrayResolved &&
            this._howMany > this._canPossiblyFulfill()) {
            this._reject(this._getRangeError(this.length()));
        }
    };
    
    SomePromiseArray.prototype.init = function () {
        this._initialized = true;
        this._init();
    };
    
    SomePromiseArray.prototype.setUnwrap = function () {
        this._unwrap = true;
    };
    
    SomePromiseArray.prototype.howMany = function () {
        return this._howMany;
    };
    
    SomePromiseArray.prototype.setHowMany = function (count) {
        this._howMany = count;
    };
    
    SomePromiseArray.prototype._promiseFulfilled = function (value) {
        this._addFulfilled(value);
        if (this._fulfilled() === this.howMany()) {
            this._values.length = this.howMany();
            if (this.howMany() === 1 && this._unwrap) {
                this._resolve(this._values[0]);
            } else {
                this._resolve(this._values);
            }
            return true;
        }
        return false;
    
    };
    SomePromiseArray.prototype._promiseRejected = function (reason) {
        this._addRejected(reason);
        return this._checkOutcome();
    };
    
    SomePromiseArray.prototype._promiseCancelled = function () {
        if (this._values instanceof Promise || this._values == null) {
            return this._cancel();
        }
        this._addRejected(CANCELLATION);
        return this._checkOutcome();
    };
    
    SomePromiseArray.prototype._checkOutcome = function() {
        if (this.howMany() > this._canPossiblyFulfill()) {
            var e = new AggregateError();
            for (var i = this.length(); i < this._values.length; ++i) {
                if (this._values[i] !== CANCELLATION) {
                    e.push(this._values[i]);
                }
            }
            if (e.length > 0) {
                this._reject(e);
            } else {
                this._cancel();
            }
            return true;
        }
        return false;
    };
    
    SomePromiseArray.prototype._fulfilled = function () {
        return this._totalResolved;
    };
    
    SomePromiseArray.prototype._rejected = function () {
        return this._values.length - this.length();
    };
    
    SomePromiseArray.prototype._addRejected = function (reason) {
        this._values.push(reason);
    };
    
    SomePromiseArray.prototype._addFulfilled = function (value) {
        this._values[this._totalResolved++] = value;
    };
    
    SomePromiseArray.prototype._canPossiblyFulfill = function () {
        return this.length() - this._rejected();
    };
    
    SomePromiseArray.prototype._getRangeError = function (count) {
        var message = "Input array must contain at least " +
                this._howMany + " items but contains only " + count + " items";
        return new RangeError(message);
    };
    
    SomePromiseArray.prototype._resolveEmptyArray = function () {
        this._reject(this._getRangeError(0));
    };
    
    function some(promises, howMany) {
        if ((howMany | 0) !== howMany || howMany < 0) {
            return apiRejection("expecting a positive integer\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
        }
        var ret = new SomePromiseArray(promises);
        var promise = ret.promise();
        ret.setHowMany(howMany);
        ret.init();
        return promise;
    }
    
    Promise.some = function (promises, howMany) {
        return some(promises, howMany);
    };
    
    Promise.prototype.some = function (howMany) {
        return some(this, howMany);
    };
    
    Promise._SomePromiseArray = SomePromiseArray;
    };
    
    
    /***/ }),
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    module.exports = function(Promise, INTERNAL) {
    var PromiseMap = Promise.map;
    
    Promise.prototype.filter = function (fn, options) {
        return PromiseMap(this, fn, options, INTERNAL);
    };
    
    Promise.filter = function (promises, fn, options) {
        return PromiseMap(promises, fn, options, INTERNAL);
    };
    };
    
    
    /***/ }),
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    module.exports = function(Promise, INTERNAL) {
    var PromiseReduce = Promise.reduce;
    var PromiseAll = Promise.all;
    
    function promiseAllThis() {
        return PromiseAll(this);
    }
    
    function PromiseMapSeries(promises, fn) {
        return PromiseReduce(promises, fn, INTERNAL, INTERNAL);
    }
    
    Promise.prototype.each = function (fn) {
        return PromiseReduce(this, fn, INTERNAL, 0)
                  ._then(promiseAllThis, undefined, undefined, this, undefined);
    };
    
    Promise.prototype.mapSeries = function (fn) {
        return PromiseReduce(this, fn, INTERNAL, INTERNAL);
    };
    
    Promise.each = function (promises, fn) {
        return PromiseReduce(promises, fn, INTERNAL, 0)
                  ._then(promiseAllThis, undefined, undefined, promises, undefined);
    };
    
    Promise.mapSeries = PromiseMapSeries;
    };
    
    
    
    /***/ }),
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    module.exports = function(Promise) {
    var SomePromiseArray = Promise._SomePromiseArray;
    function any(promises) {
        var ret = new SomePromiseArray(promises);
        var promise = ret.promise();
        ret.setHowMany(1);
        ret.setUnwrap();
        ret.init();
        return promise;
    }
    
    Promise.any = function (promises) {
        return any(promises);
    };
    
    Promise.prototype.any = function () {
        return any(this);
    };
    
    };
    
    
    /***/ }),
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    
    
    var core = __webpack_require__(62),
        isArray = __webpack_require__(74),
        isFunction = __webpack_require__(64),
        isObjectLike = __webpack_require__(72);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    module.exports = function (options) {
    
        var errorText = 'Please verify options'; // For better minification because this string is repeating
    
        if (!isObjectLike(options)) {
            throw new TypeError(errorText);
        }
    
        if (!isFunction(options.request)) {
            throw new TypeError(errorText + '.request');
        }
    
        if (!isArray(options.expose) || options.expose.length === 0) {
            throw new TypeError(errorText + '.expose');
        }
    
    
        var plumbing = core({
            PromiseImpl: options.PromiseImpl,
            constructorMixin: options.constructorMixin
        });
    
    
        // Intercepting Request's init method
    
        var originalInit = options.request.Request.prototype.init;
    
        options.request.Request.prototype.init = function RP$initInterceptor(requestOptions) {
    
            // Init may be called again - currently in case of redirects
            if (isObjectLike(requestOptions) && !this._callback && !this._rp_promise) {
    
                plumbing.init.call(this, requestOptions);
    
            }
    
            return originalInit.apply(this, arguments);
    
        };
    
    
        // Exposing the Promise capabilities
    
        var thenExposed = false;
        for ( var i = 0; i < options.expose.length; i+=1 ) {
    
            var method = options.expose[i];
    
            plumbing[ method === 'promise' ? 'exposePromise' : 'exposePromiseMethod' ](
                options.request.Request.prototype,
                null,
                '_rp_promise',
                method
            );
    
            if (method === 'then') {
                thenExposed = true;
            }
    
        }
    
        if (!thenExposed) {
            throw new Error('Please expose "then"');
        }
    
    };
    
    
    /***/ }),
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    
    
    var errors = __webpack_require__(63),
        isFunction = __webpack_require__(64),
        isObjectLike = __webpack_require__(72),
        isString = __webpack_require__(73),
        isUndefined = __webpack_require__(75);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    module.exports = function (options) {
    
        var errorText = 'Please verify options'; // For better minification because this string is repeating
    
        if (!isObjectLike(options)) {
            throw new TypeError(errorText);
        }
    
        if (!isFunction(options.PromiseImpl)) {
            throw new TypeError(errorText + '.PromiseImpl');
        }
    
        if (!isUndefined(options.constructorMixin) && !isFunction(options.constructorMixin)) {
            throw new TypeError(errorText + '.PromiseImpl');
        }
    
        var PromiseImpl = options.PromiseImpl;
        var constructorMixin = options.constructorMixin;
    
    
        var plumbing = {};
    
        plumbing.init = function (requestOptions) {
    
            var self = this;
    
            self._rp_promise = new PromiseImpl(function (resolve, reject) {
                self._rp_resolve = resolve;
                self._rp_reject = reject;
                if (constructorMixin) {
                    constructorMixin.apply(self, arguments); // Using arguments since specific Promise libraries may pass additional parameters
                }
            });
    
            self._rp_callbackOrig = requestOptions.callback;
            requestOptions.callback = self.callback = function RP$callback(err, response, body) {
                plumbing.callback.call(self, err, response, body);
            };
    
            if (isString(requestOptions.method)) {
                requestOptions.method = requestOptions.method.toUpperCase();
            }
    
            requestOptions.transform = requestOptions.transform || plumbing.defaultTransformations[requestOptions.method];
    
            self._rp_options = requestOptions;
            self._rp_options.simple = requestOptions.simple !== false;
            self._rp_options.resolveWithFullResponse = requestOptions.resolveWithFullResponse === true;
            self._rp_options.transform2xxOnly = requestOptions.transform2xxOnly === true;
    
        };
    
        plumbing.defaultTransformations = {
            HEAD: function (body, response, resolveWithFullResponse) {
                return resolveWithFullResponse ? response : response.headers;
            }
        };
    
        plumbing.callback = function (err, response, body) {
    
            var self = this;
    
            var origCallbackThrewException = false, thrownException = null;
    
            if (isFunction(self._rp_callbackOrig)) {
                try {
                    self._rp_callbackOrig.apply(self, arguments); // TODO: Apply to self mimics behavior of request@2. Is that also right for request@next?
                } catch (e) {
                    origCallbackThrewException = true;
                    thrownException = e;
                }
            }
    
            var is2xx = !err && /^2/.test('' + response.statusCode);
    
            if (err) {
    
                self._rp_reject(new errors.RequestError(err, self._rp_options, response));
    
            } else if (self._rp_options.simple && !is2xx) {
    
                if (isFunction(self._rp_options.transform) && self._rp_options.transform2xxOnly === false) {
    
                    (new PromiseImpl(function (resolve) {
                        resolve(self._rp_options.transform(body, response, self._rp_options.resolveWithFullResponse)); // transform may return a Promise
                    }))
                        .then(function (transformedResponse) {
                            self._rp_reject(new errors.StatusCodeError(response.statusCode, body, self._rp_options, transformedResponse));
                        })
                        .catch(function (transformErr) {
                            self._rp_reject(new errors.TransformError(transformErr, self._rp_options, response));
                        });
    
                } else {
                    self._rp_reject(new errors.StatusCodeError(response.statusCode, body, self._rp_options, response));
                }
    
            } else {
    
                if (isFunction(self._rp_options.transform) && (is2xx || self._rp_options.transform2xxOnly === false)) {
    
                    (new PromiseImpl(function (resolve) {
                        resolve(self._rp_options.transform(body, response, self._rp_options.resolveWithFullResponse)); // transform may return a Promise
                    }))
                        .then(function (transformedResponse) {
                            self._rp_resolve(transformedResponse);
                        })
                        .catch(function (transformErr) {
                            self._rp_reject(new errors.TransformError(transformErr, self._rp_options, response));
                        });
    
                } else if (self._rp_options.resolveWithFullResponse) {
                    self._rp_resolve(response);
                } else {
                    self._rp_resolve(body);
                }
    
            }
    
            if (origCallbackThrewException) {
                throw thrownException;
            }
    
        };
    
        plumbing.exposePromiseMethod = function (exposeTo, bindTo, promisePropertyKey, methodToExpose, exposeAs) {
    
            exposeAs = exposeAs || methodToExpose;
    
            if (exposeAs in exposeTo) {
                throw new Error('Unable to expose method "' + exposeAs + '"');
            }
    
            exposeTo[exposeAs] = function RP$exposed() {
                var self = bindTo || this;
                return self[promisePropertyKey][methodToExpose].apply(self[promisePropertyKey], arguments);
            };
    
        };
    
        plumbing.exposePromise = function (exposeTo, bindTo, promisePropertyKey, exposeAs) {
    
            exposeAs = exposeAs || 'promise';
    
            if (exposeAs in exposeTo) {
                throw new Error('Unable to expose method "' + exposeAs + '"');
            }
    
            exposeTo[exposeAs] = function RP$promise() {
                var self = bindTo || this;
                return self[promisePropertyKey];
            };
    
        };
    
        return plumbing;
    
    };