You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					130 lines
				
				3.6 KiB
			
		
		
			
		
	
	
					130 lines
				
				3.6 KiB
			| 
											3 years ago
										 | "use strict"; | ||
|  | module.exports = function(Promise, PromiseArray, apiRejection, debug) { | ||
|  | var util = require("./util"); | ||
|  | var tryCatch = util.tryCatch; | ||
|  | var errorObj = util.errorObj; | ||
|  | var async = Promise._async; | ||
|  | 
 | ||
|  | Promise.prototype["break"] = Promise.prototype.cancel = function() { | ||
|  |     if (!debug.cancellation()) return this._warn("cancellation is disabled"); | ||
|  | 
 | ||
|  |     var promise = this; | ||
|  |     var child = promise; | ||
|  |     while (promise._isCancellable()) { | ||
|  |         if (!promise._cancelBy(child)) { | ||
|  |             if (child._isFollowing()) { | ||
|  |                 child._followee().cancel(); | ||
|  |             } else { | ||
|  |                 child._cancelBranched(); | ||
|  |             } | ||
|  |             break; | ||
|  |         } | ||
|  | 
 | ||
|  |         var parent = promise._cancellationParent; | ||
|  |         if (parent == null || !parent._isCancellable()) { | ||
|  |             if (promise._isFollowing()) { | ||
|  |                 promise._followee().cancel(); | ||
|  |             } else { | ||
|  |                 promise._cancelBranched(); | ||
|  |             } | ||
|  |             break; | ||
|  |         } else { | ||
|  |             if (promise._isFollowing()) promise._followee().cancel(); | ||
|  |             promise._setWillBeCancelled(); | ||
|  |             child = promise; | ||
|  |             promise = parent; | ||
|  |         } | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | Promise.prototype._branchHasCancelled = function() { | ||
|  |     this._branchesRemainingToCancel--; | ||
|  | }; | ||
|  | 
 | ||
|  | Promise.prototype._enoughBranchesHaveCancelled = function() { | ||
|  |     return this._branchesRemainingToCancel === undefined || | ||
|  |            this._branchesRemainingToCancel <= 0; | ||
|  | }; | ||
|  | 
 | ||
|  | Promise.prototype._cancelBy = function(canceller) { | ||
|  |     if (canceller === this) { | ||
|  |         this._branchesRemainingToCancel = 0; | ||
|  |         this._invokeOnCancel(); | ||
|  |         return true; | ||
|  |     } else { | ||
|  |         this._branchHasCancelled(); | ||
|  |         if (this._enoughBranchesHaveCancelled()) { | ||
|  |             this._invokeOnCancel(); | ||
|  |             return true; | ||
|  |         } | ||
|  |     } | ||
|  |     return false; | ||
|  | }; | ||
|  | 
 | ||
|  | Promise.prototype._cancelBranched = function() { | ||
|  |     if (this._enoughBranchesHaveCancelled()) { | ||
|  |         this._cancel(); | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | Promise.prototype._cancel = function() { | ||
|  |     if (!this._isCancellable()) return; | ||
|  |     this._setCancelled(); | ||
|  |     async.invoke(this._cancelPromises, this, undefined); | ||
|  | }; | ||
|  | 
 | ||
|  | Promise.prototype._cancelPromises = function() { | ||
|  |     if (this._length() > 0) this._settlePromises(); | ||
|  | }; | ||
|  | 
 | ||
|  | Promise.prototype._unsetOnCancel = function() { | ||
|  |     this._onCancelField = undefined; | ||
|  | }; | ||
|  | 
 | ||
|  | Promise.prototype._isCancellable = function() { | ||
|  |     return this.isPending() && !this._isCancelled(); | ||
|  | }; | ||
|  | 
 | ||
|  | Promise.prototype.isCancellable = function() { | ||
|  |     return this.isPending() && !this.isCancelled(); | ||
|  | }; | ||
|  | 
 | ||
|  | Promise.prototype._doInvokeOnCancel = function(onCancelCallback, internalOnly) { | ||
|  |     if (util.isArray(onCancelCallback)) { | ||
|  |         for (var i = 0; i < onCancelCallback.length; ++i) { | ||
|  |             this._doInvokeOnCancel(onCancelCallback[i], internalOnly); | ||
|  |         } | ||
|  |     } else if (onCancelCallback !== undefined) { | ||
|  |         if (typeof onCancelCallback === "function") { | ||
|  |             if (!internalOnly) { | ||
|  |                 var e = tryCatch(onCancelCallback).call(this._boundValue()); | ||
|  |                 if (e === errorObj) { | ||
|  |                     this._attachExtraTrace(e.e); | ||
|  |                     async.throwLater(e.e); | ||
|  |                 } | ||
|  |             } | ||
|  |         } else { | ||
|  |             onCancelCallback._resultCancelled(this); | ||
|  |         } | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | Promise.prototype._invokeOnCancel = function() { | ||
|  |     var onCancelCallback = this._onCancel(); | ||
|  |     this._unsetOnCancel(); | ||
|  |     async.invoke(this._doInvokeOnCancel, this, onCancelCallback); | ||
|  | }; | ||
|  | 
 | ||
|  | Promise.prototype._invokeInternalOnCancel = function() { | ||
|  |     if (this._isCancellable()) { | ||
|  |         this._doInvokeOnCancel(this._onCancel(), true); | ||
|  |         this._unsetOnCancel(); | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | Promise.prototype._resultCancelled = function() { | ||
|  |     this.cancel(); | ||
|  | }; | ||
|  | 
 | ||
|  | }; |