Skip to content
Snippets Groups Projects
index.js 7.33 MiB
Newer Older
  • Learn to ignore specific revisions
  • Romain CREY's avatar
    Romain CREY committed
                                                                                 \n\
                return [TheName];                                                \n\
            }(tryCatch, errorObj, Promise, async);                               \n\
            ";
    
            code = code.replace(/\[TheName\]/g, name)
                .replace(/\[TheTotal\]/g, total)
                .replace(/\[ThePassedArguments\]/g, passedArguments)
                .replace(/\[TheProperties\]/g, assignment)
                .replace(/\[CancellationCode\]/g, cancellationCode);
    
            return new Function("tryCatch", "errorObj", "Promise", "async", code)
                               (tryCatch, errorObj, Promise, async);
        };
    
        var holderClasses = [];
        var thenCallbacks = [];
        var promiseSetters = [];
    
        for (var i = 0; i < 8; ++i) {
            holderClasses.push(generateHolderClass(i + 1));
            thenCallbacks.push(thenCallback(i + 1));
            promiseSetters.push(promiseSetter(i + 1));
        }
    
        reject = function (reason) {
            this._reject(reason);
        };
    }}
    
    Promise.join = function () {
        var last = arguments.length - 1;
        var fn;
        if (last > 0 && typeof arguments[last] === "function") {
            fn = arguments[last];
            if (true) {
                if (last <= 8 && canEvaluate) {
                    var ret = new Promise(INTERNAL);
                    ret._captureStackTrace();
                    var HolderClass = holderClasses[last - 1];
                    var holder = new HolderClass(fn);
                    var callbacks = thenCallbacks;
    
                    for (var i = 0; i < last; ++i) {
                        var maybePromise = tryConvertToPromise(arguments[i], ret);
                        if (maybePromise instanceof Promise) {
                            maybePromise = maybePromise._target();
                            var bitField = maybePromise._bitField;
                            ;
                            if (((bitField & 50397184) === 0)) {
                                maybePromise._then(callbacks[i], reject,
                                                   undefined, ret, holder);
                                promiseSetters[i](maybePromise, holder);
                                holder.asyncNeeded = false;
                            } else if (((bitField & 33554432) !== 0)) {
                                callbacks[i].call(ret,
                                                  maybePromise._value(), holder);
                            } else if (((bitField & 16777216) !== 0)) {
                                ret._reject(maybePromise._reason());
                            } else {
                                ret._cancel();
                            }
                        } else {
                            callbacks[i].call(ret, maybePromise, holder);
                        }
                    }
    
                    if (!ret._isFateSealed()) {
                        if (holder.asyncNeeded) {
    
                            var context = Promise._getContext();
                            holder.fn = util.contextBind(context, holder.fn);
    
    Romain CREY's avatar
    Romain CREY committed
                        }
                        ret._setAsyncGuaranteed();
                        ret._setOnCancel(holder);
                    }
                    return ret;
                }
            }
        }
    
        var $_len = arguments.length;var args = new Array($_len); for(var $_i = 0; $_i < $_len ; ++$_i) {args[$_i] = arguments[$_i ];};
    
    Romain CREY's avatar
    Romain CREY committed
        if (fn) args.pop();
        var ret = new PromiseArray(args).promise();
        return fn !== undefined ? ret.spread(fn) : ret;
    };
    
    };
    
    
    /***/ }),
    
    7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438 7439 7440 7441 7442 7443 7444 7445 7446 7447 7448 7449 7450
    /* 47 */
    /***/ (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    var cr = Object.create;
    if (cr) {
        var callerCache = cr(null);
        var getterCache = cr(null);
        callerCache[" size"] = getterCache[" size"] = 0;
    }
    
    module.exports = function(Promise) {
    var util = __webpack_require__(27);
    var canEvaluate = util.canEvaluate;
    var isIdentifier = util.isIdentifier;
    
    var getMethodCaller;
    var getGetter;
    if (true) {
    var makeMethodCaller = function (methodName) {
        return new Function("ensureMethod", "                                    \n\
            return function(obj) {                                               \n\
                'use strict'                                                     \n\
                var len = this.length;                                           \n\
                ensureMethod(obj, 'methodName');                                 \n\
                switch(len) {                                                    \n\
                    case 1: return obj.methodName(this[0]);                      \n\
                    case 2: return obj.methodName(this[0], this[1]);             \n\
                    case 3: return obj.methodName(this[0], this[1], this[2]);    \n\
                    case 0: return obj.methodName();                             \n\
                    default:                                                     \n\
                        return obj.methodName.apply(obj, this);                  \n\
                }                                                                \n\
            };                                                                   \n\
            ".replace(/methodName/g, methodName))(ensureMethod);
    };
    
    var makeGetter = function (propertyName) {
        return new Function("obj", "                                             \n\
            'use strict';                                                        \n\
            return obj.propertyName;                                             \n\
            ".replace("propertyName", propertyName));
    };
    
    var getCompiled = function(name, compiler, cache) {
        var ret = cache[name];
        if (typeof ret !== "function") {
            if (!isIdentifier(name)) {
                return null;
            }
            ret = compiler(name);
            cache[name] = ret;
            cache[" size"]++;
            if (cache[" size"] > 512) {
                var keys = Object.keys(cache);
                for (var i = 0; i < 256; ++i) delete cache[keys[i]];
                cache[" size"] = keys.length - 256;
            }
        }
        return ret;
    };
    
    getMethodCaller = function(name) {
        return getCompiled(name, makeMethodCaller, callerCache);
    };
    
    getGetter = function(name) {
        return getCompiled(name, makeGetter, getterCache);
    };
    }
    
    function ensureMethod(obj, methodName) {
        var fn;
        if (obj != null) fn = obj[methodName];
        if (typeof fn !== "function") {
            var message = "Object " + util.classString(obj) + " has no method '" +
                util.toString(methodName) + "'";
            throw new Promise.TypeError(message);
        }
        return fn;
    }
    
    function caller(obj) {
        var methodName = this.pop();
        var fn = ensureMethod(obj, methodName);
        return fn.apply(obj, this);
    }
    Promise.prototype.call = function (methodName) {
        var $_len = arguments.length;var args = new Array(Math.max($_len - 1, 0)); for(var $_i = 1; $_i < $_len; ++$_i) {args[$_i - 1] = arguments[$_i];};
        if (true) {
            if (canEvaluate) {
                var maybeCaller = getMethodCaller(methodName);
                if (maybeCaller !== null) {
                    return this._then(
                        maybeCaller, undefined, undefined, args, undefined);
                }
            }
        }
        args.push(methodName);
        return this._then(caller, undefined, undefined, args, undefined);
    };
    
    function namedGetter(obj) {
        return obj[this];
    }
    function indexedGetter(obj) {
        var index = +this;
        if (index < 0) index = Math.max(0, index + obj.length);
        return obj[index];
    }
    Promise.prototype.get = function (propertyName) {
        var isIndex = (typeof propertyName === "number");
        var getter;
        if (!isIndex) {
            if (canEvaluate) {
                var maybeGetter = getGetter(propertyName);
                getter = maybeGetter !== null ? maybeGetter : namedGetter;
            } else {
                getter = namedGetter;
            }
        } else {
            getter = indexedGetter;
        }
        return this._then(getter, undefined, undefined, propertyName, undefined);
    };
    };
    
    
    /***/ }),
    /* 48 */
    /***/ (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    module.exports = function(Promise,
                              apiRejection,
                              INTERNAL,
                              tryConvertToPromise,
                              Proxyable,
                              debug) {
    var errors = __webpack_require__(33);
    var TypeError = errors.TypeError;
    var util = __webpack_require__(27);
    var errorObj = util.errorObj;
    var tryCatch = util.tryCatch;
    var yieldHandlers = [];
    
    function promiseFromYieldHandler(value, yieldHandlers, traceParent) {
        for (var i = 0; i < yieldHandlers.length; ++i) {
            traceParent._pushContext();
            var result = tryCatch(yieldHandlers[i])(value);
            traceParent._popContext();
            if (result === errorObj) {
                traceParent._pushContext();
                var ret = Promise.reject(errorObj.e);
                traceParent._popContext();
                return ret;
            }
            var maybePromise = tryConvertToPromise(result, traceParent);
            if (maybePromise instanceof Promise) return maybePromise;
        }
        return null;
    }
    
    function PromiseSpawn(generatorFunction, receiver, yieldHandler, stack) {
        if (debug.cancellation()) {
            var internal = new Promise(INTERNAL);
            var _finallyPromise = this._finallyPromise = new Promise(INTERNAL);
            this._promise = internal.lastly(function() {
                return _finallyPromise;
            });
            internal._captureStackTrace();
            internal._setOnCancel(this);
        } else {
            var promise = this._promise = new Promise(INTERNAL);
            promise._captureStackTrace();
        }
        this._stack = stack;
        this._generatorFunction = generatorFunction;
        this._receiver = receiver;
        this._generator = undefined;
        this._yieldHandlers = typeof yieldHandler === "function"
            ? [yieldHandler].concat(yieldHandlers)
            : yieldHandlers;
        this._yieldedPromise = null;
        this._cancellationPhase = false;
    }
    util.inherits(PromiseSpawn, Proxyable);
    
    PromiseSpawn.prototype._isResolved = function() {
        return this._promise === null;
    };
    
    PromiseSpawn.prototype._cleanup = function() {
        this._promise = this._generator = null;
        if (debug.cancellation() && this._finallyPromise !== null) {
            this._finallyPromise._fulfill();
            this._finallyPromise = null;
        }
    };
    
    PromiseSpawn.prototype._promiseCancelled = function() {
        if (this._isResolved()) return;
        var implementsReturn = typeof this._generator["return"] !== "undefined";
    
        var result;
        if (!implementsReturn) {
            var reason = new Promise.CancellationError(
                "generator .return() sentinel");
            Promise.coroutine.returnSentinel = reason;
            this._promise._attachExtraTrace(reason);
            this._promise._pushContext();
            result = tryCatch(this._generator["throw"]).call(this._generator,
                                                             reason);
            this._promise._popContext();
        } else {
            this._promise._pushContext();
            result = tryCatch(this._generator["return"]).call(this._generator,
                                                              undefined);
            this._promise._popContext();
        }
        this._cancellationPhase = true;
        this._yieldedPromise = null;
        this._continue(result);
    };
    
    PromiseSpawn.prototype._promiseFulfilled = function(value) {
        this._yieldedPromise = null;
        this._promise._pushContext();
        var result = tryCatch(this._generator.next).call(this._generator, value);
        this._promise._popContext();
        this._continue(result);
    };
    
    PromiseSpawn.prototype._promiseRejected = function(reason) {
        this._yieldedPromise = null;
        this._promise._attachExtraTrace(reason);
        this._promise._pushContext();
        var result = tryCatch(this._generator["throw"])
            .call(this._generator, reason);
        this._promise._popContext();
        this._continue(result);
    };
    
    PromiseSpawn.prototype._resultCancelled = function() {
        if (this._yieldedPromise instanceof Promise) {
            var promise = this._yieldedPromise;
            this._yieldedPromise = null;
            promise.cancel();
        }
    };
    
    PromiseSpawn.prototype.promise = function () {
        return this._promise;
    };
    
    PromiseSpawn.prototype._run = function () {
        this._generator = this._generatorFunction.call(this._receiver);
        this._receiver =
            this._generatorFunction = undefined;
        this._promiseFulfilled(undefined);
    };
    
    PromiseSpawn.prototype._continue = function (result) {
        var promise = this._promise;
        if (result === errorObj) {
            this._cleanup();
            if (this._cancellationPhase) {
                return promise.cancel();
            } else {
                return promise._rejectCallback(result.e, false);
            }
        }
    
        var value = result.value;
        if (result.done === true) {
            this._cleanup();
            if (this._cancellationPhase) {
                return promise.cancel();
            } else {
                return promise._resolveCallback(value);
            }
        } else {
            var maybePromise = tryConvertToPromise(value, this._promise);
            if (!(maybePromise instanceof Promise)) {
                maybePromise =
                    promiseFromYieldHandler(maybePromise,
                                            this._yieldHandlers,
                                            this._promise);
                if (maybePromise === null) {
                    this._promiseRejected(
                        new TypeError(
                            "A value %s was yielded that could not be treated as a promise\u000a\u000a    See http://goo.gl/MqrFmX\u000a\u000a".replace("%s", String(value)) +
                            "From coroutine:\u000a" +
                            this._stack.split("\n").slice(1, -7).join("\n")
                        )
                    );
                    return;
                }
            }
            maybePromise = maybePromise._target();
            var bitField = maybePromise._bitField;
            ;
            if (((bitField & 50397184) === 0)) {
                this._yieldedPromise = maybePromise;
                maybePromise._proxy(this, null);
            } else if (((bitField & 33554432) !== 0)) {
                Promise._async.invoke(
                    this._promiseFulfilled, this, maybePromise._value()
                );
            } else if (((bitField & 16777216) !== 0)) {
                Promise._async.invoke(
                    this._promiseRejected, this, maybePromise._reason()
                );
            } else {
                this._promiseCancelled();
            }
        }
    };
    
    Promise.coroutine = function (generatorFunction, options) {
        if (typeof generatorFunction !== "function") {
            throw new TypeError("generatorFunction must be a function\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
        }
        var yieldHandler = Object(options).yieldHandler;
        var PromiseSpawn$ = PromiseSpawn;
        var stack = new Error().stack;
        return function () {
            var generator = generatorFunction.apply(this, arguments);
            var spawn = new PromiseSpawn$(undefined, undefined, yieldHandler,
                                          stack);
            var ret = spawn.promise();
            spawn._generator = generator;
            spawn._promiseFulfilled(undefined);
            return ret;
        };
    };
    
    Promise.coroutine.addYieldHandler = function(fn) {
        if (typeof fn !== "function") {
            throw new TypeError("expecting a function but got " + util.classString(fn));
        }
        yieldHandlers.push(fn);
    };
    
    Promise.spawn = function (generatorFunction) {
        debug.deprecated("Promise.spawn()", "Promise.coroutine()");
        if (typeof generatorFunction !== "function") {
            return apiRejection("generatorFunction must be a function\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
        }
        var spawn = new PromiseSpawn(generatorFunction, this);
        var ret = spawn.promise();
        spawn._run(Promise.spawn);
        return ret;
    };
    };
    
    
    /***/ }),
    /* 49 */
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    module.exports = function(Promise,
                              PromiseArray,
                              apiRejection,
                              tryConvertToPromise,
                              INTERNAL,
                              debug) {
    
    var util = __webpack_require__(27);
    
    Romain CREY's avatar
    Romain CREY committed
    var tryCatch = util.tryCatch;
    var errorObj = util.errorObj;
    var async = Promise._async;
    
    function MappingPromiseArray(promises, fn, limit, _filter) {
        this.constructor$(promises);
        this._promise._captureStackTrace();
    
        var context = Promise._getContext();
        this._callback = util.contextBind(context, fn);
    
    Romain CREY's avatar
    Romain CREY committed
        this._preservedValues = _filter === INTERNAL
            ? new Array(this.length())
            : null;
        this._limit = limit;
        this._inFlight = 0;
        this._queue = [];
        async.invoke(this._asyncInit, this, undefined);
    
        if (util.isArray(promises)) {
            for (var i = 0; i < promises.length; ++i) {
                var maybePromise = promises[i];
                if (maybePromise instanceof Promise) {
                    maybePromise.suppressUnhandledRejections();
                }
            }
        }
    
    Romain CREY's avatar
    Romain CREY committed
    }
    util.inherits(MappingPromiseArray, PromiseArray);
    
    MappingPromiseArray.prototype._asyncInit = function() {
        this._init$(undefined, -2);
    };
    
    MappingPromiseArray.prototype._init = function () {};
    
    MappingPromiseArray.prototype._promiseFulfilled = function (value, index) {
        var values = this._values;
        var length = this.length();
        var preservedValues = this._preservedValues;
        var limit = this._limit;
    
        if (index < 0) {
            index = (index * -1) - 1;
            values[index] = value;
            if (limit >= 1) {
                this._inFlight--;
                this._drainQueue();
                if (this._isResolved()) return true;
            }
        } else {
            if (limit >= 1 && this._inFlight >= limit) {
                values[index] = value;
                this._queue.push(index);
                return false;
            }
            if (preservedValues !== null) preservedValues[index] = value;
    
            var promise = this._promise;
            var callback = this._callback;
            var receiver = promise._boundValue();
            promise._pushContext();
            var ret = tryCatch(callback).call(receiver, value, index, length);
            var promiseCreated = promise._popContext();
            debug.checkForgottenReturns(
                ret,
                promiseCreated,
                preservedValues !== null ? "Promise.filter" : "Promise.map",
                promise
            );
            if (ret === errorObj) {
                this._reject(ret.e);
                return true;
            }
    
            var maybePromise = tryConvertToPromise(ret, this._promise);
            if (maybePromise instanceof Promise) {
                maybePromise = maybePromise._target();
                var bitField = maybePromise._bitField;
                ;
                if (((bitField & 50397184) === 0)) {
                    if (limit >= 1) this._inFlight++;
                    values[index] = maybePromise;
                    maybePromise._proxy(this, (index + 1) * -1);
                    return false;
                } else if (((bitField & 33554432) !== 0)) {
                    ret = maybePromise._value();
                } else if (((bitField & 16777216) !== 0)) {
                    this._reject(maybePromise._reason());
                    return true;
                } else {
                    this._cancel();
                    return true;
                }
            }
            values[index] = ret;
        }
        var totalResolved = ++this._totalResolved;
        if (totalResolved >= length) {
            if (preservedValues !== null) {
                this._filter(values, preservedValues);
            } else {
                this._resolve(values);
            }
            return true;
        }
        return false;
    };
    
    MappingPromiseArray.prototype._drainQueue = function () {
        var queue = this._queue;
        var limit = this._limit;
        var values = this._values;
        while (queue.length > 0 && this._inFlight < limit) {
            if (this._isResolved()) return;
            var index = queue.pop();
            this._promiseFulfilled(values[index], index);
        }
    };
    
    MappingPromiseArray.prototype._filter = function (booleans, values) {
        var len = values.length;
        var ret = new Array(len);
        var j = 0;
        for (var i = 0; i < len; ++i) {
            if (booleans[i]) ret[j++] = values[i];
        }
        ret.length = j;
        this._resolve(ret);
    };
    
    MappingPromiseArray.prototype.preservedValues = function () {
        return this._preservedValues;
    };
    
    function map(promises, fn, options, _filter) {
        if (typeof fn !== "function") {
            return apiRejection("expecting a function but got " + util.classString(fn));
        }
    
        var limit = 0;
        if (options !== undefined) {
            if (typeof options === "object" && options !== null) {
                if (typeof options.concurrency !== "number") {
                    return Promise.reject(
                        new TypeError("'concurrency' must be a number but it is " +
                                        util.classString(options.concurrency)));
                }
                limit = options.concurrency;
            } else {
                return Promise.reject(new TypeError(
                                "options argument must be an object but it is " +
                                 util.classString(options)));
            }
        }
        limit = typeof limit === "number" &&
            isFinite(limit) && limit >= 1 ? limit : 0;
        return new MappingPromiseArray(promises, fn, limit, _filter).promise();
    }
    
    Promise.prototype.map = function (fn, options) {
        return map(this, fn, options, null);
    };
    
    Promise.map = function (promises, fn, options, _filter) {
        return map(promises, fn, options, _filter);
    };
    
    
    };
    
    
    /***/ }),
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    module.exports = function(Promise) {
    
    var util = __webpack_require__(27);
    
    Romain CREY's avatar
    Romain CREY committed
    var async = Promise._async;
    var tryCatch = util.tryCatch;
    var errorObj = util.errorObj;
    
    function spreadAdapter(val, nodeback) {
        var promise = this;
        if (!util.isArray(val)) return successAdapter.call(promise, val, nodeback);
        var ret =
            tryCatch(nodeback).apply(promise._boundValue(), [null].concat(val));
        if (ret === errorObj) {
            async.throwLater(ret.e);
        }
    }
    
    function successAdapter(val, nodeback) {
        var promise = this;
        var receiver = promise._boundValue();
        var ret = val === undefined
            ? tryCatch(nodeback).call(receiver, null)
            : tryCatch(nodeback).call(receiver, null, val);
        if (ret === errorObj) {
            async.throwLater(ret.e);
        }
    }
    function errorAdapter(reason, nodeback) {
        var promise = this;
        if (!reason) {
            var newReason = new Error(reason + "");
            newReason.cause = reason;
            reason = newReason;
        }
        var ret = tryCatch(nodeback).call(promise._boundValue(), reason);
        if (ret === errorObj) {
            async.throwLater(ret.e);
        }
    }
    
    Promise.prototype.asCallback = Promise.prototype.nodeify = function (nodeback,
                                                                         options) {
        if (typeof nodeback == "function") {
            var adapter = successAdapter;
            if (options !== undefined && Object(options).spread) {
                adapter = spreadAdapter;
            }
            this._then(
                adapter,
                errorAdapter,
                undefined,
                this,
                nodeback
            );
        }
        return this;
    };
    };
    
    
    /***/ }),
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    module.exports = function(Promise, INTERNAL) {
    var THIS = {};
    
    var util = __webpack_require__(27);
    
    var nodebackForPromise = __webpack_require__(40);
    
    Romain CREY's avatar
    Romain CREY committed
    var withAppended = util.withAppended;
    var maybeWrapAsError = util.maybeWrapAsError;
    var canEvaluate = util.canEvaluate;
    
    var TypeError = __webpack_require__(33).TypeError;
    
    Romain CREY's avatar
    Romain CREY committed
    var defaultSuffix = "Async";
    var defaultPromisified = {__isPromisified__: true};
    var noCopyProps = [
        "arity",    "length",
        "name",
        "arguments",
        "caller",
        "callee",
        "prototype",
        "__isPromisified__"
    ];
    var noCopyPropsPattern = new RegExp("^(?:" + noCopyProps.join("|") + ")$");
    
    var defaultFilter = function(name) {
        return util.isIdentifier(name) &&
            name.charAt(0) !== "_" &&
            name !== "constructor";
    };
    
    function propsFilter(key) {
        return !noCopyPropsPattern.test(key);
    }
    
    function isPromisified(fn) {
        try {
            return fn.__isPromisified__ === true;
        }
        catch (e) {
            return false;
        }
    }
    
    function hasPromisified(obj, key, suffix) {
        var val = util.getDataPropertyOrDefault(obj, key + suffix,
                                                defaultPromisified);
        return val ? isPromisified(val) : false;
    }
    function checkValid(ret, suffix, suffixRegexp) {
        for (var i = 0; i < ret.length; i += 2) {
            var key = ret[i];
            if (suffixRegexp.test(key)) {
                var keyWithoutAsyncSuffix = key.replace(suffixRegexp, "");
                for (var j = 0; j < ret.length; j += 2) {
                    if (ret[j] === keyWithoutAsyncSuffix) {
                        throw new TypeError("Cannot promisify an API that has normal methods with '%s'-suffix\u000a\u000a    See http://goo.gl/MqrFmX\u000a"
                            .replace("%s", suffix));
                    }
                }
            }
        }
    }
    
    function promisifiableMethods(obj, suffix, suffixRegexp, filter) {
        var keys = util.inheritedDataKeys(obj);
        var ret = [];
        for (var i = 0; i < keys.length; ++i) {
            var key = keys[i];
            var value = obj[key];
            var passesDefaultFilter = filter === defaultFilter
                ? true : defaultFilter(key, value, obj);
            if (typeof value === "function" &&
                !isPromisified(value) &&
                !hasPromisified(obj, key, suffix) &&
                filter(key, value, obj, passesDefaultFilter)) {
                ret.push(key, value);
            }
        }
        checkValid(ret, suffix, suffixRegexp);
        return ret;
    }
    
    var escapeIdentRegex = function(str) {
        return str.replace(/([$])/, "\\$");
    };
    
    var makeNodePromisifiedEval;
    if (true) {
    var switchCaseArgumentOrder = function(likelyArgumentCount) {
        var ret = [likelyArgumentCount];
        var min = Math.max(0, likelyArgumentCount - 1 - 3);
        for(var i = likelyArgumentCount - 1; i >= min; --i) {
            ret.push(i);
        }
        for(var i = likelyArgumentCount + 1; i <= 3; ++i) {
            ret.push(i);
        }
        return ret;
    };
    
    var argumentSequence = function(argumentCount) {
        return util.filledRange(argumentCount, "_arg", "");
    };
    
    var parameterDeclaration = function(parameterCount) {
        return util.filledRange(
            Math.max(parameterCount, 3), "_arg", "");
    };
    
    var parameterCount = function(fn) {
        if (typeof fn.length === "number") {
            return Math.max(Math.min(fn.length, 1023 + 1), 0);
        }
        return 0;
    };
    
    makeNodePromisifiedEval =
    function(callback, receiver, originalName, fn, _, multiArgs) {
        var newParameterCount = Math.max(0, parameterCount(fn) - 1);
        var argumentOrder = switchCaseArgumentOrder(newParameterCount);
        var shouldProxyThis = typeof callback === "string" || receiver === THIS;
    
        function generateCallForArgumentCount(count) {
            var args = argumentSequence(count).join(", ");
            var comma = count > 0 ? ", " : "";
            var ret;
            if (shouldProxyThis) {
                ret = "ret = callback.call(this, {{args}}, nodeback); break;\n";
            } else {
                ret = receiver === undefined
                    ? "ret = callback({{args}}, nodeback); break;\n"
                    : "ret = callback.call(receiver, {{args}}, nodeback); break;\n";
            }
            return ret.replace("{{args}}", args).replace(", ", comma);
        }
    
        function generateArgumentSwitchCase() {
            var ret = "";
            for (var i = 0; i < argumentOrder.length; ++i) {
                ret += "case " + argumentOrder[i] +":" +
                    generateCallForArgumentCount(argumentOrder[i]);
            }
    
            ret += "                                                             \n\
            default:                                                             \n\
                var args = new Array(len + 1);                                   \n\
                var i = 0;                                                       \n\
                for (var i = 0; i < len; ++i) {                                  \n\
                   args[i] = arguments[i];                                       \n\
                }                                                                \n\
                args[i] = nodeback;                                              \n\
                [CodeForCall]                                                    \n\
                break;                                                           \n\
            ".replace("[CodeForCall]", (shouldProxyThis
                                    ? "ret = callback.apply(this, args);\n"
                                    : "ret = callback.apply(receiver, args);\n"));
            return ret;
        }
    
        var getFunctionCode = typeof callback === "string"
                                    ? ("this != null ? this['"+callback+"'] : fn")
                                    : "fn";
        var body = "'use strict';                                                \n\
            var ret = function (Parameters) {                                    \n\
                'use strict';                                                    \n\
                var len = arguments.length;                                      \n\
                var promise = new Promise(INTERNAL);                             \n\
                promise._captureStackTrace();                                    \n\
                var nodeback = nodebackForPromise(promise, " + multiArgs + ");   \n\
                var ret;                                                         \n\
                var callback = tryCatch([GetFunctionCode]);                      \n\
                switch(len) {                                                    \n\
                    [CodeForSwitchCase]                                          \n\
                }                                                                \n\
                if (ret === errorObj) {                                          \n\
                    promise._rejectCallback(maybeWrapAsError(ret.e), true, true);\n\
                }                                                                \n\
                if (!promise._isFateSealed()) promise._setAsyncGuaranteed();     \n\
                return promise;                                                  \n\
            };                                                                   \n\
            notEnumerableProp(ret, '__isPromisified__', true);                   \n\
            return ret;                                                          \n\
        ".replace("[CodeForSwitchCase]", generateArgumentSwitchCase())
            .replace("[GetFunctionCode]", getFunctionCode);
        body = body.replace("Parameters", parameterDeclaration(newParameterCount));
        return new Function("Promise",
                            "fn",
                            "receiver",
                            "withAppended",
                            "maybeWrapAsError",
                            "nodebackForPromise",
                            "tryCatch",
                            "errorObj",
                            "notEnumerableProp",
                            "INTERNAL",
                            body)(
                        Promise,
                        fn,
                        receiver,
                        withAppended,
                        maybeWrapAsError,
                        nodebackForPromise,
                        util.tryCatch,
                        util.errorObj,
                        util.notEnumerableProp,
                        INTERNAL);
    };
    }
    
    function makeNodePromisifiedClosure(callback, receiver, _, fn, __, multiArgs) {
        var defaultThis = (function() {return this;})();
        var method = callback;
        if (typeof method === "string") {
            callback = fn;
        }
        function promisified() {
            var _receiver = receiver;
            if (receiver === THIS) _receiver = this;
            var promise = new Promise(INTERNAL);
            promise._captureStackTrace();
            var cb = typeof method === "string" && this !== defaultThis
                ? this[method] : callback;
            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);