Thank you for being still here at this time of the day.
We are welcoming time, had a day, for implementing stream spec in server web engine.
Yes, thank you.
Thank you everyone.
Thank you for having me.
I'm really happy to be here today to talk about the implementation of Steve Speck in
server, before we start, about me, so I'm a software engineer from Netherlands and
basically focus on embedded systems.
And my free time, mostly weekend, and after noon, I will contribute to server, across the
engine, team 95, you can follow me team 95 online.
Yeah, so I want to talk about server, I think I'll go already thought about server
with morning.
I'll drive in directly in the implementation.
So as we know, streams are quite important in a web engine, basically they are used almost everywhere,
fetched, fetched body, upload, download, compress, and decompress, APIs, and basically
if you have a broken stream implementation in your web engine, you have a missing part
if you're working in.
What was the status of the stream implementation in server?
So server will use modules, which is a rust binding for spider monkey, and spider monkey
had its own implementation of stream implemented in engine, because we were creating this
binding, or we were also creating the binding of these stream implementation from the engine.
And specific spider monkey version, these built in implementation, they were removed from
the engine, but they were moved to the Firefox.
So basically you can browse them in Firefox, Firefox, and Cutsers.
That created an issue for server, because basically if we upgrade to the new version, we
don't have the stream implementation, it will break our fetch implementation at whole,
the WPT test will go down.
So we were in a situation where we cannot update without compromising.
So we were trying to find a short-term solution.
Basically the short-term solution is to update spider monkey, but also create a patch, which
will bring the deleted code from spider monkey, deleted code, or removed code, we're talking
about this stream implementation.
We know this is working, but basically it's not a long-term solution, what if we want
to have a spec change or want to add a new one to fix something in stream implementation,
this will be really hard.
So the long-term solution is basically, basically re-implement in the stream implementation
stream spec inside the server in Rust.
And like this, we can basically have a spec driven stream implementation in Rust.
We can follow on the bug, and we can also upgrade to the spider monkey version freely.
To do this, so the implementation in the server, even though it was using spider monkey,
but it was not fully implemented, it was only implemented, so fetch can work properly.
Which means it was only implemented, readable stream, default controller, and default reader.
To do this, we started the work where we identified what are the needed features to at least
bring WPT test to the state where it was using the built-in spider monkey stream implementation.
So we created, we could not do like a major PR for the server, so we created like an intermediate
branch, and we started making like small PRs to build the stream implementation step by step.
And when we were in the state where we are reaching the same amount of WPT test,
we were passing before the in the built-in spider monkey implementation, we made the PR for
server, which implemented readable stream, and in Rust, with the default controller and
default reader.
And of course, we were able to move the patch that we introduced for MOSJS, the patch that
brings the delete code from spider monkey, and we can upgrade the failure now.
So basically, this is the patch where, so basically in the past implementation, you will see
function like read the chunk, which is a function to read the stream, it was using the direct
code from spider monkey, and this is literally like an ff and binding through the engine directly,
but we moved more like to Rust implementation without having this engine called directly in the
server script, and we rely on the engine for handling the values of the object of the
JavaScript object, because it's the need to communicate between two words. The good thing about
this implementation is like it's following the spec, everything is documented, and yeah, it's easy for us.
Okay, so since the implementation was only implemented for readable stream, default controller
and default reader, when we wanted to implement a byte controller and be always a reader,
we had an issue where we are still dealing with buffers, so we still need to call
JavaScript engine functions. For example, if you have a buffer, you want to detach it,
you still need to call detach function from the JavaScript engine, and we didn't want to get back
to the same situation where we have JavaScript calls inside JavaScript, so we started by creating
abstraction, we called the buffer source, which is literally a spec driven, this buffer source
is the abstraction where we have all these JavaScript engine calls, and from the service script,
you call these abstraction. And when we did this, we started noticing something really interesting,
all these JavaScript engines, they share the same implementation, because they follow the TC39,
and from this we started having idea, okay, if we started creating all these abstraction,
can we reach the point where service script does not rely on the engine by itself, but
rely on abstraction, the abstraction rely on the engine. And for example, we can see example rust V8,
which is also the wrapper for V8, and rust testing function detach. But for buffer, it's easy,
because it's like a direct, direct calls, but we still rely heavily on the spider monkeys,
our server implementation, so creating abstraction will be a lot of work, and it will be like
to take a lot of time, so I had a chat with one of the, one of the servo maintainer, and we agreed
that this requires a lot of work, but it's a good sign. Okay, so since we have now an implementation
of the stream in rust, it actually made it easy for us to implement the next step, or the missing
part of the stream in servo, which will solve the most logical, the next part is to implement
writeable stream, and when you have readable stream, writeable stream, you can implement transform
stream. And that actually what we did, because we were just following the spec, now it's easy for us
easy for the bug, because it just rust code, and then we implemented the rest of the spec.
Yeah, so since we implemented writeable stream, we're also, sorry, it was simply quite
a control signal, so we ended up also implementing a both controller, a both signal, and they are
also all living in the rust in servo with the engine back in it. So what did this stream
implementation that we did unlocked in servo? So we started not seeing that the community now,
they're taking the stream implementation as a reference, and make it easy for them for them to
implement older APIs. So for example, here, somebody is literally a took the stream implementation
as a reference in implemented the compress and decompress API. Another team, another community member,
also took the stream implementation as a reference, and implemented the decode test decode stream
and test encode stream. So the implementation was a good reference. Yeah, the question is
how does the stream implementation in servo on the WPT? So basically servo almost passed all the tests
or all the stream tests, it's even sometimes surpass some other engines, but the butt is this,
servo does not support shared worker, dedicated worker and service worker. So basically when you enable
them all the stream implementation in that context they are failing of course, because we don't have
the context, but the moment we will support this context, stream implementation is there, all the WPT test
would be passing. The good news is that we are planning to start working on the workers in 2026 this year.
Okay, so we talked about stream implementation, we talked about WPT, but what does it really mean
for the for servo as a web engine? So basically because of this stream implementation about
control or controller, we noticed that we were able example to make to have a functional
functional GitHub, and we were able example to create a PR directly from for servo from using servo.
And I think Rigo already showed it to, but basically we were able to run their servo and then
you can go to PR's, you can review, you can also open. There's some missing functionalities,
but I'm also logged in, so that was not possible before implementing these APRs.
Back to the slide. Yeah, so there is another example, there is a community member
that mentioned that example, this website, ShardGPT is not working, and with some investigation,
and we found out that okay, the fetch uses stream, and one of the functions is
when you try to clone the body of this fetch, it uses readable stream T with algorithms,
and since it was not implemented, it was implemented not using this algorithm,
and then when we used this spec, followed the spec correctly on using the stream,
readable stream, inside the cloning of the body of the fetch, we were able to have at least
ShardGPT website rendering, not rendering loading, of course, not fully working, but that was nice
impact. Yeah, so we did a lot of work on stream, but there is still we still have some
good start issues for people, if you want the work on them, we have a nice website called the
StarSeries.org, you find some last issues there, join and reach out in servo Zulip Shard,
if you want to have a chat, and check out the website. Yeah, so for the same implementation,
it was quite a journey, and I would like to thank some, so I would like to thank an
led foundation for supporting the project and believing in the project, also I would like to
thank reviewer and maintainer, so George for helping us, understanding how inspired the monkey works,
and how we can move from the build-in implementation to the own Rost servo implementation,
also Gregory for working with me, he was supposed to be here, but he couldn't make it,
and also the EGALATIM for also helping us support the project and reviewing our work.
Yep, that's it, thank you. Thank you, we are ready at the time, so if you have questions,
you can feed free to ask any question.
Thank you for the presentation, I have a question about why what was different about streams
that made it such that Mozilla implemented them in spider monkey at first versus in the browser
engine. Yes, to be honest, I don't know exactly why they implemented in the browser,
in the JavaScript engine itself, but I think the stream does not belong to the engine itself,
but they are in like an API, also the engine, but why they did it, I'm not sure.
Other questions?
Don't be shy.
Okay, so thank you then. Thank you so much and thank you for your presentation. Thank you.