When I first heard about
WebAssembly technology, it immediately seemed like a cool thing to me and I immediately wanted to try it out. From the first desire, to something working, however, I had to spend a lot of time and sometimes experience some disappointments. In order to save your time and your nerves, if you want to repeat the same way, this article is written.

Warning reader
This article was written on June 24th, 2016. Since WebAssembly is a very young and dynamic technology, with time, many of the things described in this article will become obsolete or change completely - keep this in mind.
And now let's go.
')
What is WebAssembly?
Official documentation says the following: “WebAssembly or wasm is a new portable, efficient in size and download speed compilation format for the web.” Ummmmmm ... What? What format? Text or binary? Yes, this is frankly a bad description. So remove your bazo-bingo cards and I, based on my experience, will give my definition:
"WebAssembly or wasm is the bytecode specification for writing productive, browser-independent components for the web." This definition, too, of course, is not the top of the epistolary genre, but I will try to complement it. WebAssembly allows you to improve performance by using statically typed variables that cost significantly faster on runtime than dynamic ones. WebAssembly is being developed by the
W3C Community Group and is planned to be implemented in all major browsers. And from this point on, the killer feature is laid out on the table: you can write the code of web components in any programming language.
Now it sounds better, right?
Let's start
When I learn a new thing, I usually look for the smallest possible example, enough to see how everything works. Unfortunately, this approach is not very possible with WebAssembly. In its current state, the wasm specification is simply a bytecode format. Imagine how in some 1996th year, Sun Microsystems engineers would have introduced the JVM ... but without Java. The conversation would go something like this:
"- Hey, you all, check out what a cool machine we have created for baytkod!
- Cool! And how to write code for it?
- That's how:

“Ummmmmh ... cool ... I'll try it sometime at leisure.
“Fine, let us know if there are any problems or ideas!”
- Yes Yes. But I'm a little busy here, you need to look at a few other things ... But as soon as - so immediately! "
And even this is a bad example, since the JVM is at least based on the Java language, and with WebAssembly we don’t have that either. I hope you get the idea. If you represent bytecode without a tool that compiles the code of some programming language into this bytecode, it will be difficult for you to promote it. So how do we still start working with WebAssembly?
What happened to WebAssembly?
Most technologies are the result of the development of some previous technologies, especially when the planned goal is to obtain some formal specification. WebAssembly is not an exception, it is a continuation of the development of ideas embodied once in asm.js, a specification designed for writing javascript code in such a way that it can be compiled with static typing. Wasm developed these ideas by creating a bytecode specification that can be created by the compiler of any programming language, then sent over the Internet as a binary file, suitable for execution by any modern browser.
asm.js is just a specification for writing javascript code using a subset of Javascript features. You can write the code in asm.js manually and if you can not wait to take and write something - it's time to start.
function MyMathModule(global) { "use asm"; var exp = global.Math.exp; function doubleExp(value) { value = +value; return +(+exp(+value) * 2.0); } return { doubleExp: doubleExp }; }
This is not a very useful feature, but it is written according to the asm.js specification. If it looks a little silly for you - so know that you are not the only one who thinks so. However, all these "strange" symbols (all these unary operators) are necessary. They point the compiler to the data types in the operations. The code is very simple, but if you make a mistake somewhere, the debug console will show a fairly readable error message.
If you want to use this function, you can do it something like this:
var myMath = new MyMathModule(window); for(var i = 0; i < 5; i++) { console.log(myMath.doubleExp(i)); }
And if you did everything right, then you should see something like this at the output:

Finally, go to WebAssembly
At the moment we have a working piece of code on asm.js. We can go to the
official WebAssembly page on GitHub and find there tools to compile this code into wasm. The only trouble is that we will have to assemble these tools on our own. This is, frankly, the worst part of the quest. These tools are constantly changing and are in broken condition from time to time, especially in terms of using them under Windows.
You need make and cmake to build. If you are working under Windows, you will also need Visual Studio 2015. Here are
instructions for building on Mac, but on Windows.

It should be noted that the distribution of the collected binaries of these utilities would be a huge step forward in promoting the WebAssembly technology.
If you went through all of the above without any problems, you got the bin folder in the binaryen folder, where the tools for converting our asm.js code to wasm are located. The first tool is called asm2wasm.exe. It converts the code in asm.js to the .s code format, which is a textual representation of the abstract syntax tree (AST) of the wasm format. By running asm2wasm on your asm.js code, you will get something like this:
(module
(memory 256 256)
(export "memory" memory)
(type $FUNCSIG$dd (func (param f64) (result f64)))
(import $exp "global.Math" "exp" (param f64) (result f64))
(export "doubleExp" $doubleExp)
(func $doubleExp (param $0 f64) (result f64)
(f64.mul
(call_import $exp
(get_local $0)
)
(f64.const 2)
)
)
)
You can parse this code line by line, but now I just want to emphasize that since wasm is a binary format, just clicking on the browser on something and seeing the code, as you used to do it with Javascript, will not work (at least for now). moment). What you see will be very similar to the code above.
The next step is to convert this .s format to a wasm binary, for this we will use the wasm-as.exe utility. Applying it to your output .s-file, you will get a bytecode, for which we started this whole story.


Now grab the latest version of Firefox or Chrome Canary and enable WebAssembly.
For Firefox, you need to open about: config and type "wasm" in the search bar. After that, change the value of the javascript.options.wasm option to true and restart the browser. For Chrome Canary, you need to open chrome: // flags, find and enable the Experimental WebAssembly option, and then restart the browser.
Now we need to run our module in the browser. For me, this at first turned out to be a problem, since it is not at all obvious how to do this. I opened the console in Chrome Canary and tried to type "WebAsse" - and nothing, no tips. Then I typed "Was" and got a hint! This object in the inspector looked very poor in terms of documentation. I will omit the whole story about how I rummaged in search of a working example, I will only say that in the end I found it in some
JS.md file in the WebAssembly repository. There was something like documentation and an example, here it is:
fetch("my-math-module.wasm") .then(function(response) { return response.arrayBuffer(); }) .then(function(buffer) { var dependencies = { "global": {}, "env": {} }; dependencies["global.Math"] = window.Math; var moduleBufferView = new Uint8Array(buffer); var myMathModule = Wasm.instantiateModule(moduleBufferView, dependencies); console.log(myMathModule.exports.doubleExp); for(var i = 0; i < 5; i++) { console.log(myMathModule.exports.doubleExp(i)); } });
Drop it into your html file, raise the local web server and open this file in the browser. Here is what it will look like:

It's time to go send a bug report. Remember that this is still a very raw and experimental technology, so do not be surprised at the bugs arising along the way.

Congratulations!
You have created your first WebAsse installation component. What's next? Well, we have only slightly discarded the covers of mystery. Writing asm.js code was the key to this example, and writing any non-trivial functionality will take time and patience. Using emscripten, compiling non-trivial applications in asm.js becomes much easier. I advise you to read the asm.js specification, especially the section on the memory model, since many concepts have been transferred to WebAssembly directly from asm.js. One more important point: at the moment you cannot pass arrays as function arguments. There is some agreement that this should change, but so far this is not reflected in the specification. It's time to refresh the memory of working with pointers.
Another caveat: when you start writing non-trivial things on wasm, you may notice that performance can sometimes be slower than good old Javascript. Just keep in mind that modern Javascript engines in all browsers are very highly optimized and it will take some time for wasm to achieve their effectiveness. The theoretical performance limit of WebAssembly is higher than that of Javascript code in text form, but WebAssembly is not yet ready for industrial use.