CancelToken-likes?
The Promise constructor takes a cancellation token argument (and lots of other API functions take one and pass it through to the promise constructor).
But what exactly should one be able to pass in there?
- instances of
CancelToken: sure - instances of
CancelTokensubclasses: probably - arbitrary objects as long as they have a
.requestedproperty: maybe, why not?
Actually a .requested property is not exactly enough. We need a way to register a function that synchronously cancels the promise when the cancellation is requested.
In the current proposal, RegisterPromise, CancelPromise and CancelFunction take care of this.
This also works for CancelToken subclasses, as they do have a [[RegisteredPromises]] slot as well.
And with .requested properties we need to be cautious too. Currently it is expected that it changes state exactly only once, from false to true, and that when it does that happens in the process of calling CancelFunction. This ensures that we have no pending promises whose [[CancelToken]] is .requested, and that we have no cancelled promises whose [[CancelToken]] is not .requested. (Or at least not observably to scripts, the first situation actually happens during the call to CancelFunction).
This already breaks apart for subclasses of CancelToken, who can overwrite get requested() at their own discretion. For those instances, we can actually check their [[Result]] directly like CancelToken.prototype.requested does, to ensure that we don't believe in .requested when it claims false despite the token being cancelled (see also #7 for related issues).
This is not easily possible for arbitrary objects however.
The next question, after deciding what is a cancellation token, is what the constructor should do when something was passed but it's invalid. The default would be do nothing, but I guess we could as well assume that anything (non-null, non-undefined) being passed as a second argument is supposed to be a token, and when it is invalid we could throw (ending up as rejection) before calling the executor.
Doing anything besides "do nothing" would be a breaking change, since there are definitely existing scripts that return values in the executor.
@ljharb But I don't know any scripts that pass something token-like as an argument besides the constructor. Of course it is a breaking change to introduce a second parameter, but I don't think it'll break anything.
https://github.com/tc39/proposal-cancellation/issues/22 looks like a step forward in this direction
With https://github.com/tc39/proposal-cancellation/issues/22, I would liken this to the behavior of new Map([]) vs. new Map({}). Since {} doesn't have a Symbol.iterator method, a TypeError would be thrown. However new Map(), new Map(undefined), and new Map(null) do not throw as the argument is ignored. The same would be the case for an object expected to have a Symbol.cancelSignal method.