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.
		
		
		
		
		
			
		
			
				
					
					
						
							315 lines
						
					
					
						
							12 KiB
						
					
					
				
			
		
		
	
	
							315 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);
 | 
						|
};
 | 
						|
};
 | 
						|
 |