UNPKG

3.71 kBJavaScriptView Raw
1"use strict";
2module.exports = function(Promise, PromiseArray, apiRejection, debug) {
3var util = require("./util");
4var tryCatch = util.tryCatch;
5var errorObj = util.errorObj;
6var async = Promise._async;
7
8Promise.prototype["break"] = Promise.prototype.cancel = function() {
9 if (!debug.cancellation()) return this._warn("cancellation is disabled");
10
11 var promise = this;
12 var child = promise;
13 while (promise._isCancellable()) {
14 if (!promise._cancelBy(child)) {
15 if (child._isFollowing()) {
16 child._followee().cancel();
17 } else {
18 child._cancelBranched();
19 }
20 break;
21 }
22
23 var parent = promise._cancellationParent;
24 if (parent == null || !parent._isCancellable()) {
25 if (promise._isFollowing()) {
26 promise._followee().cancel();
27 } else {
28 promise._cancelBranched();
29 }
30 break;
31 } else {
32 if (promise._isFollowing()) promise._followee().cancel();
33 promise._setWillBeCancelled();
34 child = promise;
35 promise = parent;
36 }
37 }
38};
39
40Promise.prototype._branchHasCancelled = function() {
41 this._branchesRemainingToCancel--;
42};
43
44Promise.prototype._enoughBranchesHaveCancelled = function() {
45 return this._branchesRemainingToCancel === undefined ||
46 this._branchesRemainingToCancel <= 0;
47};
48
49Promise.prototype._cancelBy = function(canceller) {
50 if (canceller === this) {
51 this._branchesRemainingToCancel = 0;
52 this._invokeOnCancel();
53 return true;
54 } else {
55 this._branchHasCancelled();
56 if (this._enoughBranchesHaveCancelled()) {
57 this._invokeOnCancel();
58 return true;
59 }
60 }
61 return false;
62};
63
64Promise.prototype._cancelBranched = function() {
65 if (this._enoughBranchesHaveCancelled()) {
66 this._cancel();
67 }
68};
69
70Promise.prototype._cancel = function() {
71 if (!this._isCancellable()) return;
72 this._setCancelled();
73 async.invoke(this._cancelPromises, this, undefined);
74};
75
76Promise.prototype._cancelPromises = function() {
77 if (this._length() > 0) this._settlePromises();
78};
79
80Promise.prototype._unsetOnCancel = function() {
81 this._onCancelField = undefined;
82};
83
84Promise.prototype._isCancellable = function() {
85 return this.isPending() && !this._isCancelled();
86};
87
88Promise.prototype.isCancellable = function() {
89 return this.isPending() && !this.isCancelled();
90};
91
92Promise.prototype._doInvokeOnCancel = function(onCancelCallback, internalOnly) {
93 if (util.isArray(onCancelCallback)) {
94 for (var i = 0; i < onCancelCallback.length; ++i) {
95 this._doInvokeOnCancel(onCancelCallback[i], internalOnly);
96 }
97 } else if (onCancelCallback !== undefined) {
98 if (typeof onCancelCallback === "function") {
99 if (!internalOnly) {
100 var e = tryCatch(onCancelCallback).call(this._boundValue());
101 if (e === errorObj) {
102 this._attachExtraTrace(e.e);
103 async.throwLater(e.e);
104 }
105 }
106 } else {
107 onCancelCallback._resultCancelled(this);
108 }
109 }
110};
111
112Promise.prototype._invokeOnCancel = function() {
113 var onCancelCallback = this._onCancel();
114 this._unsetOnCancel();
115 async.invoke(this._doInvokeOnCancel, this, onCancelCallback);
116};
117
118Promise.prototype._invokeInternalOnCancel = function() {
119 if (this._isCancellable()) {
120 this._doInvokeOnCancel(this._onCancel(), true);
121 this._unsetOnCancel();
122 }
123};
124
125Promise.prototype._resultCancelled = function() {
126 this.cancel();
127};
128
129};