You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							314 lines
						
					
					
						
							12 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							314 lines
						
					
					
						
							12 KiB
						
					
					
				
								"use strict";
							 | 
						|
								module.exports = function(Promise, INTERNAL) {
							 | 
						|
								var THIS = {};
							 | 
						|
								var util = require("./util");
							 | 
						|
								var nodebackForPromise = require("./nodeback");
							 | 
						|
								var withAppended = util.withAppended;
							 | 
						|
								var maybeWrapAsError = util.maybeWrapAsError;
							 | 
						|
								var canEvaluate = util.canEvaluate;
							 | 
						|
								var TypeError = require("./errors").TypeError;
							 | 
						|
								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 (!false) {
							 | 
						|
								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);
							 | 
						|
								    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);
							 | 
						|
								};
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 |