-
Notifications
You must be signed in to change notification settings - Fork 299
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AbortController
/ AbortSignal
was updated in a somewhat breaking way
#1059
Comments
For a context: |
It's unfortunate this has happened, but those are not considered breaking changes. I thought it was somewhat widely known that patching objects can lead to issues in the JavaScript community? Also, |
I appreciate that this doesn't meet the official designation of a breaking change. And I'm not trying to argue it is. I still consider it "breaking" in an ergonomic sense (and practical sense, since it literally has broken libraries/sites). When new properties get added to already existing APIs (objects), it has been my observation that they are not usually "locked down" in the sense of being defined read-only, as doing so limits user-land (libraries or apps). If there's a reason to protect a property, like security/privacy/etc, sure. But native APIs have capabilities that user-land code does not, like storing state in internal slots. So allowing developers to set (or change) the value of a public property, such as reason, even if that didn't affect any of the behaviors internally, seems like it would have been a more permissive/open sort of change to an existing API. If you had known there are libraries that were already setting Note: CAF is not the only (potentially) affected library. There are other small "polyfill" type utilities that defined/extended |
With respect to the "PRIOR" behavior of Say I'm a site author and I observe that whether I pass an argument to So I write a very simple function like this for my own app: function doAbort(cont,reason) {
if (!cont.signal.aborted) {
cont.signal.reason = reason;
cont.abort();
}
} In some places, I pass a if (!signal.reason) {
console.log("unknown reason");
} I end up doing these sorts of simple checks in dozens of places throughout my app. I have effectively treated this When I later find out about I try that, but I'm dismayed that my whole site still seems broken. Eventually I realize it's because not only is there now a And when I look at the object, it's a DOMException object! Whoa, wait. So are they telling me that But wait, the docs (and spec!) don't really call this a "required" argument. MDN indicates it's optional. So I'm confused. Ergonomically, if a thing has not existed before, and if it now exists but is treated as "optional", generally you just expect in places where you don't use it for it to behave as not used. In JS land, that USUALLY looks like a property being /remaining This DOMException approach contradicts that intuition/expectation, because semantically it signals that The DOMException doesn't throw, which would be even more hostile. But it does show up in my checks of It sure feels like a "breaking" change that now And I have a lot more code to change to adhere to this "breaking change". In reality, the change in CAF to avoid setting the read-only But then I realized the DOMException part... and that turned out to be much more disruptive to CAF's code. To preserve CAF's prior existing behavior (and thus the behavior sites/apps rely on), it took me 5 hours of effort yesterday and almost 200 lines of code added/changed throughout the library. I hope maybe that perspective helps explain why this feels breaking even if it's not officially labeled as such. |
We add many readonly attributes to objects all the time. The only place where we necessarily have to be somewhat cautious is the global object and certain I strongly recommend not trying to guess how the web platform might extend objects going forward as indeed that can result in a lot of work. |
I would typically never touch/extend built-in objects. Cancelation has been such a HUGE gap in JS (and the web platform) for decades that I felt CAF had a responsibility to fix these gaps 4 years ago, mostly in response to But I was deeply dismayed that it wasn't added with something as obvious/helpful as a reason-tracking mechanism. I fished around for why, and I didn't find anything concrete. Reluctantly, I decided CAF couldn't wait around in case a future change would address that gap. As it turned out, waiting 4 long years would have been, IMO, an unacceptable delay in addressing what people needed. It was important to me to embrace the ecosystem, and (in particular) interop with things like I had thoughts about what it would be like if I did not anticipate the read-only bit, but again that turned out to be an easy'ish accommodation to work around. I honestly never would have even remotely dreamed of the DOMException-on-omission bit. That part in particular just feels so unlike how features are typically added to existing APIs, as it feels to me like deliberately "breaking". Lessons learned, for sure. But honestly, the 4 year gap here in some ways validates my reluctant decisions back then. Again, if there are strong motivations for read-only and DOMException-on-omission, they are not at all obvious to me thus far. I would appreciate links to any further historical context onnsuch decisions. |
Before the change there was a singular reason, exposed in APIs that ended up rejecting a promise (i.e., an "AbortError" DOMException). So that's what |
I don't think there's anything left to do here. |
Just for posterity sake, this is not accurate as far as I know. Prior to the spec adding |
We add attributes to objects all the time. It's not generally known as a breaking change. Sometimes it does lead to breakage and in rare cases that warrants a rename (this mostly happens with JS objects, not platform objects). |
I understand that narrower stance, but I don't think this point has been fully groked: The "breaking change" was not "adding the property", it's the combination of all 3 of these things together that constitutes the de facto (even if not official) "breaking change":
Those 3 things together constitute a "breaking change" by any meaningful definition that I (or any reasonable dev I know) would use for any software I maintain. I cannot imagine making that kind of a change to any library I maintain, and then with a straight face claiming "what, bro, it's not technically a breaking change!?" I understand you refuse to accept that since you're using a more academic definition of "breaking change" instead of a pragmatic one. But anyway, I dealt with the breakage it caused users of my library, I've said my piece, and this is long-past water under the bridge. I won't keep belaboring it anymore. Sorry for the noise of ressurecting a dead thread. I somehow never saw those previous responses around the time of the thread resolution. |
I am not quite sure when this happened, but it seems like fairly recently... the change to add
reason
toAbortSignal
was done in a somewhat breaking way, and I'm just finding out about it given that this breakage propagated to one of my libraries that uses/extendsAbortController
andAbortSignal
.In particular, my concerns are:
The definition of
reason
as READ-ONLY breaks libraries (like CAF) that had previously been monkey-patching/polyfilling areason
property ontoAbortSignal
instances. More about the breakage can be read here: Cannot set property reason of #<AbortSignal> which has only a getter getify/CAF#28A BREAKING CHANGE was also made to the
abort(..)
method. The change is that prior, if aabort()
call was made with no argument, nothing adverse happens. But now, if you callabort()
with no arguments, thereason
doesn't stay set asundefined
, as one would expect from PRIOR behaviors... rather, it gets set to a non-falsyDOMException
error. That is, in particular, rather surprising, given thatabort(undefined)
-- explicitly passing inundefined
-- avoids theDOMException
value forreason
.Both of these changes may indeed have valid rationale, and I would certainly appreciate seeing where such discussions happened (as my searches thus far haven't turned up anything).
However, they conspire together to create a breaking change that crashes my CAF library. CAF has been around for 4+ years, is downloaded over 5,000 times per week on npm, and has over 1,200 stars on GitHub. As such, there's clearly a decent amount of sites/apps out there using CAF, and all of them are now broken as a result of these two changes.
I've done a pre-release of CAF to try to fix this crashing in a backwards-compatible way -- will do a full release once affected users report that it addressed the breakage -- but I have no idea if, or how quickly, all those sites/apps who are using CAF will update to my newest library release.
I would like to ask if it's possible to unwind change, even if temporarily, so browsers (like Chrome) are not breaking CAF v14.0.0 and prior?
The text was updated successfully, but these errors were encountered: