Oxidizing Source Maps with Rust and WebAssembly(hacks.mozilla.org) |
Oxidizing Source Maps with Rust and WebAssembly(hacks.mozilla.org) |
Wow. Some people have been wondering if Rust has a "killer app", but this could be it. Right now WebAssembly only supports non-GC languages (so C, C++, and Rust), and of those three Rust is the easiest to get started with. It looks really appealing.
This stuff is a bit hard to get into at the moment, as it's early days, but as things coalesce, we're also working on making everything well documented and super-smooth to use. It's already reasonably easy, but we want it to be trivial.
[Disclaimer : i'm old enough to dream in K&R C and later ANSI C, and then C++, but am more than enthused about Rust, so a genuine question]
Edit: Some of the numbers:
Original JS: just under 30,000 bytes.
Closure compiler minified JS: 8,365 bytes.
New combined JS and WASM: 20,996 bytes
Roughly half of the WASM output is JS and half of which is WASM, since not all components in the original JS were replaced, just a specific subset. There is some duplication of functions that both the remaining JS still uses and the new WASM code does as well. Rust diagnostic and error messages appear to still be present inthe data section although unusable, so could be cleared out with better tooling.
1. `shift` can grow large, and an overlong left shift will panic in Rust. I expect an input like "gggggggC" to crash.
2. `accum >>= 1` is wrong because it rounds down. It needs to be a round-towards-zero: `accum /= 2`.
3. `accum` is a 32 bit int which is too small. It needs to be larger so it can represent -2^31 in sign-magnitude form.
We've already fixed some of these issues[0] but I didn't update the code snippets in the article -- woops!
[0] https://github.com/tromey/vlq/commit/3b41a2b6c778ce476eaaa28...
One thing that stuck out to me was the exploded-struct callback mechanism for reporting Mappings back to JS. I've also been struggling to handle the low-bandwidth interface between JS and WASM. That wasn't a strategy I'd considered, but it's pretty neat.
It's simple enough and will work in this case, but unfortunately doesn't generalize very well. I've been exploring using well-defined binary encoding for this purpose (specifically Cap'n'Proto, but Protobuf or another binary encoding would work, too).
See an example I put together: https://github.com/couchand/rust-wasm-capnproto-example. I'm definitely going to go back and clean that up with some of the FFI patterns from this article.
Vec::<usize>::from_raw_parts(capacity_ptr, size, capacity);
But size is wrong. size here is the number of bytes that JavaScript instructed Rust to allocate. It's not the size of the Vec::<usize>.This should be harmless as the resulting Vec is immediately deallocated, so the only thing that size is used for is deinitializing values, and since the values are usize there's nothing to deinitialize. But it's still technically incorrect.
Fix is over in https://github.com/fitzgen/source-map-mappings/pull/15
> which IIRC requires unsafe access as it's not thread-safe
Yes, and also has no guarantees against mutably aliasing and re-entry.
Note that wasm currently has no shared memory threading (just message passing via FFI through JS and workers), so thread-safety isn't an issue to be wary of here, just re-entry.
emscripten is no longer required for Rust to target WASM. There is a new target of wasm32-unknown-unknown. This project gives you quick bootstrap instructions into WASM with Rust:
https://github.com/koute/stdweb
Very quick to get started with, and the examples get you going quickly. I just used it yesterday (nothing fancy), and everything worked right out of the box.
C is so small a language that you can learn it much quicker. The problems surface later on.
Unless what you are doing is not fit for what guarantees Rust gives you, the compiler should just be a crutch in case you missed a step.
In fact if I could, I would like that writing in C was prohibited by law to permit holders only, the jury being rob pike and richard stallman themselves!
I think it's hard for those who carry "mindset-baggage" from C/C++. My first attempt at Rust was a failure mostly because I thought it was sort of a "weird C/C++".
It's hard to escape the mindset of languages we're used to!
> At the same time a lot of the error messages are very cryptic
You should file bugs! We care deeply about the legibility of error messages, and the whole --explain system is there to try and go above and beyond.
Next time I do some Rust I will. I also need to check out that --explain system. I didn't see that when learning Rust.
> error[E0384]: cannot assign twice to immutable variable `x`
That E0384 is a link in the browser. Click it and you go to https://doc.rust-lang.org/error-index.html#E0384 which has a longer version of this error.
On the command line, you can run `rustc --explain E0384` and it'll print out the same text to the terminal.