07:50
<annevk>
I think that is editorial. It doesn't change how the standard is understood.
07:51
<annevk>
https://github.com/whatwg/meta/blob/main/COMMITTING.md#title-prefixes has advice, though I'll admit that every now and then Domenic will correct me. It still doesn't come natural to me.
08:19
<The Finder>
Hello everybody here, You can consider me as someone accidently land out into this room. But I am really exciting to be here. and will really appreciate that if anyone here explain me a bit on its science ?
08:55
<ntim>
Domenic: Filed https://bugs.webkit.org/show_bug.cgi?id=233514 & https://bugzilla.mozilla.org/show_bug.cgi?id=1743082 for WebKit & Gecko
08:55
<ntim>
(also i'm doing the work for WebKit)
08:56
<ntim>
emilio: sefeng ^
16:23
<jgraham>
So I'm trying to work out how to talk about sandboxes / isolated worlds for WebDriver BiDi (Extensions will need something similar for content scripts). I kind of just want to sketch in the basics of how it works at the moment, but it would be good to start with a model that isn't total nonsense. So I'm leaning towards a model where the behaviour is explained as "in a sandbox, objects are accessed through a transparent wrapper object. When getting a property, if the property is defined on the wrapper, return that. Otherwise check if the property is defined on the wrapped object and, if it is, and the wrapped object is a platform object, and the property is part of the interface definition for the wrapped object, or is an internal slot, return the wrapped property value if it's an object, or the primitive value if it's not. When setting a property, check if the wrapped object is a platform object, and the property is part of the interface for that platform object, then act as if setting the property on the wrapped object. Otherwise set the property on the wrapper." Does that make any sense whatsoever as a model or is it going to run into insurmountable difficulties (I think it's similar to the actual Gecko implementation, but I'm not an expert)? If it does make sense, how to fit it into the formalism? I don't mind the wrapper objects being "magical", but does it make sense to claim that the sandbox itself is a realm and the wrapped objects are part of a different realm? That kind of makes sense at a high level, and matches how we want to expose it in the BiDi protocol but is it going cause problems with some invariants at the spec level?
16:26
<jgraham>
I kind of realise that this stuff doesn't match the theoretical model of ECMAScript etc. so there is probably going to be some amount of doing things that aren't intended (and maybe people won't like it), but it would be good to avoid unnecessary friction.
16:33
<Jim Pryor>
I've been reading the Webstreams spec and working on porting some code running in Node to use webstreams. I came across two obstacles that I think are built into the current design. Would value hearing from others who know more about or have more experience working with this spec. Is this a good place to ask? Would it be ok/better to raise issue on whatwg/streams?
16:33
<Jim Pryor>
  1. In a Readable/WritableStream's start() implementation (also in read() or write()) I sometimes want to gracefully cancel or abort the stream. For example, if a WritableStream is passed data of a type it doesn't handle, but I want the stream implementation to do some post-processing on the data it already received. One can't use the client-facing cancel or abort methods on the streams at these points, because the stream is typically locked. You can call controller.error, but (at least in Node 17.1.0's implementation and in the current web-streams-polyfill), this throws an error outside the scope of the stream implementation (so it can't be observed/caught by the implementation's cancel or abort routines). I'd be interested to hear whether this design is deliberate and what kinds of worksarounds I might consider.
16:33
<Jim Pryor>
  1. There doesn't seem to be any way to observe errors/aborts/cancelations in an existing stream (that my code did not implement itself). Some Node code I'm trying to port calls webstream.on('error', err => ...) but I don't see any way to do something similar with webstreams. I considered having my code implement a TransformStream and piping the externally-provided ReadableStream through that. But I don't see any way to make the TransformStream observe errors in another stream piping into it.
16:37
<annevk>
jgraham: at a high-level it sounds reasonable; "Proxy object" is the TC39 verbiage. You could look at WindowProxy for some inspiration. Defining that in detail seems quite involved though.
16:37
<ntim>
Domenic: emilio sefeng , I wrote https://github.com/web-platform-tests/wpt/pull/31758 which formalizes the behavior implemented in Chrome/Firefox (though it fails in WebKit), although I'm not sure this is specified anywhere
16:39
<ntim>
Should ::backdrop receive events from the associated element ?
16:39
<Jim Pryor>
  1. There doesn't seem to be any way to observe errors/aborts/cancelations in an existing stream (that my code did not implement itself). Some Node code I'm trying to port calls webstream.on('error', err => ...) but I don't see any way to do something similar with webstreams. I considered having my code implement a TransformStream and piping the externally-provided ReadableStream through that. But I don't see any way to make the TransformStream observe errors in another stream piping into it.
Whoops, I mean, it calls nodestream.on('error', err => ...)
16:41
<annevk>
Jim Pryor: I think stream.closed ends up rejecting
16:41
<annevk>
Someone else prolly knows better though
16:43
<jgraham>
annevk: Yeah, I have been looking at WindowProxy, that's pretty much how I ended up with "oh if we just override all the internal methods…" :)
16:43
<Mattias Buelens>
Whoops, I mean, it calls nodestream.on('error', err => ...)
You can use `reader.closed.catch(err => { ... })` for that.
16:44
<jgraham>
And yes I agree it's quite a lot of work, this is why the aim in the short term is to have something that sketches out the requirements, because in reality browsers already have an implementation of this stuff and they aren't going to change the existing implementation to match the spec anyway
16:44
<annevk>
jgraham: "just" is doing a lot in that sentence
16:44
<jgraham>
Fair :)
16:48
<annevk>
jgraham: I wonder if implementations are truly creating proxy objects or if they are creating separate JS objects that point to the same backing IDL object
16:49
<annevk>
jgraham: the former seems kinda painful for perf, especially if you'd also have to do it for website scripts (not sure how you'd avoid expandos leaking to extensions otherwise)
16:52
<jgraham>
annevk: I think Gecko and Blink are different here (I assume WebKit matches Blink). Blink basically creates a new JS reflector for each underlying C++ object. But Gecko I think is closer to having a proxy object as described (and a practial implication is that in Gecko you can get to the original JS reflector using .wrappedJSObject fram a sandbox)
16:52
<Mattias Buelens>
  1. In a Readable/WritableStream's start() implementation (also in read() or write()) I sometimes want to gracefully cancel or abort the stream. For example, if a WritableStream is passed data of a type it doesn't handle, but I want the stream implementation to do some post-processing on the data it already received. One can't use the client-facing cancel or abort methods on the streams at these points, because the stream is typically locked. You can call controller.error, but (at least in Node 17.1.0's implementation and in the current web-streams-polyfill), this throws an error outside the scope of the stream implementation (so it can't be observed/caught by the implementation's cancel or abort routines). I'd be interested to hear whether this design is deliberate and what kinds of worksarounds I might consider.
