Don't call queued callbacks from cancelled sub-promise

Closes #67
This commit is contained in:
eryn L. K 2021-12-27 23:15:44 -05:00
parent 34273a7efc
commit 2cb2eec152
2 changed files with 31 additions and 1 deletions

View file

@ -1206,7 +1206,7 @@ function Promise.prototype:_andThen(traceback, successHandler, failureHandler)
self._unhandledRejection = false
-- Create a new promise to follow this part of the chain
return Promise._new(traceback, function(resolve, reject)
return Promise._new(traceback, function(resolve, reject, onCancel)
-- Our default callbacks just pass values onto the next promise.
-- This lets success and failure cascade correctly!
@ -1224,6 +1224,15 @@ function Promise.prototype:_andThen(traceback, successHandler, failureHandler)
-- If we haven't resolved yet, put ourselves into the queue
table.insert(self._queuedResolve, successCallback)
table.insert(self._queuedReject, failureCallback)
onCancel(function()
-- These are guaranteed to exist because the cancellation handler is guaranteed to only
-- be called at most once
if self._status == Promise.Status.Started then
table.remove(self._queuedResolve, table.find(self._queuedResolve, successCallback))
table.remove(self._queuedReject, table.find(self._queuedReject, failureCallback))
end
end)
elseif self._status == Promise.Status.Resolved then
-- This promise has already resolved! Trigger success immediately.
successCallback(unpack(self._values, 1, self._valuesLength))

View file

@ -543,6 +543,27 @@ return function()
expect(y).to.equal(2)
expect(z).to.equal(3)
end)
it("should not call queued callbacks from a cancelled sub-promise", function()
local resolve
local count = 0
local root = Promise.new(function(r)
resolve = r
end)
root:andThen(function()
count += 1
end)
root:andThen(function()
count += 1
end):cancel()
resolve("foo")
expect(count).to.equal(1)
end)
end)
describe("Promise:cancel", function()