class: middle, less-space, title-bg, title, jskongress-title, jskongress # WebAssembly for the Rest of Us ## Wasm Kongress 2017, Munich ## Jan-Erik Rediger — [@badboy_](https://twitter.com/badboy_) — 2017-11-14
??? --- class: middle, less-space, title-bg, title, jskongress-title, devroadshow # WebAssembly for the Rest of Us ## Mozilla Dev Roadshow, Munich ## Jan-Erik Rediger — [@badboy_](https://twitter.com/badboy_) — 2017-11-15
??? --- layout: true --- class: center, middle
Activate Demo
??? *open demo on main screen* *switch to webcam* *switch to super edge* *turn off javascript* --- class: center, middle, less-space, introduction
Jan-Erik Rediger
@badboy_
Organizer
Work / Tech Speaker
??? Hi, I'm Jan-Erik. In the Internet I'm know as badboy underscore I do organize stuff, such as meetups and conference for the programming language Rust I am working as a software engineer, but today I'm here in my function as a Mozilla Tech Speaker. --- class: middle, center, wasmlogo ![](media/web-assembly-logo.svg) ??? and as such I'm here to tell you about WebAssembly. The live video demo you saw before was already using WebAssembly in my browser That was running WebAssembly. Now that you're here at the conference about the future of JavaScript, you probably already heard about it --- class: center, middle, wasmlogo ![What is WebAssembly?](media/web-assembly-questionmark.svg) ??? So: what is webassembly? For that ... --- class: center, middle # History time ??? we have to step back in time a bit --- class: jslogo # 1995 ![](media/js.jpg) ??? Back to the early days when websites were simple. Then Javascript was invented in 1995 People used it to extend their websites with dynamic features Back then JavaScript engines were simple interpreters By today's standards slow, but good enough for the language and the task at hand People started to use it more and more and so browsers became better at running it but at some point it was too limited, people wanted to do more stuff not supported in a browser --- class: jslogo # 2000s ![](media/adobe_flash.svg) ??? so we got flash apps and java applets in the browser they didn't integrate into the browser as nice, but had required functionality but soon we learned of all the disadvantages using them we also learned about what it would require to use javascript again and so people build more and more web apis that were implemented across browsers --- class: jslogo # 2008 ![](media/v8.png) ??? Then JavaScript got really fast with the release of JIT compiler engines such as v8 And we got huge web applications People moved more and more stuff to the web They even translated existing code to JavaScript to run it in the browser yet again people experienced problems Full JavaScript wasn't the best target for compilation from other languages --- class: jslogo, asmjs # 2013 ## asm.js ### an extraordinarily optimizable, low-level subset of JavaScript .footnote[\* slide design adapted from [asmjs.org](http://asmjs.org/)] ??? In 2013 an approach to formalize a subset of javascript began By now this is known as asm.js asm.js was specified as a subset of JS with certain assumptions, so an engine can detect and optimize it and at best compile it to native code Two of the main features are type annotations for functions, types and expressions. and a flat memory space for data Let's look into the details, as they are similar to what we have in WebAssembly now --- class: code, big, nospecialhighlight # Type Annotations in asm.js ```javascript function add(x, y) { ` ` ` ` return (x + y); } ``` ??? If you write JS, you know you don't need to explicitely name your types. the engine will infer them from usage but that makes things more complex to optimize see this function for example, simple addition of two variables it used the plus operator on x and y if those are numbers, it will add them but if those are strings, it will concatenate them what if one is a number and the other is not? fun things happen! --- class: code, big # Type Annotations in asm.js ```javascript function add(x, y) { `x = x|0;` // <- parameter type annotation y = y|0; `return (x + y) | 0;` } // ^- return type annotation ``` ??? > So now we added a binary-or 0 to the input variables x and y and to the return expression. With this simple annotations to the code, things change. a binary-or only makes sense on integers, and there it doesn't change anything with these changes we know it only makes sense to handle integer input if annotated as asm.js code the browser can take this code and compile it down to the add instructions for integers on your CPU Firefox actually does this and even Chrome optimizes it similar to some extent This brings a significant speedup for such code, making it possible to run at near-native speed --- class: imgfull # Linear memory access ![](media/memory.svg) .footnote[from ["Introduction to WebAssembly"](https://rsms.me/wasm-intro) by Rasmus Andersson] ??? the other thing asm.js uses is putting all used data into a linear memory buffer normally you don't worry about your memory usage. the JS GC will eventually collect the garbage and free memory but this means it will have to stop your code to collect the garbage this is quite unpredictable and might hurt performance significantly so asm.js simply uses one large buffer from the point of view of the engine it always looks like it is in use and will not be freed However, your code is free to put data anywhere in this buffer Management of this buffer space is up to the code. If your familiar with C, this looks familiar and it actually maps quite good to how C handles memory --- class: code, increased, hiddenslide # Linear memory access ```c size_t strlen(char *ptr) { char *curr = ptr; while (*curr != 0) { curr++; } return (curr - ptr); } ``` ??? In C you can use the heap and allocate memory from it. You get back a pointer to requested memory and can write to it. Take this naive implementation of the string length function for example it gets a pointer to some memory location and simply increases it until it hits a null byte the difference to the start is then the length of the string --- class: code, increased, hiddenslide # Linear memory access ```js function strlen(ptr) { ptr = ptr|0; var curr = 0; curr = ptr; while (HEAP8[curr]|0 != 0) { curr = (curr + 1)|0; } return (curr - ptr)|0; } ``` ??? translated to asm.js it looks like this our ptr becomes a simple index into the heap memory --- class: code, increased, hiddenslide # Linear memory access ```js function strlen(ptr) { ptr = ptr|0; var curr = 0; curr = ptr; * while (HEAP8[curr]|0 != 0) { curr = (curr + 1)|0; } return (curr - ptr)|0; } ``` ??? translated to asm.js it looks like this our ptr becomes a simple index into the heap memory Accessing data simply indexes into this buffer So when you take your C code and compile it to asm.js, its heap will simply be emulated by that linear memory buffer don't worry though, the toolchain will make sure you have appropiate memory management --- class: wasmlogo # 2015 ![](media/web-assembly-logo.svg) ??? In 2015 then folks from all browsers vendors sat together and thought about what an actual successor to asm.js would need to look like and webassembly was born --- class: center, middle, wasmlogo ![What is WebAssembly?](media/web-assembly-questionmark.svg) ??? so what is webassembly? it's a lot of things --- class: code, increased # What is WebAssembly? * Binary executable format for the web ```binary 00 61 73 6d 01 00 00 00 01 86 80 80 80 00 01 60 01 7f 01 7f 03 82 80 80 80 00 01 00 04 84 80 80 80 00 01 70 00 00 05 83 80 80 80 00 01 00 01 06 81 80 80 80 00 00 07 91 80 80 80 00 02 06 6d 65 6d 6f 72 79 02 00 04 68 61 6c 66 00 00 0a 8d 80 80 80 00 01 87 80 80 80 00 00 20 00 41 01 6d 0b ``` ??? It is a new binary executable format for the web It allows to take your code written in another language, turn it into WebAssembly and then run it in your browser. --- class: code, increased # What is WebAssembly? * General purpose virtual architecture ```binary get_local $0 i32.const 2 i32.add i32.const 42 i32.eq return ``` ??? It is also a general purpose virtual architecture It gives you a few operations and their semantics that is not directly bound to the architecture of your machine, but can be translated to it very easily While intended for the web, it is not bound to that. It allows embedding in other engines Which is now used to re-use existing JavaScript engines to execute it --- class: wasmlogo # What is WebAssembly? * Compiler target ![](media/compiler-process.svg) ??? It's best to think of it as a compiler target. Take your existing code in C, C++ or Rust throw it into the compiler and out you get a WebAssembly module ready to run in your browser at least that's the idea. right now it's a bit more trickier to get something running --- class: wasmlogo # What is WebAssembly? * Open standard ![W3C](media/w3c-cg.svg) ??? But the best thing about it: it is an open standard It's developed in a W3C community group, out in the open. The group was launched over 2 years ago. The first version of WebAssembly was then finalized in Februrary this year --- class: middle, center, browserlogos ![](media/firefox.svg) ![](media/chrome.svg) ![](media/edge.svg) ![](media/safari.svg) .footnote[[WebAssembly support now shipping in all major browsers](https://blog.mozilla.org/blog/2017/11/13/webassembly-in-browsers/)] ??? When I say open standard, what I also mean is: Folks from all major browser vendors are involved and are adding support for it. It is enabled across all 4 major browsers firefox, chrome, edge and safari all have support for it --- class: underlinedstrong, centeredanswer # What is WebAssembly __not__? ??? when talking about WebAssembly we also need to think about what WebAssembly is not --- class: underlinedstrong, centeredanswer # What is WebAssembly __not__? ## Replacement for JavaScript ??? It is definitely not a replacement for JavaScript, but lives right next to it in perfect harmony. The majority of web applications can and will still be written in JS. --- class: underlinedstrong, centeredanswer # What is WebAssembly __not__? ## Programming Language ??? Wasm is also not a programming language by itself. It can be used as one but just as you won't write assembly today for the native world, you don't need to write WebAssembly for the web world --- class: underlinedstrong, centeredanswer # What is WebAssembly __not__? ## Target for every language\* .footnote[\* yet] ??? And Wasm is not a good target for every language out there. Its use of a flat memory space and explicit typing does not map easily to all languages. --- class: center, middle, hiddenslide # Why WebAssembly? ??? So why would we need WebAssembly? For that we need to take a step back --- class: smaller-list # Why not use asm.js? ??? With this knowledge about JavaScript in the beginning and asm.js after that you might wonder why can't we just stay with it? And indeed, there are advantages: -- .left-col[ ## Pros: * "It's just JavaScript" * It's fast ] ??? Afterall asm.js is a subset of JS and thus valid JS Every engine running JS can run asm.js, even if not optimized And where the engine DOES know asm.js, it can be optimized and can become quite fast, running at near-native speed -- .right-col[ ## Cons: * Informal spec * No speed guarantuees * Hard to extend ] ??? but there are downsides as well asm.js is a quite informal spec without baking from all browser vendors and it offers no speed guarantuees in the end it is all just JS, so it is hard to extend; that means we can't even add native 64-bit integers --- # Why WebAssembly? ??? So why do we need WebAssembly --- class: centeredanswer # Why WebAssembly? ## Smaller than asm.js ??? Even though JavaScript and especially asm.js can be already quite small when compressed, WebAssembly was designed to be even smaller for the same code. Its binary representation helps here --- class: centeredanswer # Why WebAssembly? ## Faster parsing ??? Turns out JS is quite hard to parse. WebAssembly on the other hand is straight forward. It is already compiled, so you merely need a verification step and compile it to machine code --- class: centeredanswer # Why WebAssembly? ## Freedom to extend ??? and with Wasm we now have the chance to extend it with necessary new features not available in JS --- class: centeredanswer # Why WebAssembly? ## Formal specification ??? As mentioned before, it is also an open standard with a formal specification, backed by all major browser vendors. Hopefully this means everyone will implement compatible engines --- class: nested # Use cases *
Game Engines
{
* Multimedia * Performance * Non-Web .right-box[ * Tanks Demo * Zen Garden ] ??? before taking a look how to actually use it, lets briefly look at some use cases some game engines could be compiled to webassembly and your next big 3d game can be run without installing it Some demos include a tanks game using the Unity game engine and a 3D zen garden demo --- class: nested # Use cases * Game Engines *
Multimedia
{
* Performance * Non-Web .right-box[ * Image/Video editing * Live video augmentation * CAD applications ] ??? Another interesting use case would be Multimedia applications Things like image or video editing or even live augmentation require extended features and speed --- class: nested # Use cases * Game Engines * Multimedia *
Performance
{
* Non-Web .right-box[ * Encryption * Machine Learning * Platform simulation ] ??? Wasm's performance will come in handy for things like encryption algorithms or machine learning or even simulations for your favorite game or computing platform --- class: nested # Use cases * Game Engines * Multimedia * Performance *
Non-Web
{
.right-box[ * Smart Contracts in Ethereum * DICOM (Medical Image File Format) ] ??? WebAssembly can also work for non-web use cases. For example the Ethereum blockchain has plans for using WebAssembly as the format for their smart contracts. and another thing I recently saw was an app reading an old medical file image format, which would enable it to be accessible cross-platform far more easily. --- class: wasmlogo # How to use it ## Use the compiler! ![](media/compiler-process.svg) ??? So now let me show you how to actually use it The easiest thing is: use your compiler, take your C or Rust code and compile it to wasm So far the idea. The tooling is not there right now --- class: center, biggerh2 ![](media/emscripten-logo.svg) ## open source LLVM-based compiler from C and C++\* to JavaScript .footnote.big[\* and Rust] ??? one of the best ways to get started is to use Emscripten it is a LLVM-based compiler, which takes your C or C++ code or even Rust, and compiles it to JavaScript --- class: center, biggerh2 ![](media/emscripten-logo.svg) ## open source LLVM-based compiler from C and C++\* to asm.js .footnote.big[\* and Rust] ??? or asm.js --- class: center, biggerh2 ![](media/emscripten-logo.svg) ## open source LLVM-based compiler from C and C++\* to WebAssembly .footnote.big[\* and Rust] ??? or now even WebAssembly Let's see how we can turn some C code into WebAssembly now --- class: code, big # Some C code ```c int half(int x) { return x / 2; } ``` ??? Take this small piece of code. A function called half, that takes an integer x as an argument, divides it by 2 and returns the result Not complicated, but enough to get us started --- class: code, large # Compile it (native) ```binary clang -O3 \ -c half.c -o half.o ``` ??? usually, you could compile that to machine code using clang or gcc. The output of this can then be taken into your larger application to call the half function --- class: code, large # Compile it (wasm) ```binary emcc -O3 \ -s WASM=1 -s SIDE_MODULE=1 \ half.c -o half.wasm ``` ??? Now to compile it to webassembly we will use emcc, the emscripten compiler we need to pass a few more flags so it knows what to do, but out we get a WebAssembly module in half.wasm --- class: code, increased ## Wasm (binary representation) ```binary 00 61 73 6d 01 00 00 00 01 86 80 80 80 00 01 60 01 7f 01 7f 03 82 80 80 80 00 01 00 04 84 80 80 80 00 01 70 00 00 05 83 80 80 80 00 01 00 01 06 81 80 80 80 00 00 07 91 80 80 80 00 02 06 6d 65 6d 6f 72 79 02 00 04 68 61 6c 66 00 00 0a 8d 80 80 80 00 01 87 80 80 80 00 00 20 00 41 01 6d 0b |.asm...........`| |................| |...p............| |..............me| |mory...half.....| |.......... .A.m.| ``` ??? What Emscripten outputs is this. If you do like to read binary code and know how WebAssembly encodes things you can actually read this. But don't worry, I'll explain. Every WebAssembly program is called a "module" A module consists of its imports, exports, some memory declarations and the actual code --- class: code, increased, fixhighlight ## Wasm (binary representation) ```binary `00 61 73 6d` 01 00 00 00 01 86 80 80 80 00 01 60 01 7f 01 7f 03 82 80 80 80 00 01 00 04 84 80 80 80 00 01 70 00 00 05 83 80 80 80 00 01 00 01 06 81 80 80 80 00 00 07 91 80 80 80 00 02 06 6d 65 6d 6f 72 79 02 00 04 68 61 6c 66 00 00 0a 8d 80 80 80 00 01 87 80 80 80 00 00 20 00 41 01 6d 0b |`.asm`...........`| |................| |...p............| |..............me| |mory...half.....| |.......... .A.m.| ``` ??? Each module always begins with the magic header of 4 bytes. A zero byte followed by the ASCII string for a s m --- class: code, increased ## Wasm (binary representation) ```binary 00 61 73 6d `01 00 00 00` 01 86 80 80 80 00 01 60 01 7f 01 7f 03 82 80 80 80 00 01 00 04 84 80 80 80 00 01 70 00 00 05 83 80 80 80 00 01 00 01 06 81 80 80 80 00 00 07 91 80 80 80 00 02 06 6d 65 6d 6f 72 79 02 00 04 68 61 6c 66 00 00 0a 8d 80 80 80 00 01 87 80 80 80 00 00 20 00 41 01 6d 0b |.asm`....`.......`| |................| |...p............| |..............me| |mory...half.....| |.......... .A.m.| ``` ??? It's followed by 4 bytes indicating the version. With the released webassembly we are at version 1 New features will require this version to be incremented --- class: code, increased ## Wasm (binary representation) ```binary 00 61 73 6d 01 00 00 00 01 86 80 80 80 00 01 60 01 7f 01 7f 03 82 80 80 80 00 01 00 04 84 80 80 80 00 01 70 00 00 05 83 80 80 80 00 01 00 01 06 81 80 80 80 00 00 07 91 80 80 80 00 02 06 6d 65 6d 6f 72 79 02 00 04 `68 61 6c 66` 00 00 0a 8d 80 80 80 00 01 87 80 80 80 00 00 20 00 41 01 6d 0b |.asm...........`| |................| |...p............| |..............me| |mory...`half`.....| |.......... .A.m.| ``` ??? Further down you can see the word half. That's the export section. Functions are exported by name, so you can actually find them later on from the JavaScript side --- class: code, increased, bin ## Wasm (binary representation) ```binary 00 61 73 6d 01 00 00 00 01 86 80 80 80 00 01 60 01 7f 01 7f 03 82 80 80 80 00 01 00 04 84 80 80 80 00 01 70 00 00 05 83 80 80 80 00 01 00 01 06 81 80 80 80 00 00 07 91 80 80 80 00 02 06 6d 65 6d 6f 72 79 02 00 04 68 61 6c 66 00 00 0a 8d 80 80 80 00 01 87 80 80 80 00 00 `20 00 41 02 6d 0b` |.asm...........`| |................| |...p............| |..............me| |mory...half.....| |..........` .A.m.`| ``` ??? and last in the module is the code. These 6 highlighted bytes are all it takes to divide a passed number by 2 Luckily all this binary can be mapped to some pretty readable text representation --- class: code, increased ## Wat (text representation) ```lisp (module (table 0 anyfunc) (memory $0 1) (export "memory" (memory $0)) (export "half" (func $half)) (func $half (param $0 i32) (result i32) (i32.div_s (get_local $0) (i32.const 2) ) ) ) ``` ??? so this is the same module as before, now in text --- class: code, increased ## Wat (text representation) ```lisp (module `(table 0 anyfunc)` `(memory $0 1)` `(export "memory" (memory $0))` `(export "half" (func $half))` (func $half (param $0 i32) (result i32) (i32.div_s (get_local $0) (i32.const 2) ) ) ) ``` ??? on top you see a bit of metadata, the memory declaration and some exports --- class: code, increased ## Wat (text representation) ```lisp (module (table 0 anyfunc) (memory $0 1) (export "memory" (memory $0)) `(export "half" (func $half))` (func $half (param $0 i32) (result i32) (i32.div_s (get_local $0) (i32.const 2) ) ) ) ``` ??? one of it is our fucntion it points to the dollar-half function further down --- class: code, increased ## Wat (text representation) ```lisp (module (table 0 anyfunc) (memory $0 1) (export "memory" (memory $0)) (export "half" (func $half)) (func $half (param $0 i32) (result i32) ` (i32.div_s` ` (get_local $0)` ` (i32.const 2)` ) ) ) ``` ??? this is defined further down, followed by the actual code. it is just these 3 operations: div, get_local, const calling the division operator on a 32-byte integer with two arguments first it gets the value stored in the passed argument, noted by dollar-0 then it gets the constant integer 2 the order in the binary code is switched around, but this text representation is close enough and readable --- class: code, big, gap, button # JavaScript API ```javscript fetch('half.wasm') .then(data => data.arrayBuffer()) .then(buf => WebAssembly.compile(buf)) .then(mod => WebAssembly.instantiate(mod)) .then(ins => alert(ins.exports.half(128))) ```
Run code
??? Now to actually run this code in the browser, we first need to fetch the data from the server and then use the provided Web API to load and execute the WebAssembly As everything is in the browser I can actually show you that. *press button* The browser downloaded the file, compiled and instantiated it and then called the exported function. --- class: code, big # Available in Rust! ```binary rustup target add wasm32-unknown-emscripten cargo build --target wasm32-unknown-emscripten ``` ### Check out [hellorust.com/wasm](http://hellorust.com/wasm) ??? As you briefly saw, emscripten can take C or C++ code directly. But I'm less of a C programmer and more of a Rust programmer so I'm happy to say: we do have WebAssembly compiler support for Rust as well. There might still be bugs and things that don't work out of the box, but it is ready for first tests --- class: wasmlogo # Tooling: ![](media/webpack.svg) ### "Drop Rust files into a folder and it will *Just Work*!" .footnote[["Implementing first-class support for WebAssembly" funded by Mozilla Open Source Support](https://medium.com/webpack/webpack-awarded-125-000-from-moss-program-f63eeaaf4e15)] ??? and speaking of tooling: webpack recently got funding from Mozilla to implement frist-class support for WebAssembly this would allow you to drop rust files into a folder, tell webpack, execute webpack and it will just work --- class: imgfull, hiddenslide # Tooling: WasmExplorer [![](media/wasm-explorer.png)](http://mbebenita.github.io/WasmExplorer/) ??? Speaking of tools, there are some so you can play around with WebAssembly without needing installed locally the first is WasmExplorer. You can use it to write C or C++ and immediately see the Wasm representation as well as the x86 assembly it compiles to If you're developing a wasm compiler or engine you can use this to compare example code --- class: imgfull, hiddenslide # Tooling: Wasm Fiddle [![](media/wasm-fiddle.png)](https://wasdk.github.io/WasmFiddle/) ??? another tool is Wasm fiddle, quite similar to the popular js fiddle it allows you to collaboratively write some C code, compile it to Wasm and add the required frontend code to run it You can then share your examples around. This is under heavy development and should get you started quite quickly. --- class: inline-img, centeredhead # 🦄 WebAssembly's future 🦄 ??? Ok, now that we know about wasm and how to use it, let's look into the future What we have now enabled in the browser and specified as version 1 of WebAssembly is only the first stage of WebAssembly's development from the start additional features were planned and WebAssembly was specified in a way to be extendable without breaking These future features include -- * Threads - [#1073](https://github.com/WebAssembly/design/issues/1073) ??? Threading support, meaning you can actually make use of all cores in your machine, safely in a sandboxed environment -- * SIMD - [#1075](https://github.com/WebAssembly/design/issues/1075) ??? SIMD support is planned as well, allowing math operations on 128-bit vectors --- class: inline-img, centeredhead # 🦄 WebAssembly's future 🦄 * Threads - [#1073](https://github.com/WebAssembly/design/issues/1073) * SIMD - [#1075](https://github.com/WebAssembly/design/issues/1075) * GC/DOM/Web API integration - [#1079](https://github.com/WebAssembly/design/issues/1079) ??? And even though WebAssembly is not bound to a browser environment, that is its first target and thus neatless integration into the existing DOM and Web APIs will be necessary to make full use of the web environment --- class: quote --- class: quote #
{
If you're a Native developer,
the Web is just a compiler target away.
}
.author[by [@callahad](https://twitter.com/callahad)] --- class: quote #
{
If you're a Web developer,
you can leverage the enormous world of native libraries.
}
.author[by [@callahad](https://twitter.com/callahad)] --- class: quote #
{
Both worlds have to learn from each other to make the most of this.
}
.author[by [@callahad](https://twitter.com/callahad)] --- class: middle, center, hiddenslide # Want to know more? ## [webassembly.org](http://webassembly.org) ??? Now that you know what WebAssembly is, why we need it and the basics of how it works and how to use it head over to WebAssembly.org for detailed information ---- class: middle, less-space, title-bg, title, mozilla-title # Thank you! # WebAssembly for the rest of us ## Jan-Erik Rediger — [@badboy_](https://twitter.com/badboy_) | 2017-05-14
??? Thanks! --- class: less-space, title, jskongress-title background-image: url(media/codemotion_crowd2.png) ## JS Kongress / Wasm Kongress
Munich, 13 - 14 November 2017 # Thank you! ## Jan-Erik Rediger — [@badboy_](https://twitter.com/badboy_) ## Slides: [fnordig.de/jskongress2017](https://fnordig.de/jskongress2017) ??? Thanks! --- class: less-space, title, jskongress-title, devroadshow background-image: url(media/codemotion_crowd2.png) ## Munich
15 November 2017 # Thank you! ## Jan-Erik Rediger — [@badboy_](https://twitter.com/badboy_) ## Slides: [fnordig.de/jskongress2017](https://fnordig.de/jskongress2017) ??? Thanks! --- class: credits ### Sources & Credit * Code File: Pham Thi Dieu Linh, [The Noun Project](https://thenounproject.com/), CC BY 3.0 * Gears: Gregor Cresnar, [The Noun Project](https://thenounproject.com/), CC BY 3.0 * Linear Memory: [Introduction to WebAssembly](https://rsms.me/wasm-intro) * Last quotes: [@callahad](http://twitter.com/callahad) * [WebAssembly Video Editor](https://d2jta7o2zej4pf.cloudfront.net/) * [hellorust.com/wasm](http://www.hellorust.com/wasm/) - Demos & Info * [emscripten](http://emscripten.org/) * [Tanks Game Demo](http://webassembly.org/demo/Tanks/) * [Zen Garden Demo](https://s3.amazonaws.com/mozilla-games/ZenGarden/EpicZenGarden.html)