UNPKG

bluebird

Version:

Full featured Promises/A+ implementation with exceptionally good performance

196 lines (183 loc) 7.49 kB
/** * Copyright (c) 2013 Petka Antonov * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions:</p> * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ "use strict"; module.exports = function( Promise ) { var THIS = {}; var util = require( "./util.js"); var withAppended = util.withAppended; var maybeWrapAsError = util.maybeWrapAsError; var nodebackForResolver = util.nodebackForResolver; var canEvaluate = util.canEvaluate; var notEnumerableProp = util.notEnumerableProp; var deprecated = util.deprecated; var ASSERT = require( "./assert.js" ); function makeNodePromisifiedEval( callback, receiver, originalName ) { function getCall(count) { var args = new Array(count); for( var i = 0, len = args.length; i < len; ++i ) { args[i] = "a" + (i+1); } var comma = count > 0 ? "," : ""; if( typeof callback === "string" && receiver === THIS ) { return "this['" + callback + "']("+args.join(",") + comma +" fn);"+ "break;"; } return ( receiver === void 0 ? "callback("+args.join(",")+ comma +" fn);" : "callback.call("+( receiver === THIS ? "this" : "receiver" )+", "+args.join(",") + comma + " fn);" ) + "break;"; } function getArgs() { return "var args = new Array( len + 1 );" + "var i = 0;" + "for( var i = 0; i < len; ++i ) { " + " args[i] = arguments[i];" + "}" + "args[i] = fn;"; } var callbackName = ( typeof originalName === "string" ? originalName + "Async" : "promisified" ); return new Function("Promise", "callback", "receiver", "withAppended", "maybeWrapAsError", "nodebackForResolver", "var ret = function " + callbackName + "( a1, a2, a3, a4, a5 ) {\"use strict\";" + "var len = arguments.length;" + "var resolver = Promise.pending( " + callbackName + " );" + "var fn = nodebackForResolver( resolver );"+ "try{" + "switch( len ) {" + "case 1:" + getCall(1) + "case 2:" + getCall(2) + "case 3:" + getCall(3) + "case 0:" + getCall(0) + "case 4:" + getCall(4) + "case 5:" + getCall(5) + "default: " + getArgs() + (typeof callback === "string" ? "this['" + callback + "'].apply(" : "callback.apply(" ) + ( receiver === THIS ? "this" : "receiver" ) + ", args ); break;" + "}" + "}" + "catch(e){ " + "" + "resolver.reject( maybeWrapAsError( e ) );" + "}" + "return resolver.promise;" + "" + "}; ret.__isPromisified__ = true; return ret;" )(Promise, callback, receiver, withAppended, maybeWrapAsError, nodebackForResolver); } function makeNodePromisifiedClosure( callback, receiver ) { function promisified() { var _receiver = receiver; if( receiver === THIS ) _receiver = this; if( typeof callback === "string" ) { callback = _receiver[callback]; } var resolver = Promise.pending( promisified ); var fn = nodebackForResolver( resolver ); try { callback.apply( _receiver, withAppended( arguments, fn ) ); } catch(e) { resolver.reject( maybeWrapAsError( e ) ); } return resolver.promise; } promisified.__isPromisified__ = true; return promisified; } var makeNodePromisified = canEvaluate ? makeNodePromisifiedEval : makeNodePromisifiedClosure; function f(){} function isPromisified( fn ) { return fn.__isPromisified__ === true; } var hasProp = {}.hasOwnProperty; var roriginal = new RegExp( "__beforePromisified__" + "$" ); function _promisify( callback, receiver, isAll ) { if( isAll ) { var changed = 0; var o = {}; for( var key in callback ) { if( !roriginal.test( key ) && !hasProp.call( callback, ( key + "__beforePromisified__" ) ) && typeof callback[ key ] === "function" ) { var fn = callback[key]; if( !isPromisified( fn ) ) { changed++; var originalKey = key + "__beforePromisified__"; var promisifiedKey = key + "Async"; notEnumerableProp( callback, originalKey, fn ); o[ promisifiedKey ] = makeNodePromisified( originalKey, THIS, key ); } } } if( changed > 0 ) { for( var key in o ) { if( hasProp.call( o, key ) ) { callback[key] = o[key]; } } f.prototype = callback; } return callback; } else { return makeNodePromisified( callback, receiver, void 0 ); } } Promise.promisify = function Promise$Promisify( callback, receiver ) { if( typeof callback === "object" && callback !== null ) { deprecated( "Promise.promisify for promisifying entire objects " + "is deprecated. Use Promise.promisifyAll instead." ); return _promisify( callback, receiver, true ); } if( typeof callback !== "function" ) { throw new TypeError( "callback must be a function" ); } if( isPromisified( callback ) ) { return callback; } return _promisify( callback, arguments.length < 2 ? THIS : receiver, false ); }; Promise.promisifyAll = function Promise$PromisifyAll( target ) { if( typeof target !== "function" && typeof target !== "object" ) { throw new TypeError( "Cannot promisify " + typeof target ); } return _promisify( target, void 0, true ); }; };