Spaces:
Sleeping
Sleeping
| ; | |
| 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; | |
| }; | |