w3c / webtransport

WebTransport is a web API for flexible data transport

Home Page:https://w3c.github.io/webtransport/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Expose [[State]] internal slot

achingbrain opened this issue · comments

The spec sets out a [[State]] internal slot that contains the current state of the transport.

It would be really useful to expose this as an attribute to allow js code to have a little more introspection ability.

It would help with application observability and diagnostics, and also to better understand the lifecycle of a WebTransport object.

This seems duplicative. We already have the ready promise and errors. If we added this, we'd need a corresponding event handler (onstatechange). The state change events would correspond to the ready promise and errors. So it's not clear to me that the application would obtain more information.

I agree it's duplicative since we went with promises over events and state. Here's a polyfill that works:

if (!('state' in WebTransport.prototype)) {
  const nativeWebTransport = window.WebTransport.bind(window);

  window.WebTransport = function(url, options) {
    const wt = new nativeWebTransport(url, options);
    wt.state = "connecting";
    wt.ready.then(() => wt.state = "connected", () => wt.state = "failed");
    wt.closed.then(() => wt.state = "closed", () => wt.state = "failed");
    wt.draining?.then(() => wt.state = "draining", () => {});
    return wt;
  };
}

I propose we close this at next meeting.

The problem with the suggested polyfill is that if you call .then with two args, if the promise rejects it no longer causes an unhandled promise rejection.

If a user wants this in their application that's down to them but it's not the sort of code you could reasonably include in a library.

Exposing the [[State]] slot would allow observability without changing the behaviour of the thing it is observing.

@achingbrain thanks for spotting that. Rethrowing the error should hopefully fix that.

if (!('state' in WebTransport.prototype)) {
  const nativeWebTransport = window.WebTransport.bind(window);

  window.WebTransport = function(url, options) {
    const wt = new nativeWebTransport(url, options);
    wt.state = "connecting";
    wt.ready.then(() => wt.state = "connected", e => { wt.state = "failed"; throw e; });
    wt.closed.then(() => wt.state = "closed", e => { wt.state = "failed"; throw e; });
    wt.draining?.then(() => wt.state = "draining");
    return wt;
  };
}

Hmm, that might always trigger unhandled rejections. I'll have to think about it a little more.

@jan-ivar I agree with closing this issue. So far, I haven't found a situation in which a [[State]] internal slot would be useful.

So far, I haven't found a situation in which a [[State]] internal slot would be useful

Here's one - I put this demo page together while investigating a bug that makes WebTransport unusable for peer to peer applications, it tracks the state of various WebTransport connections opened by the page.

It does so by doing something similar to the suggested polyfills above, but due to the semantics of using promises for .ready, .closed, etc it can't observe the state of a connection without changing it's behaviour.

[[State]] would have been very useful here.

Here's another, though similar - I'd like to also expand the observability of js-libp2p through a dashboard similar to ipfs-webui but again this isn't something we can do without either causing unhandled promise rejections or smothering errors.

Meeting: