Consider dropping Lox's WASM
Lox is written in Rust and our UI is written in JavaScript.
The two of them need some glue, and currently we're using a WASM blob. However, in !1090 (merged) and !1032 (merged) we've seen that sometimes this might be more complicated than using other integration mechanisms.
Status quo: the WASM blob
Pros
- More generic: WASM is more generic than solutions that target Firefox/Tor Browser.
- Is it something we really need? Are there going to be other consumers?
- Is it really that generic? If I understand correctly, there's a Rust crate only for this integration, and is actually modeled around what we need in Tor Browser
- Possibly ligther? The compiled blob is a few hundres of kB, and once compressed is less than 300kB. However, we don't now the details of the native code
- Runs in the browser's sandbox (possibly, I'm not sure, since it's chrome JS)
Cons
- Not tailored for our specific needs, exporting types isn't trivial, so (currently) we constantly pass JSON strings
- Not many other examples in Firefox, only translations AFAIK. So, we might be using this WASM module in a wrong way
- Updating the module is hard: we generate it through tor-browser-build and then version in tor-browser.git manly for development purposes
- We need to patch
wasm-bindgen
(and maintain the patches)
Possible alternatives
Firefox already uses Rust a lot, so there are at least two possible alternatives to keep doing most of the thing in Rust, and then expose a minimal set of specific functions to integrate with our JS.
The main alternatives are XPCOM and UniFFI. Both would involve writing at least a manifest/interface file to create the bindings between languages. I think both would also need some Rust code to simplify what you pass to the other language.
XPCOM
With XPCOM I think we'd have to create a type, e.g. LoxService
.
The current JS module could own an instance of this type, and initialize/shutdown it, and maybe do some syntax sugar for the JS callers.
Apart from that, we could move evrything to Rust.
Depending on how much data we'd need to pass back and forth, we could need to implement more or less custom types. Passing things like strings, numbers, booleans and similar will be easy. Also broadcasting events will be possible.
It'd be very integrated with Firefox, so it would be able to mess with preferences and I think also with timers for the background checks.
I think starting such integration will require some XPCOM knowledge, so I think someone from the apps team with some XPCOM knowledge could implement the most XPCOM-my details, and then let possibly someone from the AC team implement some of the actual features.
Notice that network requests in Firefox are async, but XPCOM stuff works mostly with callbacks, AFAIK, I don't know if the support for async
Rust has improved.
@ma1 and @jwilde are the probably the most expert in this area, but Morgan and me have also inevitable worked a bit with XPCOM things.
UniFFI
UniFFI is an alternative to XPCOM, and can generate bindings for many languages (JS, Kotlin, Swift, ...).
It also involves some manifest/interface, but I don't know the details.
@brizental worked with UniFFI IIRC, maybe she can help or tell us about her experience.
Including the code in the source tree
At this point, we'd include Lox's source code directly in tor-browser.git, either through git submodules, or with vendoring.
Firefox has vendoring facilities.
The thing that worries me the most is that audits with cargo vet are enforced.
I don't know exactly what they involve.
@jwilde might have some experience also about this.
I think we'll have to go through this process anyway when implementing Arti, so it could be very useful for us to start earlier with another project.
/cc @onyinyang @cohosh