Should RTCDataChannel onclose event be fired when its peer connection gets closed?
As per, data channel readyState is set to closed synchronously, which prevents to fire the onclose event.
As per https://jsfiddle.net/uoLzbn17/, it appears that Safari does not fire the event but Firefox (and Chrome apparently as well) do. https://bugs.webkit.org/show_bug.cgi?id=303052 mentions a usecase where it is useful for web apps if the event would be fired.
We should figure out which behaviour we want and align implementations.
FWIW the reason this originally came up is that two libraries we use rely on the data channel firing the close event to execute various cleanup tasks when the peer connection closes unexpectedly, e.g.
- https://github.com/novnc/noVNC/blob/d44f7e04fc456844836c7c5ac911d0f4e8dd06e6/core/websock.js#L284
- https://github.com/xtermjs/xterm.js/blob/46c510a76d76d246ad015130a7f2d52e1f4629e1/addons/addon-attach/src/AttachAddon.ts#L40
As a rule of thumb (probably @jan-ivar's thumb) events aren't fired if they result of action JS has taken action?
Semi-related https://jsfiddle.net/cf34zrt2/ looks like some browsers are not firing as https://w3c.github.io/webrtc-pc/#error-on-creating-data-channels says they should while other browsers are a bit too lenient about bundle
For same object action->event, I think this rule is mostly consistently applied. For cross-object action->event, I am not sure there is consistency or desire one way or the other.
There is also the case of a data channel living in a worker while its peer connection remains in window. It would probably be handy to fire the close event in that case.
We probably also have to fix the spec to handle transferred workers being closed this way.
This seems worth discussing at next interim.
Agreeed that it seems easiest for users of datachannel if the statechange to closed always happens. I have questioned the benefits of the "if javascript calls it, javascript shouldn't be notified" rule before (I think it's a bad idea in general, given multiple libraries accessing the same objects, but have been convinced to not pursue changing the status quo on track mute), but in the case of action->object->object->event, I think the case for firing the event is even stronger.
Let's converge on the behavior of Firefox and Chrome, and fire the event.
This issue had an associated resolution in WebRTC December 2025 meeting – 09 December 2025 (DataChannel close event):
RESOLUTION: Align close event spec with Firefox/Chromium implementation