update speaker notes
This commit is contained in:
+47
-49
@@ -1,101 +1,99 @@
|
||||
---------
|
||||
|
||||
(Title page)
|
||||
Have you ever wanted to add your own crate to your favourite open source browser?
|
||||
Or write your own Web API to your own custom browser fork?
|
||||
My name is Ed Guloien and today I'm going to tell you how and what to watch out for.
|
||||
Have you ever wanted to add your own crate
|
||||
Or write your own Web API to your favourite browser?
|
||||
My name is Ed Guloien and today
|
||||
I'm going to tell you how.
|
||||
|
||||
(about://ed-guloien)
|
||||
I'm a Senior Software Developer,
|
||||
Formerly working on the Web Platform Networking team at Mozilla.
|
||||
Currently at Quantum Bridge working on Distributed Symmetric Key Exchange
|
||||
Interested in privacy, security and systems programming
|
||||
Currently writing rust full time Quantum Bridge working on Distributed Symmetric Key Exchange.
|
||||
|
||||
(Interop 2025)
|
||||
For the unfamiliar there is an initiative to improve web compatibility
|
||||
by improving pre-selected Web API implementations across all browsers.
|
||||
It's called Interop.
|
||||
And a hundred years ago, for Interop 2025, I implemented the URLPattern Web API.
|
||||
There is an initiative to improve web compatibility by improving Web API implementations
|
||||
across the major browsers.
|
||||
It's called Interop and it happens every year.
|
||||
And a hundred years ago, for Interop 2025,
|
||||
I implemented the URLPattern Web API.
|
||||
|
||||
(URLPattern Web API)
|
||||
URLPattern is basically pattern matching supporting ECMAScript Regex
|
||||
for URLs and their components.
|
||||
From Web JavaScript we construct a pattern and match strings against it.
|
||||
URLPattern is basically pattern matching for URLs and their components.
|
||||
We can construct a pattern object and match strings against it.
|
||||
|
||||
(Denoland crate and Firefox)
|
||||
Luckily for me there is an existing open source implementation by Denoland, written in rust.
|
||||
So all I have to do is figure out how to incorporate it into Firefox.
|
||||
Luckily for us there is an existing open source implementation by Denoland, written in rust.
|
||||
So all we have to do is figure out how to incorporate it into Firefox.
|
||||
This is Firefox's Fission Architecture,
|
||||
it isolates web content from other web content, roughly by origin.
|
||||
And we have the main process handling orchestration and networking.
|
||||
it isolates web content from other web content.
|
||||
We need URLPattern everywhere:
|
||||
* for each content process
|
||||
* for each web content process
|
||||
* and for Compression Dictionaries in the main process.
|
||||
So we add it to the very common libXUL library within Firefox.
|
||||
So we add it to libXUL, a common library within Firefox.
|
||||
|
||||
(WebAPI call flow to crate)
|
||||
We fork Denoland's crate by vetting and vendoring it in to libXUL, inside gkrust.
|
||||
And that compiles just fine.
|
||||
But Firefox's Browser Engine, Gecko, is mostly C++.
|
||||
* So we tell the build system about our FFI glue crate
|
||||
* We use cbindgen to generate the headers required for compiling C++ against rust.
|
||||
* Then generate JS-callable-C++-bindings from a webIDL file
|
||||
* And implement the DOM wrapper that forwards the call to our glue crate.
|
||||
We fork Denoland's crate by vetting, vendoring and telling the build system to compile it.
|
||||
This works just ffine.
|
||||
But Firefox's Browser Engine is mostly C++ and we're missing a call path.
|
||||
* So we generate JS_callable C++ bindings from a webIDL file
|
||||
* Implement a DOM wrapper that will forward the calls to our gloue crate
|
||||
* And Tell the build system about our FFI glue crate
|
||||
* It uses cbindgen to generate headers for C++ compilation against rust
|
||||
* And include a C++ convenience wrapper and make our rust call the crate
|
||||
|
||||
(UrlPattern crate API)
|
||||
Then we call the crate from our rust glue.
|
||||
The crate API exposes a trait called RegExp and a few functions to go with it.
|
||||
We simply implement trait, and call the functions to create patterns and match against them.
|
||||
|
||||
(Glue Crate)
|
||||
Easy Peazy,
|
||||
Easy Peazy, right?
|
||||
well,
|
||||
not so fast.
|
||||
|
||||
(Reality Sets In)
|
||||
Non-POD objects need to be passed-by-reference across the FFI.
|
||||
* And since our common C ABI doesn't have references, cbindgen degrades our references to raw pointers.
|
||||
* And if the object exposes internal types unknown to the other side you need an opaque pointer (a void pointer) to hide those details.
|
||||
* This leads to unsafe, pointer casts, dereferences, return parameters and so on.
|
||||
Similarly we use pointers to represent options, or write wrapper bindings to hide the gory details.
|
||||
But sometimes we are lucky and can use specialized FFI types to that can handle the ownership model difference between C++ and Rust
|
||||
* And if the object exposes internal types unknown to the other side you need an opaque pointer to hide those details.
|
||||
* This leads to all sorts of unsafe pointer voodoo
|
||||
|
||||
Similarly, to represent options we use pointers, or write wrapper bindings to hide the gory details.
|
||||
But sometimes we get lucky and find a specialized FFI type that can handle the ownership model difference between C++ and Rust
|
||||
|
||||
(Pattern re-use)
|
||||
We get that working and quickly notice that
|
||||
Pattern construction is the most expensive part of using URLPattern.
|
||||
We cannot feasibly do it on every match.
|
||||
So we cannot feasibly do it on every match.
|
||||
* So to save some cycles we pass the pattern object to the closest persistent object,
|
||||
* all the way back in the generated DOM bindings,
|
||||
* subjecting our pattern object to further marshaling across the ownership models.
|
||||
But with that done, when the user requests a match or closes the page,
|
||||
we pass the pattern to the rust crate for use or deletion.
|
||||
* and write the additional marshaling to do it.
|
||||
With that done, when the user requests a match: we pass the pattern along to the crate.
|
||||
To avoid memory leaks, when the DOM binding goes out of scope the pattern is destroyed by it's rust creator.
|
||||
|
||||
(99.8%)
|
||||
If you can get past all that,
|
||||
If you get this far
|
||||
You're pretty much there, with decent performance.
|
||||
But if you want to go all the way you have to know
|
||||
But if you want the whole banana, you have to know
|
||||
* that rust::regex is not EcmaRegex compliant
|
||||
* and the urlpattern crate uses rust::regex by default.
|
||||
Luckily for us, we're in Firefox,
|
||||
we already HAVE an EcmaRegex implementation living in the SpiderMonkey Javascript engine
|
||||
we already HAVE an EcmaRegex in SpiderMonkey, the Javascript engine
|
||||
|
||||
(Spidermonkey Challenges)
|
||||
But it comes at the cost of toil.
|
||||
We write similar FFI going the back to C++ to access SpiderMonkey.
|
||||
But this API was not designed for C++ use.
|
||||
* It requires JS context, which we lost touch with through the marshaling.
|
||||
* It has a completely different memory model using Garbage Collection.
|
||||
* A typical Web JS runtime can be interrupted to prioritize other JS.
|
||||
* AND it uses UTF-16 by default, unlike Rust's UTF-8.
|
||||
* It requires JS context, which we lost through all the marshaling.
|
||||
* It uses Garbage Collection.
|
||||
* Calling JS can be interrupted to prioritize other JS.
|
||||
So we cast some spells:
|
||||
* we spin up a JS context,
|
||||
* we prevent Spidermonkey from interrupting it's execution,
|
||||
* we root the objects to a context that will prevent the GC from marking them for deletion
|
||||
* we prevent Spidermonkey from interrupting execution,
|
||||
* we root the objects to a context that is safe from GC
|
||||
* AND convert between UTF-8 and 16 as needed.
|
||||
|
||||
And if you do all that...
|
||||
|
||||
(Phew!)
|
||||
Phew! All done.
|
||||
Now you can add your own crates and WebAPI's
|
||||
to an open source browser.
|
||||
|
||||
(references)
|
||||
You're done.
|
||||
Now you can add your own crates and Web API's to your favourite open source browser.
|
||||
|
||||
Reference in New Issue
Block a user