03:12
<annevk>
I could make that perhaps. I told jib various things too though, I think he’s preparing as well
10:30
<Domenic>
MikeSmith: I'm a little scared of merging two order-dependent PRs with GitHub in its current fragile state, and also how well any subsequent Travis runs and deploys will go. So if we could wait until https://status.github.com/ calms down a bit that'd be ideal. But yeah nothing blocking on the code front.
10:31
<MikeSmith>
Domenic: ah yeah, good point
10:32
<MikeSmith>
Domenic: I had to try multiple times before I could even successfully submit that issues comment :)
10:32
<MikeSmith>
GitHub kept saying, "You can '
10:32
<MikeSmith>
"You can't comment right now."
10:32
<Domenic>
Yeah, I think sometimes it goes through though. Like I've gotten 15 emails from Jake's comment on service worker F2F agenda.
10:33
<Domenic>
So I actually tried to reply on-thread and then saw it fail and decided to go here instead, to avoid potentially sending N emails of my own while retrying.
13:29
<Domenic>
annevk: any reason to wait on merging https://github.com/whatwg/html/pull/4099 ?
13:29
<Domenic>
I guess maybe because GitHub is shaky
13:36
<annevk>
Domenic: I didn't do it because it wasn't sure about the commit message, feel free
13:36
<annevk>
And I guess I wanted to give dbaron some time to chime in, but it's probably okay
13:37
<Ms2ger>
lgtm
13:39
<dbaron>
I was just forwarding an email to the right place...
13:47
<annevk>
Merged
14:38
<Domenic>
annevk: working on https://github.com/whatwg/html/pull/4076/files but I am really confused because "associated Document" does not seem defined...
14:41
<annevk>
Domenic: hmm yeah, I guess that was never defined
14:42
<Domenic>
Trying to formulate something alternate and maybe a bit simpler, but not sure if it's equivalent...
14:43
<annevk>
relevant Document is probably Location object's relevant global object's browsing context's active document
14:44
<Domenic>
I think it's:
14:44
<Domenic>
The relevant Document of a Location object loc is loc's relevant settings object's responsible document, if that Document is active, and null otherwise.
14:45
<Domenic>
Yours maybe is better
14:45
<Domenic>
Is "active document" null for detached iframes?
14:45
<Domenic>
(Sounds like a question we've asked before...)
14:46
<annevk>
That shouldn't be active, I think
14:46
<Domenic>
https://github.com/whatwg/html/issues/1073
14:47
<annevk>
good times
14:48
<Domenic>
I think ours are equivalent
14:48
<Domenic>
Happy with either, although with yours we should add a note pointing to 1073 and clarify the intent
14:48
<Domenic>
Hmm no we need the note with both
14:49
<Domenic>
I'll capture on GitHub
14:51
<Domenic>
I really wish documents were dumber/not tied to anything
14:58
<annevk>
heh
20:27
<lgrahl>
o/
20:29
<lgrahl>
Access to Raw Audio... is this something you would consider in scope for WHATWG streams? https://docs.google.com/presentation/d/1WOihY0SMJbWvfbc-41GA78F4yzPSwmyDOJ8GbRoU7dw/edit#slide=id.g445c72bf7e_1_0 (slides 30 to 38)
20:29
<lgrahl>
I honestly don't know in this case.
20:35
<Domenic>
lgrahl: from what I can tell that is about real-time audio processing, which is not as good a fit (in part because real time audio is very specialized). But if you were talking just streaming access to the audio bytes of a RTC stream, that would make sense, and in fact there's a proto-spec for it
20:36
<lgrahl>
Domenic: Yeah, I think this is mainly about real-time transformation. I guess this is better suited for Worklets.
20:37
<lgrahl>
Domenic: I think we will see a couple of slides tomorrow that suggest using streams for RTP 'n stuff
20:37
<Domenic>
https://discourse.wicg.io/t/rfc-proposal-for-integration-streams-mediastreamtrack-api/2256 for streaming access to raw bytes of a MediaStreamTrack
20:37
<Domenic>
Exciting. I should be able to make it.
20:37
<lgrahl>
Great! :)
20:52
<lgrahl>
Jan-Ivar and I were thinking whether we should create an API that can handle both binary and string data (since that is what WebSocket and Data Channels currently allow to send)... or just binary and say that encode/decode should be a transformation.
20:52
<lgrahl>
I do kind of like the latter approach.
20:52
<Domenic>
Yeah the latter is what we're doing with modern APIs these days like fetch
20:53
<Domenic>
These days it's as easy (in spec land and in Chrome) as `const stringReadable = byteReadable.pipeThrough(new TextDecoderStream())`
20:54
<lgrahl>
Oh, that's good to know :)
20:54
<jib>
hi
20:56
<lgrahl>
jib: You may want to take a look at the latest comment from Domenic (see the log). Might be a neat example.
20:56
<jib>
I saw
20:57
<jib>
but that requires cooperation to know what's text and what's not
20:57
<lgrahl>
Then again, the application will usually know. It could even use separate channels for that purpose.
20:58
<jib>
well sure, but it requires dedicating a single channel per type. that's easy
20:59
<jib>
Today, we can do dc1.send("A"); dc1.send(fileB); do2.send("C"); dc2.onmessage = ({data}) => (data instanceof Blob)? processFile(data) : log(data);
20:59
<jib>
which lets you mix heterogeneous messages by type at least
21:00
<lgrahl>
Yes and I wouldn't want to change that now. However, it does support the argument that we shouldn't bother about having a stream support strings, too.
21:00
<jib>
It does? how?
21:01
<lgrahl>
If we go with .onmessage spitting out streams for binary data and DOMString for strings, then you still have both. If you want to send huge strings, just encode/decode them and send them as binary.
21:02
<jib>
We might be able to do the same with streams, with e.g. onreadable = ({readable}) => (readable.type == "bytes")? readable.pipeTo(fileProcessor) : readable.pipeTo(logger);
21:02
<jib>
If I encode strings, how will receiver tell them apart from files?
21:03
<jib>
ss/onreadable/dc2.onreadable/
21:03
<lgrahl>
Why would the receiver not know what it is going to receive?
21:03
<lgrahl>
Which application does stuff like that? :)
21:03
<jib>
because we support it today? do dc1.send("A"); dc1.send(fileB); do2.send("C"); dc2.onmessage = ({data}) => (data instanceof Blob)? processFile(data) : log(data);
21:03
<Domenic>
It seems surprising to me that you've so far privileged one type's byte-serialization (strings) over others, and made it auto-decode. Why not do the same for numbers, or JSON, or protobufs?
21:04
<jib>
isn't that what websocket does?
21:05
<Domenic>
Ah, so just following web sockets?
21:05
<jib>
as opposed to?
21:05
<Domenic>
Following fetch or other modern APIs
21:05
<jib>
RTCDataChannel is modeled after websocket. How would we follow fetch?
21:06
<Domenic>
Operate on bytes, and let applications choose their semantics by decoding those bytes appropriately. This allows a mucher richer set of types to all have equal support, instead of privileging strings.
21:06
<lgrahl>
Also makes the transport less complicated
21:07
<jib>
makes some sense. Specs are a bit confusing wrt ReadableStream, it seems type-agnostic at times, but other times seems to be bytes only, to me
21:08
<lgrahl>
Let me say again: This is meant as an extension. You can still get strings out of .onmessage. I'm just saying that we shouldn't care about handling backpressure for strings. It would make the stack unnecessarily complicated for a moot use case (IMO). If someone is sending gigantic strings, it could easily drop in TextDecoderStream.
21:09
<Domenic>
Yeah I can see that. The ones from the network are bytes, but the type itself supports everything, which lets you do things like write transforms that go from ReadableStream<bytes> -> ReadableStream<string> or ReadableStream<JS object> or ReadableStream<number> or...
21:09
<jib>
lgrahl: ok I'll buy that
21:10
<jib>
I think you've convinced me
21:11
lgrahl
cheers
21:11
<jib>
fewer options simplify slides
21:12
<lgrahl>
Nice side effect :)
21:12
<jib>
Btw on naming, How do we feel about dc.createWritable() ? The word "stream" is a bit overloaded in webrtc
21:12
<lgrahl>
If it were TypeScript, I would like "createMessage" because the return type is clear
21:12
<jib>
hmm
21:13
<jib>
but it's not typescript ;)
21:13
jib
likes ducktyping
21:13
Domenic
too
21:14
<jib>
if it reads and writes like a duck...
21:14
<Domenic>
Given the overloaded meaning of stream that seems pretty solid.
21:14
<Domenic>
I assume it should be a function, not a property, because calling it causes some locking or change into "write via a stream" mode?
21:14
<jib>
ok
21:15
<lgrahl>
Yeah, it would lock .send
21:15
<jib>
yeah
21:15
<lgrahl>
Or, actually... it might not even need to
21:15
<Domenic>
Seems simpler
21:15
<lgrahl>
Agree. We should lock. Let's not make things more complicated.
21:16
<jib>
dc1.send("A"); fileB.pipeTo(dc1.createWritable()); do2.send("C"); // emits A, B0, B1, B2 ... Bend, C
21:17
<jib>
uh s/do2/dc2/
21:17
<lgrahl>
Is there some kind of indications on when the piping is complete?
21:17
<jib>
it's closed()
21:17
<Domenic>
pipeTo promise will settle
21:18
<jib>
ah
21:18
<jib>
thanks
21:18
<lgrahl>
Okay, good. Because otherwise the locking would be awkward
21:18
<jib>
dc1.send("A"); await fileB.pipeTo(dc1.createWritable()); do2.send("C"); // emits A, B0, B1, B2 ... Bend, C
21:18
<Domenic>
Noob question, why is the last example do2/dc2, not dc1
21:18
<jib>
cause I cut'n'pasted my earlier typo ;/
21:19
<jib>
dc1.send("A"); await fileB.pipeTo(dc1.createWritable()); dc2.send("C"); // emits A, B0, B1, B2 ... Bend, C
21:19
<Domenic>
OK but why dc2 instead of dc1
21:19
<jib>
dc1.send("A"); await fileB.pipeTo(dc1.createWritable()); dc1.send("C"); // emits A, B0, B1, B2 ... Bend, C
21:19
<jib>
:*)
21:19
<Domenic>
OK now it makes sense
21:19
<lgrahl>
Heh
21:19
<Domenic>
Hmm now I guess I see how no-locking might be fine if it's just a queue of stuff to do anyway
21:19
<jib>
?
21:20
<jib>
oh with await
21:20
<jib>
well
21:20
<jib>
What happens if I do:
21:20
<lgrahl>
Yeah, it's a queue, but we shouldn't encourage people to fill it if we want to avoid backpressure
21:20
<Domenic>
No yeah I'm starting to see the problems again
21:20
<jib>
dc1.send("A"); const p = fileB.pipeTo(dc1.createWritable()); dc1.send("C"); await p; // should probably also emit A, B0, B1, B2 ... Bend, C
21:21
<jib>
or gremlins
21:21
<lgrahl>
Exception in your face
21:21
<Domenic>
Yeah there's no way to make that give the order you want I now realize
21:22
<Domenic>
If you don't prevent dc1.send() while the piping is ongoing (i.e. while the writable stream is not-closed), then interleaving happens
21:22
<Domenic>
So yeah locking good
21:22
<jib>
I think so
21:22
<Domenic>
Thanks for bearing with me :)
21:22
<jib>
sure np!
21:23
<jib>
Btw, my slides are also going to claim that streams of streams make no sense
21:23
<jib>
just running this by here first, to check
21:23
<lgrahl>
Interleaving of messages on the same channel is actually being prevented by SCTP but... I still think locking makes more sense as users could get the wrong impression on order.
21:23
<lgrahl>
Also makes it either to port to WebSocket later.
21:23
<lgrahl>
*easier
21:24
<Domenic>
I'm not sure they make _no_ sense, but I can see how they wouldn't but you much, and it seems like you've found a nice cut point to introduce them that gets most (all?) of the benefits without disturbing everything
21:24
<lgrahl>
I think they would make sense if we would design a new API from scratch
21:25
<jib>
Unsure about that even
21:25
<jib>
here's my thinking:
21:25
<jib>
Message semantics are appealing for multiple (heterogeneous) finite payloads.
21:25
<jib>
Stream semantics are appealing for single payload; outsourcing chunking & pressure.
21:25
<jib>
A queue of streams is appealing to manage multiple discrete payloads of large size.
21:25
<jib>
A “stream of streams” doesn’t add much over queue of streams; hurts: Competing semantics; Outsourcing chunking & pressure again hides messages.
21:26
<Domenic>
I don't understand the hurts
21:26
<jib>
Yes, shimming stream semantics on top of messages works in demos, but hijacks channel for single payload and loses control of messages. Stream semantics on top of streams has the same problem. A multi-payload quasi-stream as API isn’t a stream
21:27
<jib>
Isn't part of the value of a stream not having any semantic overload of its "chunks"?
21:27
<Domenic>
Like if someone is producing a stream of streams and wants to give it to a Web RTC consumer then making them go through a different API, and lose backpressure on their inner-stream production, seems sad
21:27
<Domenic>
Not sure exactly what you mean by that
21:28
<jib>
The semantics of stream of stream hurts my head basically, not sure what it adds over queue of streams
21:29
<Domenic>
Backpressure and easy piping/interop with other streams-of-streams, I think
21:29
<Domenic>
(There are no other streams-of-streams yet of course)
21:29
<jib>
nested backpressure?
21:29
<lgrahl>
I think it's just a different model. But in comparison to events, we can automatically handle backpressure across multiple messages. Say, if you would pipe a stream of messages from one data channel to another.
21:30
<lgrahl>
(where messages is another word for Stream<bytes>)
21:30
<jib>
I thought we settled on sstream of bytes
21:30
<lgrahl>
*message
21:30
<jib>
right
21:31
<Domenic>
Yeah nested backpressure :). Like if your inner-streams are files and your outer-stream is deciding whether to open new files from the filesystem, backpressure would tell you "don't open a new file yet, I'm backed up processing the ones you already gave me"
21:31
<lgrahl>
Piping a whole directory
21:32
<jib>
but why stream a queue?
21:33
<jib>
because you can process more than one at a time?
21:33
<Domenic>
I mean aren't all streams (async) queues? Just queues that you care about backpressure on?
21:34
<jib>
the backpressure stuff makes sense to me for buffers, but my understanding falls apart for types without a predetermined length
21:34
<Domenic>
Well at that level the length of every file is "1"
21:35
<Domenic>
And it's a question of "if I am backed up by 3 files then maybe don't open any more for me"
21:35
<jib>
hmm
21:35
<Domenic>
I guess you could do actual file size stuff but I wasn't thinking of it that way
21:35
<Domenic>
Wow my internet is dying. Maybe a sign it's time to sleep.
21:35
<jib>
heh
21:35
<jib>
ok thanks for the chat, it was very helpful!
21:36
<Domenic>
\o/
21:36
<jib>
I think I'm going to stick with queue of streams for now, maybe my understanding will grow over time with that
21:36
<lgrahl>
A queue of streams might make sense for proxying websites for example
21:39
<jib>
backpressure with bytes makes sense to me, e.g. "ok we can handle 16000 more bytes please"
21:39
<lgrahl>
Imagine a fetch API that allows to queue fetch operations and move the body into the stream (I guess this could be easily written). That is essentially a Stream<Stream<bytes>>
21:39
<jib>
but saying "we can handle 5 more files" hardly seems deterministic, because it all depends on file sizes
21:40
<jib>
hmm
21:40
<lgrahl>
A requests page 1, 2 and 3. A is very slow in processing the data, though. B now uses that imaginary API to start fetching all pages but with automatic backpressure. B would only fetch the data as fast as A can process it and one after another.
21:43
<jib>
ok maybe I'm focusing too much on the backpressure value. Maybe there's API value solely in being able to creates pipes out of these things
21:43
<lgrahl>
Yeah, I believe so.
21:44
<jib>
so what would stream of streams look like for RTCDataChannel?
21:45
<jib>
The premise of pipeTo() seems to rely on other stream objects of similar type
21:45
<jib>
or lots of clever transforms
21:45
<jib>
That might lose a lot of people
21:46
<jib>
case in point: promises
21:46
<jib>
async/await is soooo much simpler to explain and get right, than promises
21:46
<jib>
at least for me
21:47
<lgrahl>
It would have a .readable attribute of type ReadableStream<ReadableStream<bytes>> and a corresponding .writable attribute. Again, I would only suggest that for NV. I agree it's hard to wrap your head around and we need to find easy and convincing examples first.
21:48
<jib>
I guess we can add that later, have both
21:48
<jib>
or, hmm
21:48
<lgrahl>
I think it will be a while before we discuss NV APIs
21:49
<lgrahl>
Or at least their final versions
21:49
<jib>
tomorrow? ;)
21:49
<jib>
Btw, when you say ReadableStream<bytes> with the < and > that's not any webidl syntax is it?
21:49
<lgrahl>
I'm not sure actually
21:50
<lgrahl>
I mean, 'bytes' is an abstraction anyway
21:50
<jib>
sure
21:50
<jib>
but byte is valid webidl
21:50
<lgrahl>
https://heycam.github.io/webidl/#idl-promise
21:51
<lgrahl>
They use Promise<T> so I guess we can use ReadableStream<T>
21:51
<jib>
except there's no ReadableStream in https://heycam.github.io/webidl/#idl-promise
21:53
<lgrahl>
I would go that far and say this syntax is fairly well-known
21:53
<lgrahl>
But for actual WebIDL definitions...
21:53
<jib>
it's not valid webidl, at least not yet
22:20
<Domenic>
TimothyGu: https://github.com/servo/servo/pull/21882/files
22:26
<lgrahl>
jib: I'll get some sleep :)
22:27
<jib>
jib: goodnight, thanks for your help!
22:27
<jib>
uh
22:27
<jib>
lgrahl: ^
22:27
jib
is tired
22:28
lgrahl
is so tired that he didn't even see the wrong mention
23:35
<TimothyGu>
Domenic: yay!