Hmm, controller.error() does indeed clear the queue, it's supposed to be for an "immediate" fatal error. You could do controller.close() for a ReadableStream, but then you can't signal an error. 🤔
16:54
<annevk>
jgraham: does that mean you can see expandos in Gecko? I guess one thing that would help me here is to have some examples 🙂
16:55
<annevk>
jgraham: I also wonder if we want to keep that setup in Gecko or if this is something we might change (we ended up changing things for document.domain)
16:56
<jgraham>
annevk: In gecko, if a window does something like document.expando = 1 then from a sandbox document.expando is undefined but document.wrappedJSObject.expando is 1 (I believe)
16:56
<jgraham>
The Firefox UI code leans pretty heavily on the current implementation, so I wouldn't bet on it changing.
16:57
<annevk>
I wonder how that works. Doesn't that mean that wrappedJSObject also has to be a proxy?
16:58
<jgraham>
I mean I don't think it really works in terms of ES proxies
16:58
<annevk>
Yeah, but I guess that means that specifying this in a way that's agreeable to the various implementations might also be tricky and will end up being mostly hand-wavy...
16:58
<jgraham>
https://firefox-source-docs.mozilla.org/dom/scriptSecurity/xray_vision.html is the entrypoint to the documentation on what Firefox does
17:01
<jgraham>
Yeah, it's kind of "exciting" in that implementations aren't exactly the same, but also are very unlikely to converge, and in spec terms it's not super clear that exposing the concept of the internal state of an object being different from the JS observed state is OK/not going to cause people to be cross.
17:01
<jgraham>
But it's also a thing that exists in the real world and is needed by at least two popular platform-adjacent features (remote automation and extensions)
17:04
<annevk>
jgraham: yeah not sure. Maybe you can come up with a way of writing it down where you just have requirements on observable behavior ( + some stuff that's implementation-defined). Having examples would help a lot with that I think.
17:05
<annevk>
jgraham: and some explanation as to why there's no actual model, to not favor any particular approach.
17:05
<Mattias Buelens>
Jim Pryor: I think these questions deserve an issue in whatwg/streams. You're right, there's no way for a TransformStream to observe cancel or abort on its readable or writable end. I have personally had to do the same trick with piping through another identity transform in order to observe errors from the pipeTo promise. Not very elegant. 😛
17:10
<jgraham>
annevk: Yeah that's kind of what I planned to do and then when it came to writing it turned out to be hard to reason about how precise one needs to be when this is interacting with existing specs to avoid breaking their models/invariants. Usually the answer is "everything needs to be precise, but here it's more like "you need to look like you're doing something reputable from the outside, whilst furiously handwaving the internals". So I think that's been pushing me towards something that looks more like a "real" definition, but maybe it's not actually helping :)
18:01
<Jim Pryor>
Mattias Buelens: I've seen this in some code with nodestreams too. The scenario is, you have some outside-supplied readable stream (may be the readable end of a pipeline), that you want to observe and/or catch errors in. With node streams, I've seen code do stream.pipeline(suppliedStream, new stream.PassThrough (), callback) in order to catch errors raised by the supplied stream. I guess we're close to being able to do the same with webstreams, something like suppliedStream.pipeThrough(new IdentityTransform()).catch(callback). Only issue is that pipeThrough returns the readable end of the TransformStream, instead of a promise. Whereas pipeTo provides a promise, but expects a writable destination.
18:01
<Jim Pryor>
I guess what we'd have to do is: function installCallback(suppliedStream: ReadableStream, callback): ReadableStream { const t = new TransformStream(); suppliedStream.pipeTo(t.writable).catch(callback); return t.readable; }
18:04
<Jim Pryor>
Thanks, was helpful to talk this through.