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.
		
		
		
		
		
			
		
			
				
					147 lines
				
				4.5 KiB
			
		
		
			
		
	
	
					147 lines
				
				4.5 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								"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;
							 | 
						||
| 
								 | 
							
								};
							 |