Permalink
Browse files

fixes #1187

  • Loading branch information...
1 parent 637ea7a commit 77f77116c16893d7326a51ec5b9bb7b800716ea7 @petkaantonov committed Aug 24, 2016
Showing with 41 additions and 17 deletions.
  1. +2 −1 .jshintrc
  2. +10 −6 src/cancel.js
  3. +3 −2 src/constants.js
  4. +3 −3 src/debuggability.js
  5. +1 −1 src/finally.js
  6. +4 −0 src/promise.js
  7. +1 −1 src/promise_array.js
  8. +10 −3 src/synchronous_inspection.js
  9. +7 −0 test/mocha/cancel.js
View
@@ -93,14 +93,15 @@
"IS_FOLLOWING": false,
"IS_FULFILLED": false,
"IS_REJECTED": false,
- "IS_CANCELLABLE": false,
+ "WILL_BE_CANCELLED": false,
"IS_FINAL": false,
"IS_BOUND": false,
"IS_REJECTION_UNHANDLED": false,
"IS_REJECTION_IGNORED": false,
"IS_UNHANDLED_REJECTION_NOTIFIED": false,
"IS_DISPOSABLE": false,
"IS_CANCELLED": false,
+ "IS_CANCELLED_OR_WILL_BE_CANCELLED": false,
"LENGTH_MASK": false,
"LENGTH_CLEAR_MASK": false,
"MAX_LENGTH": false,
View
@@ -11,7 +11,7 @@ Promise.prototype["break"] = Promise.prototype.cancel = function() {
var promise = this;
var child = promise;
- while (promise.isCancellable()) {
+ while (promise._isCancellable()) {
if (!promise._cancelBy(child)) {
if (child._isFollowing()) {
child._followee().cancel();
@@ -22,7 +22,7 @@ Promise.prototype["break"] = Promise.prototype.cancel = function() {
}
var parent = promise._cancellationParent;
- if (parent == null || !parent.isCancellable()) {
+ if (parent == null || !parent._isCancellable()) {
if (promise._isFollowing()) {
promise._followee().cancel();
} else {
@@ -31,6 +31,7 @@ Promise.prototype["break"] = Promise.prototype.cancel = function() {
break;
} else {
if (promise._isFollowing()) promise._followee().cancel();
+ promise._setWillBeCancelled();
child = promise;
promise = parent;
}
@@ -70,8 +71,7 @@ Promise.prototype._cancelBranched = function() {
};
Promise.prototype._cancel = function() {
- if (!this.isCancellable()) return;
-
+ if (!this._isCancellable()) return;
ASSERT(!this._isFollowing());
this._setCancelled();
async.invoke(this._cancelPromises, this, undefined);
@@ -82,10 +82,14 @@ Promise.prototype._cancelPromises = function() {
};
Promise.prototype._unsetOnCancel = function() {
- ASSERT(this.isCancellable() || this.isCancelled());
+ ASSERT(this._isCancellable() || this._isCancelled());
this._onCancelField = undefined;
};
+Promise.prototype._isCancellable = function() {
+ return this.isPending() && !this._isCancelled();
+};
+
Promise.prototype.isCancellable = function() {
return this.isPending() && !this.isCancelled();
};
@@ -119,7 +123,7 @@ Promise.prototype._invokeOnCancel = function() {
};
Promise.prototype._invokeInternalOnCancel = function() {
- if (this.isCancellable()) {
+ if (this._isCancellable()) {
this._doInvokeOnCancel(this._onCancel(), true);
this._unsetOnCancel();
}
View
@@ -37,7 +37,7 @@ CONSTANT(CALLBACK_SIZE, 4);
//W = isFollowing (The promise that is being followed is not stored explicitly)
//F = isFulfilled
//N = isRejected
-//C = isCancellable
+//C = willBeCancelled
//T = isFinal (used for .done() implementation)
//B = isBound
//I = isRejectionIgnored
@@ -52,14 +52,15 @@ CONSTANT(IS_ASYNC_GUARANTEED, 0x8000000|0);
CONSTANT(IS_FOLLOWING, 0x4000000|0);
CONSTANT(IS_FULFILLED, 0x2000000|0);
CONSTANT(IS_REJECTED, 0x1000000|0);
-CONSTANT(IS_CANCELLABLE, 0x800000|0);
+CONSTANT(WILL_BE_CANCELLED, 0x800000|0);
CONSTANT(IS_FINAL, 0x400000|0);
CONSTANT(IS_BOUND, 0x200000|0);
CONSTANT(IS_REJECTION_UNHANDLED, 0x100000|0);
CONSTANT(IS_REJECTION_IGNORED, 0x80000|0);
CONSTANT(IS_UNHANDLED_REJECTION_NOTIFIED, 0x40000|0);
CONSTANT(IS_DISPOSABLE, 0x20000|0);
CONSTANT(IS_CANCELLED, 0x10000|0);
+CONSTANT(IS_CANCELLED_OR_WILL_BE_CANCELLED, IS_CANCELLED | WILL_BE_CANCELLED)
CONSTANT(LENGTH_MASK, 0xFFFF|0);
CONSTANT(LENGTH_CLEAR_MASK, ~LENGTH_MASK);
CONSTANT(MAX_LENGTH, LENGTH_MASK);
@@ -307,7 +307,7 @@ function cancellationExecute(executor, resolve, reject) {
}
function cancellationAttachCancellationCallback(onCancel) {
- if (!this.isCancellable()) return this;
+ if (!this._isCancellable()) return this;
var previousOnCancel = this._onCancel();
if (previousOnCancel !== undefined) {
@@ -322,12 +322,12 @@ function cancellationAttachCancellationCallback(onCancel) {
}
function cancellationOnCancel() {
- ASSERT(this.isCancellable());
+ ASSERT(this._isCancellable());
return this._onCancelField;
}
function cancellationSetOnCancel(onCancel) {
- ASSERT(this.isCancellable());
+ ASSERT(this._isCancellable());
this._onCancelField = onCancel;
}
View
@@ -59,7 +59,7 @@ function finallyHandler(reasonOrValue) {
var maybePromise = tryConvertToPromise(ret, promise);
if (maybePromise instanceof Promise) {
if (this.cancelPromise != null) {
- if (maybePromise.isCancelled()) {
+ if (maybePromise._isCancelled()) {
var reason =
new CancellationError(LATE_CANCELLATION_OBSERVER);
promise._attachExtraTrace(reason);
View
@@ -323,6 +323,10 @@ Promise.prototype._setCancelled = function() {
this._fireEvent("promiseCancelled", this);
};
+Promise.prototype._setWillBeCancelled = function() {
+ this._bitField = this._bitField | WILL_BE_CANCELLED;
+};
+
Promise.prototype._setAsyncGuaranteed = function() {
if (async.hasCustomScheduler()) return;
this._bitField = this._bitField | IS_ASYNC_GUARANTEED;
@@ -137,7 +137,7 @@ PromiseArray.prototype._resolve = function (value) {
};
PromiseArray.prototype._cancel = function() {
- if (this._isResolved() || !this._promise.isCancellable()) return;
+ if (this._isResolved() || !this._promise._isCancellable()) return;
this._values = null;
this._promise._cancel();
};
@@ -48,13 +48,20 @@ var isResolved = PromiseInspection.prototype.isResolved = function () {
return (this._bitField & IS_REJECTED_OR_FULFILLED) !== 0;
};
-PromiseInspection.prototype.isCancelled =
-Promise.prototype._isCancelled = function() {
+PromiseInspection.prototype.isCancelled = function() {
+ return (this._bitField & IS_CANCELLED_OR_WILL_BE_CANCELLED) !== 0;
+};
+
+Promise.prototype.__isCancelled = function() {
return (this._bitField & IS_CANCELLED) === IS_CANCELLED;
};
+Promise.prototype._isCancelled = function() {
+ return this._target().__isCancelled();
+};
+
Promise.prototype.isCancelled = function() {
- return this._target()._isCancelled();
+ return (this._target()._bitField & IS_CANCELLED_OR_WILL_BE_CANCELLED) !== 0;
};
Promise.prototype.isPending = function() {
@@ -750,6 +750,13 @@ describe("Cancellation", function() {
var p = new Promise(function(_, __, onCancel) {resolve = arguments[0]});
return p;
});
+
+ specify("gh-1187", function() {
+ var a = Promise.delay(300).lastly(function() {});
+ a.cancel();
+ assert(a.isCancelled());
+ assert(!a.isCancellable());
+ })
});
describe("Cancellation with .all", function() {

0 comments on commit 77f7711

Please sign in to comment.