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