147 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			147 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
"use strict";
 | 
						|
module.exports = function(Promise, tryConvertToPromise, NEXT_FILTER) {
 | 
						|
var util = require("./util");
 | 
						|
var CancellationError = Promise.CancellationError;
 | 
						|
var errorObj = util.errorObj;
 | 
						|
var catchFilter = require("./catch_filter")(NEXT_FILTER);
 | 
						|
 | 
						|
function PassThroughHandlerContext(promise, type, handler) {
 | 
						|
    this.promise = promise;
 | 
						|
    this.type = type;
 | 
						|
    this.handler = handler;
 | 
						|
    this.called = false;
 | 
						|
    this.cancelPromise = null;
 | 
						|
}
 | 
						|
 | 
						|
PassThroughHandlerContext.prototype.isFinallyHandler = function() {
 | 
						|
    return this.type === 0;
 | 
						|
};
 | 
						|
 | 
						|
function FinallyHandlerCancelReaction(finallyHandler) {
 | 
						|
    this.finallyHandler = finallyHandler;
 | 
						|
}
 | 
						|
 | 
						|
FinallyHandlerCancelReaction.prototype._resultCancelled = function() {
 | 
						|
    checkCancel(this.finallyHandler);
 | 
						|
};
 | 
						|
 | 
						|
function checkCancel(ctx, reason) {
 | 
						|
    if (ctx.cancelPromise != null) {
 | 
						|
        if (arguments.length > 1) {
 | 
						|
            ctx.cancelPromise._reject(reason);
 | 
						|
        } else {
 | 
						|
            ctx.cancelPromise._cancel();
 | 
						|
        }
 | 
						|
        ctx.cancelPromise = null;
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
function succeed() {
 | 
						|
    return finallyHandler.call(this, this.promise._target()._settledValue());
 | 
						|
}
 | 
						|
function fail(reason) {
 | 
						|
    if (checkCancel(this, reason)) return;
 | 
						|
    errorObj.e = reason;
 | 
						|
    return errorObj;
 | 
						|
}
 | 
						|
function finallyHandler(reasonOrValue) {
 | 
						|
    var promise = this.promise;
 | 
						|
    var handler = this.handler;
 | 
						|
 | 
						|
    if (!this.called) {
 | 
						|
        this.called = true;
 | 
						|
        var ret = this.isFinallyHandler()
 | 
						|
            ? handler.call(promise._boundValue())
 | 
						|
            : handler.call(promise._boundValue(), reasonOrValue);
 | 
						|
        if (ret === NEXT_FILTER) {
 | 
						|
            return ret;
 | 
						|
        } else if (ret !== undefined) {
 | 
						|
            promise._setReturnedNonUndefined();
 | 
						|
            var maybePromise = tryConvertToPromise(ret, promise);
 | 
						|
            if (maybePromise instanceof Promise) {
 | 
						|
                if (this.cancelPromise != null) {
 | 
						|
                    if (maybePromise._isCancelled()) {
 | 
						|
                        var reason =
 | 
						|
                            new CancellationError("late cancellation observer");
 | 
						|
                        promise._attachExtraTrace(reason);
 | 
						|
                        errorObj.e = reason;
 | 
						|
                        return errorObj;
 | 
						|
                    } else if (maybePromise.isPending()) {
 | 
						|
                        maybePromise._attachCancellationCallback(
 | 
						|
                            new FinallyHandlerCancelReaction(this));
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                return maybePromise._then(
 | 
						|
                    succeed, fail, undefined, this, undefined);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (promise.isRejected()) {
 | 
						|
        checkCancel(this);
 | 
						|
        errorObj.e = reasonOrValue;
 | 
						|
        return errorObj;
 | 
						|
    } else {
 | 
						|
        checkCancel(this);
 | 
						|
        return reasonOrValue;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
Promise.prototype._passThrough = function(handler, type, success, fail) {
 | 
						|
    if (typeof handler !== "function") return this.then();
 | 
						|
    return this._then(success,
 | 
						|
                      fail,
 | 
						|
                      undefined,
 | 
						|
                      new PassThroughHandlerContext(this, type, handler),
 | 
						|
                      undefined);
 | 
						|
};
 | 
						|
 | 
						|
Promise.prototype.lastly =
 | 
						|
Promise.prototype["finally"] = function (handler) {
 | 
						|
    return this._passThrough(handler,
 | 
						|
                             0,
 | 
						|
                             finallyHandler,
 | 
						|
                             finallyHandler);
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
Promise.prototype.tap = function (handler) {
 | 
						|
    return this._passThrough(handler, 1, finallyHandler);
 | 
						|
};
 | 
						|
 | 
						|
Promise.prototype.tapCatch = function (handlerOrPredicate) {
 | 
						|
    var len = arguments.length;
 | 
						|
    if(len === 1) {
 | 
						|
        return this._passThrough(handlerOrPredicate,
 | 
						|
                                 1,
 | 
						|
                                 undefined,
 | 
						|
                                 finallyHandler);
 | 
						|
    } else {
 | 
						|
         var catchInstances = new Array(len - 1),
 | 
						|
            j = 0, i;
 | 
						|
        for (i = 0; i < len - 1; ++i) {
 | 
						|
            var item = arguments[i];
 | 
						|
            if (util.isObject(item)) {
 | 
						|
                catchInstances[j++] = item;
 | 
						|
            } else {
 | 
						|
                return Promise.reject(new TypeError(
 | 
						|
                    "tapCatch statement predicate: "
 | 
						|
                    + "expecting an object but got " + util.classString(item)
 | 
						|
                ));
 | 
						|
            }
 | 
						|
        }
 | 
						|
        catchInstances.length = j;
 | 
						|
        var handler = arguments[i];
 | 
						|
        return this._passThrough(catchFilter(catchInstances, handler, this),
 | 
						|
                                 1,
 | 
						|
                                 undefined,
 | 
						|
                                 finallyHandler);
 | 
						|
    }
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
return PassThroughHandlerContext;
 | 
						|
};
 |