8 ms·
WASM by example
- Sponge5 3y agoAn instruction set that is supported by all major browsers sounds enticing. I have tried the hello_world demo with Emscripten a couple years ago and was stumped that the generated page had multiple megabytes. In the first example in this page, I read This will output a pkg/ directory containing our wasm module, wrapped in a js object. So I'm guessing that the result is the same. Why is it so? Hello world requires a print function, which I suppose needs a small subset of some implementation of libc. Why so much space? Why the need for a .js object? Shouldn't we be bypassing the JS engine?
- nikki93 3y agoHello world just needs to call console.log, so doesn't need libc. Here's an example that builds without libc / emscripten to produce a very small wasm hello world: https://github.com/nikki93/cxx-wasm-freestanding https://github.com/nikki93/cxx-wasm-freestanding There's actually some other stuff in there right now but console.cc is the main thing -- it calls consoleLog which js exposed to wasm from the js code at https://github.com/nikki93/cxx-wasm-freestanding/blob/master/index.html#L50 https://github.com/nikki93/cxx-wasm-freestanding/blob/master... . You do need some JS code that asks the browser to run the wasm blob. You can't eg. just have a script tag that refers to a wasm blob yet. libc does help with things like having an allocator or string operations etc., or for using C libraries that use libc. And that's where emscripten becomes helpful. Browser functionality like the console or making html elements is exposed through JS interfaces, and the wasm needs to call out to those. But they may be directly exposed to wasm later (or they may already be at this point in new / experimental browser features).
- itslennysfault 3y agoThe hello world in this guide doesn't actually use console.log at all. It adds 2 numbers and sets the page content to the result. All it does is expose an add function from rust and call it from the javascript side.
- davexunit 3y agoCan't speak to the size issue as I don't use emscripten, but I agree that most WASM output is waaay too large. Regarding JS, you need a small amount of JS to bootstrap your WASM program. In the browser, JS is the host environment and WASM is the guest. The host instantiates the WASM module and passes in capabilities that map to the module's declared imports. https://developer.mozilla.org/en-US/docs/WebAssembly/Using_the_JavaScript_API https://developer.mozilla.org/en-US/docs/WebAssembly/Using_t...
- one-more-minute 3y agoYou need (a little) JS to run Wasm in the same way you need (a little) HTML to run JS; it's a hosted platform. JS handles loading and invoking the wasm code, and because it's close to a pure instruction set there's very little you can do without calling JS APIs, which in turn requires support code to translate across the boundary. The WASI project specifies wasm-native APIs (modelled on posix) for running locally without JS, so you could imagine something similar for the browser. But the complexity of the DOM is forbidding. I've not tried Emscripten hello world for a while, but I imagine it depends on things like optimisation level, dead code elim etc. In general to compile C code you'll need a malloc, string support and so on as you say. You can make the wasm file tiny if you lean on JS strings, but that increases the amount of support code again. Languages other than C will have an easier time reusing parts of the JS runtime (like strings or GC).
- josephg 3y agoYeah. And hello world is (thankfully) much smaller now than it used to be. Bigger than you think if you use printf, which is a quite complex C function. But at a guess, 10kb or something including support files. There are some great guides and tooling around to help shrink wasm size. Eg for rust: https://rustwasm.github.io/docs/book/reference/code-size.html https://rustwasm.github.io/docs/book/reference/code-size.htm...
- brabel 3y agoTo really understand WASM, you should try to write it by hand! That's right, it's possible, it even has a text format that all WASM runtimes let you run directly. Check this out: https://blog.scottlogic.com/2018/04/26/webassembly-by-hand.html https://blog.scottlogic.com/2018/04/26/webassembly-by-hand.h... Once you know what WASM really does, it's obvious why you need JS (or whatever the host language is in your runtime, which could be anything) to provide anything related to IO and why there's zero chance you'll get DOM access as it currently stands... until they finally finish off specifying a whole lot of APIs (they did GC already which was pretty fundamental for that to work, but there's many more things needed for complete access to IO and DOM). If you use a compiler like Rust, it's going to include WASI which is a sort of POSIX for WASM (and currently completely underdefined, just try to find the spec and you'll see it's mostly being made up as implementers go), which is why you'll get ridiculous amounts of code into your WASM file. If you write it by hand, importing some made up function like `console_log` which you then import from WASM, then your WASM should be just a few bytes! Literally. I wrote a little compiler to do this as it's not hard to generate WASM bytecode, but to make anything useful is very painful due to the complete lack of specifications of how things should work (e.g. to print a string is actually very hard as you'll just be able to give JS or your host a pointer to linear memory, and then you need to write the actual bytes - not UTF or even ASCII characters in WASM itself - to linear memory, which the JS then has to decipher to be able to call its own `console.log()`)... so I am waiting (a few years by now) until this improves to continue.
- flohofwoe 3y agoYou can get a simple WebGL2 WASM app down to a couple of kBytes, for instance this downloads 30 KBytes in Chrome: https://floooh.github.io/sokol-html5/clear-sapp.html https://floooh.github.io/sokol-html5/clear-sapp.html (1.4 KB for the .html, 8.8 KB for the .js, 14.5 KB for the .wasm - and a whopping 5.5 KB for the 404 page returned by Github pages for the missing favicon - wtf...) The .js file is basically glue code between the WASM code and the browser runtime environment. Without the Emscripten "convenience runtime" you can also go smaller, but at a few dozen KBytes more or less it's pretty deep in diminishing returns territory. The C library is provided via MUSL these days (in Emscripten). But there's a small 'syscall layer' which is implemented in Javascript (basically if you want to run in the browser and access web APIs, at some point you need to go through Javascript).
- vinc98 3y agoGreat guide to getting started. I wonder if one day WASM will replace Javascript in the browser.
- Dudester230602 3y agoThat's the dream. Render to WebGL/Canvas. Bypass CSS + HTML. Make web actually open to other languages by putting them on a very common ground.
- _lvbh 3y agoI would rather not have JS replaced. It would really hurt the ability of users to poke through the code and tweak stuff as they like.
- ravenstine 3y agoThere isn't anything actually wrong with JavaScript in 2023, either. The idea that it needs to be replaced stems from countless failed attempts to shove a bunch of crap into the client with a bunch of frameworks and without a shred of actual engineering discipline. Trust me when I say that, if web apps become commonly written mainly in other "scalable" or "type-safe" languages, your average software developers will find a way to screw that up as much as they have with today's web, if not worse than that. WASM is cool, but I don't see any reason to get rid of JS. There's value to having a lingua franca of JIT interpreted code with a standard UI toolkit, and I think those who point out how "insufficient" the DOM is and how "slow" and "unsafe" JavaScript is are simply wrong. They both do their jobs exceedingly well when idiotic and theological ideas are not simply thrown at them by software developers obsessed by convenience over soundness of design.
- QwertyPi 3y ago> There isn't anything actually wrong with JavaScript in 2023, either. The semantics of the language can be quite complex and it took decades for browsers to agree on them for most use cases. WASM arose out of a failure of browsers to figure out ways to deprecate this—mostly unnecessary—complexity. > The idea that it needs to be replaced stems from countless failed attempts to shove a bunch of crap into the client with a bunch of frameworks and without a shred of actual engineering discipline. The same can be said about the implementation of javascript in browsers as well. We're stuck with it regardless, but our reliance on javascript and its myriad interactions with html and css functions much the same way for large browser vendors as regulatory capture does for large corporations at the state level.
- ge96 3y agoThat simple add example, huh... makes sense but idk why it's surprising to me. The imported non-js language is interactive (can take parameters at runtime). neat, thought it was just a static thing you embed/can't change.
- csjh 3y agoIf it couldn't take parameters what point would there be in it?
- ge96 3y agoIt reminds me of how you can export a 3D model and inject it into a webpage via ThreeJS/.glb file. Granted this one too, you can individually import the parts/move them for animation. (it's not passive/just working like an iframe)
- nonethewiser 3y agoAnother interesting use case for WASM is making cross-language libraries. Write a library in one language, compile to WASM, and import into any other language. Im not that familiar with WASM but isnt that pretty damn awesome? Feel like I must be missing something because that seems like the bigger deal but it seems like an uncommon use-case.
- rockwotj 3y agoYeah the component model the bytecode alliance is pushing defines a canonical ABI and codegen tools to make this easier (also separating memory from these components so a bug in some random C library doesn’t have a blast radius outside the processing it does in its library boundary)
- never_inline 3y agoYour post got me wondering, what advantage might it provide over an FFI? Does WASM ABI define higher level common primitives than C?
- lesuorac 3y agoIf it ends up becoming more similar to LUA then a big advantage is that the WASM code won't randomly read your harddrive and send your bitcoins to North Korea unless you explicitly gave the WASM code disk/network permissions.
- brabel 3y agoLua allows full control over which APIs you want to expose to a script you embed in your application. With some effort you can even expose only a constrained version of the `os` module for example which only lets you access a few resources. Why do you believe WASM can do better here? In fact, as far as I know , there's nothing in WASM that lets you sandbox it yet once you've given it WASI access (unless you're talking about host specific features, which are NOT part of WASM spec itself).
- 3y ago
- 3cats-in-a-coat 3y agoI'm definitely going to read through it. But one thing immediately made an impression on me: CTRL+CLICK doesn't open links in a new tab, but the input event is hijacked and it opens the page in the same tab. The same with other modifiers like SHIFT+CLICK, ALT+CLICK etc. The feeling is one of losing control of your computer, like the site is trying to keep you trapped in a tab. Very unpleasant. I know you don't mean it this way. And I appreciate it's loading the pages inline without reloading, but it's absolutely not worth it, if people have to constantly fight years, decades of muscle memory in order to use the site. Please fix this! Links should act like links.
- deleted 3y ago[deleted]
- mark_and_sweep 3y agoAlso, the back button doesn't work properly for navigations on the site.
- 3cats-in-a-coat 3y agoIndeed. There are bugs in the history management, for example it pushes false entries like index.html# next to index.html which were not navigated to. So if you click back/next it sometimes works, sometimes it doesn't. And when it works, it doesn't show the page where you had scrolled it to (the native behavior) but scrolls you always to the top, so you lose context. Also if you right-click a link to open it in a new tab from the menu, it opens a new tab... but at the home page, instead of the link. I have to say... pretty bad experience start to end :(
- flohofwoe 3y agoShameless plug: I wrote a similar from-scratch guide a couple of days ago about how to get WASM debugging working in VSCode both for "command line" and browser apps using the new WASM DWARF Debugging extension for VSCode: https://floooh.github.io/2023/11/11/emscripten-ide.html https://floooh.github.io/2023/11/11/emscripten-ide.html
- factormeta 3y agovery nice! Can this be done with Java and/or Rust? Or does it only work with C ATM?
- flohofwoe 3y agoRust should work if the Rust compiler can generate DWARF info for WASM targets. Java most likely not.
- ilrwbwrkhv 3y agoWasm will never take off. It is too hard to get started for it to be meaningful. Maybe for games or things like figma it will work but having to use rust means it will never ever be mainstream.
- yett 3y agoYou can use Kotlin, C# or bunch of other languages
- flohofwoe 3y agoMaybe a compiled-to-wasm Typescript lookalike is more your thing? https://www.assemblyscript.org/ https://www.assemblyscript.org/
- 3cats-in-a-coat 3y agoI think you're projecting a little. WASM is already in heavy use. It's obviously not intended for casual scripting. So if you find it too hard, you're not the target. But you're not representative of all developers in general. Also, it's not intended, usually, for you to actually write WASM directly. It's a compilation target. You can import C++ libraries, Rust libraries, and so on, and use them from JavaScript. Or you can write your own C++ code and run it in a browser. You write WASM directly mostly when you write compilers. Have you written compilers? Well let me tell you it's definitely not simpler than WASM. I'm under the impression you may think WASM is trying to be a replacement for JavaScript. It's not. They play together. In fact, you can think of WASM as a new JavaScript API, like we have WebGL or WebGPU. It's just that. WASM can't do anything by itself. It's just math in a block of memory. But... it's fast math.
- xcv123 3y ago> Wasm will never take off. Already has taken off. > having to use rust You don't have to use Rust. There are wasm compilers for dozens of languages. C, C++, D, Java, C#, F#, Python, Go, Lua, PHP, etc.
- owenpalmer 3y agoWhen WASM has direct access to the dom, everything will change.
- sonicanatidae 3y agoI tried WASM in an FPS and I have to say, I'm not a fan of reaching across half the keyboard when I need to slide right. ;) Edit: looks like someone's sense of humor was taken out to a shed and shot. You enjoy that.
- deleted 3y ago[deleted]
- w10-1 3y agoThe examples seemed clear enough to read (I did not test them), but I felt than even when teaching by example there needs to be more overview and explanation. I.e., I would prefer an overview of WASM structure and use with examples, rather than just the examples. (I have some (but limited) experience using WASM.) As for the utility of wasm, note also that Cloudflare workers can run WASM on edge servers [1], and that the Swift community has some support for compiling to wasm [2]. I've never really understood how wasm could do better than java bytecode, but I've been impressed with how much people are using lua and BPF. More generally, in a world of federated programming, we need languages client can submit that providers can run safely, without obviously leaking any secret sauce -- perhaps e.g., for model refinement or augmented lookup. [1] https://github.com/cloudflare/workers-wasi https://github.com/cloudflare/workers-wasi [2] https://github.com/swiftwasm https://github.com/swiftwasm
- scroot 3y agoThere is also another book in the works that has you grapple with WASM itself directly throughout by building your own compiler. It's called WASM from the Ground Up [1]. It's still in progress, but I have really found it informative so far [1] https://wasmgroundup.com/ https://wasmgroundup.com/
- KRAKRISMOTT 3y agoCan you add a category for raw WebAssembly in the S-expr syntax? I think it would be helpful to understand how things work under the hood. WebAssembly is a very high level assembly language and somewhat different from your usual x64/ARM/RISC-V since it's a stack machine.
- alwaysal44 3y agoHere's an example of a Unity demo running using WASM and WebGPU, posted to HN: https://news.ycombinator.com/item?id=38281040 https://news.ycombinator.com/item?id=38281040
- neilv 3y agoI was wondering why my burst of middle-clicking links into tabs didn't actually open those pages. <a href="#" onclick="goToExample('examples/hello-world', 'hello-world', 'assemblyscript', 'en-us')" >Hello World!</a >
- afgrant 3y agoEveryone: Please stop using ‘#’ as an href placeholder. Don’t make your ‘<a>’ elements rely on events. If you want to replace their events with others, go for it. But please make them work at the base level.
- subarctic 3y agoLooks like the code is here if you want to send a PR: https://github.com/torch2424/wasm-by-example https://github.com/torch2424/wasm-by-example
- deleted 3y ago[deleted]
- l72 3y agoYes, this killed navigation and pressing back. I was on example 4 in rust, and changed it to c++ to look at the differences. Instead, it showed the intro page in c++ and pressing back does nothing, as the history is completely broken. There was no easy way to jump back to example 4 in rust. I had to change it to rust and click through each example again.
- Snelius 3y agoSuch annoying. I can't find anymore about wasm assembler compiler.
- ceeam 3y agoabout:config javascript.options.wasm -> false I don't see how WASM isn't everything that Web was NOT supposed to be. Minified/obfuscated JS is bad enough already.