2 module.exports = function(Promise, tryConvertToPromise) {
3 var util = require("./util");
4 var CancellationError = Promise.CancellationError;
5 var errorObj = util.errorObj;
7 function PassThroughHandlerContext(promise, type, handler) {
8 this.promise = promise;
10 this.handler = handler;
12 this.cancelPromise = null;
15 function FinallyHandlerCancelReaction(finallyHandler) {
16 this.finallyHandler = finallyHandler;
19 FinallyHandlerCancelReaction.prototype._resultCancelled = function() {
20 checkCancel(this.finallyHandler);
23 function checkCancel(ctx, reason) {
24 if (ctx.cancelPromise != null) {
25 if (arguments.length > 1) {
26 ctx.cancelPromise._reject(reason);
28 ctx.cancelPromise._cancel();
30 ctx.cancelPromise = null;
37 return finallyHandler.call(this, this.promise._target()._settledValue());
39 function fail(reason) {
40 if (checkCancel(this, reason)) return;
44 function finallyHandler(reasonOrValue) {
45 var promise = this.promise;
46 var handler = this.handler;
50 var ret = this.type === 0
51 ? handler.call(promise._boundValue())
52 : handler.call(promise._boundValue(), reasonOrValue);
53 if (ret !== undefined) {
54 promise._setReturnedNonUndefined();
55 var maybePromise = tryConvertToPromise(ret, promise);
56 if (maybePromise instanceof Promise) {
57 if (this.cancelPromise != null) {
58 if (maybePromise.isCancelled()) {
60 new CancellationError("late cancellation observer");
61 promise._attachExtraTrace(reason);
64 } else if (maybePromise.isPending()) {
65 maybePromise._attachCancellationCallback(
66 new FinallyHandlerCancelReaction(this));
69 return maybePromise._then(
70 succeed, fail, undefined, this, undefined);
75 if (promise.isRejected()) {
77 errorObj.e = reasonOrValue;
85 Promise.prototype._passThrough = function(handler, type, success, fail) {
86 if (typeof handler !== "function") return this.then();
87 return this._then(success,
90 new PassThroughHandlerContext(this, type, handler),
94 Promise.prototype.lastly =
95 Promise.prototype["finally"] = function (handler) {
96 return this._passThrough(handler,
102 Promise.prototype.tap = function (handler) {
103 return this._passThrough(handler, 1, finallyHandler);
106 return PassThroughHandlerContext;