| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 | 
							- "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;
 
- };
 
 
  |