SensePost | Introduction to webassembly

WebAssembly change all you know about full stack and out of browser too

WebAssembly change all you know about full stack and out of browser too

WebAssembly Disrupting JavaScript

WebAssembly is a new low-level, high-performance complement to JavaScript on the Web. As an open standard developed by Mozilla, Google, Microsoft, and Apple, WebAssembly runs everywhere that JavaScript does: in every major Web browser, and in runtimes like Node.js and Electron

This talk examines WebAssembly from a practical standpoint, answering why it was created, what it’s good for, how it works, and how you can use it today.

Thanks for watching ❤

If you liked this post, share it with all of your programming buddies!

Follow me on Facebook | Twitter

Learn More

The Web Developer Bootcamp

The Complete JavaScript Course 2019: Build Real Projects!

Vue JS 2 - The Complete Guide (incl. Vue Router & Vuex)

Angular 7 (formerly Angular 2) - The Complete Guide

Build a web scraper with Node

Build Your First PWA with Angular

Top 10 Podcasts for Web Developers

Get started with WebAssembly using JavaScript

Get started with WebAssembly using JavaScript

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. WebAssembly is an exciting new language that many JavaScript engines have added support for.

WebAssembly is a brand new web technology with massive potential. It will have a significant impact on how web applications are **developed **in the future.

But, sometimes, I feel like it just doesn’t want to be understood… almost in a strangely passive-aggressive kind of way.

When I look at the documentation and the handful of tutorials that are already out there, I can’t help but feel like a farmer who prayed for rain, only to drown in a flood. I technically got what I wanted… just not in the way that I’d hoped. “You want rain?! Oh, I’ll give you rain!”

This is because WebAssembly makes so many new things possible and can be implemented in so many different ways. But, it has changed so much along the way to its official MVP release in February, that when you first get started learning about it, it’s easy to drown in a sea of details.

Continuing the rain metaphor, this article is my attempt to provide a light shower of an introduction to WebAssembly. Not the concepts or the nuts and bolts, but the actual implementation.

I’ll walk you through the steps to create and implement an extremely simple project, removing complexity wherever possible. After you’ve implemented it once, however simply, a lot of those higher level ideas are a lot easier to make sense of.

Let’s break it down

Everything will be much clearer if we step back and look at a list of the steps involved in implementing **WebAssembly **in a project.

When you’re first getting started, it’s easy to look at WebAssembly and just see a big wad of options and processes. Breaking it down into discrete steps will help us get a clear picture of what’s going on:

  1. Write: Write something (or use an existing project) in C, C++, or Rust
  2. Compile: Compile it into WebAssembly (giving you a binary .wasm file)
  3. Include: Get that .wasm file into a project
  4. Instantiate: Write a bunch of asynchronous **JavaScript **that will compile the .wasm binary and instantiate it into something that **JS **can play nicely with.

And that’s pretty much it. Granted, there are different permutations of this process, but that’s the gist of it.

Broadly speaking, it’s not all that complicated. However, it can get extremely complicated, because most of these steps allow for widely varying degrees of complexity. In each case, I’m going to err on the side of bare-bones simplicity.

For our project, we’ll be writing a simple function in C++ (don’t worry if you’re not familiar with C++, it’ll be** **extremely simple). The function will return the square of a given number.

Then, we’ll compile it into .wasm using an online tool (you won’t need to download or use any command line utilities). Next, we’ll instantiate it with 14 lines of JS.

When we’re done, you’ll be able to call a function written in C++ as if it were a JS function, and you’ll be amazed!

The sheer number of possibilities that this opens up are absolutely mind blowing.

Write

Let’s start with our C++ code. Remember, we won’t be using a local dev environment to write or compile this.

Instead, we’ll be using an online tool called WebAssembly Explorer. It’s kind of like **CodePen **for WebAssembly, and it allows you to compile your C or C++ code right in the browser and download a .wasm file all in one place.

Once you’ve opened up WebAssembly Explorer, type this C++ code into the leftmost window:

int squarer(int num) {
  return num * num;
}

Like I said, we’re using a really simple example here. Even if you’ve never looked at C or C++ before, it’s probably not too difficult to tell what’s going on.

Compile

Next, click the button that says “compile” in the red bar above your C++ code. Here’s what you’ll see:

The middle column shows you a human-readable version of the .wasm binary that you’ve just created. This is called “WAT” or WebAssembly Text Format.

On the right is the resultant assembly code. Pretty cool.

I won’t go into much detail about either of these, but you do need to know at least a little bit about the WAT file in order to follow the next steps.

WAT exists because we humans generally have a hard time making sense of straight binary. It’s essentially a layer of abstraction that helps you understand and interact with your WebAssembly code.

In our case, what we want to understand is how our WebAssembly refers to the function that we just created. This because we’ll need to use that exact same name in our JS file later on to refer to it.

Any functions that you write in your C++ code will be available in WebAssembly as something called an “export.” We’ll talk a bit more about this later, but for now, all you need to know is that the exports are the things that you’ll be able to interact with and use.

Take a look at the WAT file and look for the word “export.” You’ll see it twice: once alongside the word memory and again alongside the word _Z7squareri. We don’t need to know about memory for now, but we’re definitely interested in _Z7squareri.

We used the function name squarer in our C++, but now that has somehow become _z7squareri. This can definitely be confusing the first time you see it.

As far as I can tell, the “_Z7” prefix and “i” suffix are debug markers introduced by the C++ compiler. This isn’t really important to understand in depth, though. You just need to be aware that this will happen, because you need to use this exact name in your JS file in order to call your C++ function.

Include

Now just click the “download” button at the top of the purple WAT section. You’ll get the .wasm binary file. Rename it squarer.wasm. Then create a new directory and put your squarer.wasm file in there, along with two other files:

  • index.html (boilerplate)
  • scripts.js (empty for now)

Instantiate

Now for the tricky part. Or, at least, the part that caused me a lot of confusion when I first started sifting through the documentation.

Although you’ll eventually be able to include .wasm modules like a regular old ES6 module (using <script type='module'> ), for the time being you need to “manually” set it up. This is done by making a bunch of asynchronous calls to the WebAssembly API. There are three steps:

  • Get your .wasm binary file into an array buffer*
  • Compile the bytes into a WebAssembly module*
  • Instantiate* the WebAssembly module

If all of this makes sense to you, then you can skip to the next section. But if you found yourself scratching your head a bit and want a more detailed explanation, then continue reading.

Array Buffer

A buffer is a temporary storage place for data while it’s being moved around. Generally, this is useful when data is being received and processed at different rates.

For example, when a video is buffering, the data is being received at a rate slower than the video player can play it. One of the things that our array buffer is doing is queueing up our binary data so that it can be compiled more easily.

But there’s something else very important going on here. In JavaScript, an array buffer is a typed array, which is something that’s used specifically for storing binary data.

The fact that it is explicitly typed means that the JS engine can interpret an array buffer much faster than it can a regular array, because it already knows the data type and doesn’t have to go through the process of figuring it out.

WebAssembly module

Once you’ve got all your binary data into an array buffer, you can compile it into a module. The WebAssembly module is, in itself, inert. It’s just the compiled binary, waiting for something to be done with it.

You can almost think of the module like a cake recipe. The recipe is just a format for storing information about how to make a cake. If you actually want a cake, you need to create an instance of the cake described in the recipe (instantiate the cake).

You do this by following the instructions laid out in the recipe. Alternatively, you could send the recipe to someone else (a “service worker”), or you could save it and use it later (“cache” it). Both of these are much more convenient to do with a recipe, than with an actual cake.

Instantiate

The last thing you need to do is create an instance of your WebAssembly module, which “brings it to life” and makes it actually usable.

The instance gives you access to the module’s exports (remember this from our WAT file?). This is an object that contains:

  • Memory (not relevant to us, but you can read more about it here)
  • Any functions that were present in your C++ code. This is how you will use the C++ function that you’ve written.

Finish up and run it!

Here’s the code that accomplishes all of the steps we just went over (this goes into your scripts.js file):

let squarer;

function loadWebAssembly(fileName) {
  return fetch(fileName)
    .then(response => response.arrayBuffer())
    .then(bits => WebAssembly.compile(bits))
    .then(module => { return new WebAssembly.Instance(module) });
};
  
loadWebAssembly('squarer.wasm')
  .then(instance => {
    squarer = instance.exports._Z7squareri;
    console.log('Finished compiling! Ready when you are...');
  });

The loadWebAssembly() function fetches your .wasm file and then performs the operations mentioned above. Then it returns a new instance of your WebAssembly module.

Our C++ function (remember it’s referred to by the funky name that we mentioned before: _z7squareri ) lives in the exports property of our instance. You can see it being assigned to the global variable squarer on line 12. Now we can use squarer() as a regular JavaScript function!

Once you put this into your scripts.js file and hit save, you can pull it up on localhost and you should see the “Finished compiling…” message in the console.

Now, just call your function and pass in an argument from the console. Try something like squarer(9) . Hit return and you’ll see 81 . It works! You’re calling a function written in C++!

This is fantastic

You can just imagine all of the things that this makes possible.

For one, JavaScript is no longer your only option for “doing things” in the browser. That is absolutely huge.

Then there’s the performance improvements, since WebAssembly, unlike JS, runs at near-native speed.

And then there’s all the legacy code that’s now at your disposal. C and C++ have been around for a long time, and in that time, a lot of brilliant people have created some amazing open-source projects with it. Projects that can now be integrated into websites or apps.

From here, you can write more complex C, C++, or Rust code, or even adapt an existing project, and “wasm-it” into a web project.

One caveat, however, is that if you want to create functions that accept arguments or return values that are not numbers, then things start to get a bit more complicated. That’s when you’ll need to learn a bit more about the memory attribute of the .wasm instance’s exports.

This project is available on GitHub if you’d just like to clone a working copy in addition to following along with the article.

Will WebAssembly replace JavaScript in the future?

Will WebAssembly replace JavaScript in the future?

JavaScript is flourishing. But thanks to WebAssembly, its death may be just a matter of time.

Some programming languages are loved. Others are only tolerated. For many programmers, JavaScript is an example of the latter — a language that every front-end developer needs to understand but no one needs to like.

Ten years ago, it wasn’t obvious that JavaScript was set to rule the world. Other platforms, like Java, Flash, and Silverlight were also in the running. All three needed a browser plug-in to do their work, and all three replaced HTML with a different approach to user interface. This approach allowed them to get far in front of JavaScript with features — for example, adding video, animation, and drawing long before we had the <video> element, the CSS Animations specification, or the HTML canvas. But it also spelled their downfall. When mobile browsing exploded and HTML shifted to embrace it, these other platforms became obsolete.

Here’s another irony. At the same time that JavaScript was conquering the world, a tiny seed was planted that may, sometime in the future, spell the end of JavaScript. That seed was an experimental technology called asm.js.

But before we get to that, let’s take a step back to survey the situation today.

Transpiling: The current approach

As long as we’ve had JavaScript, developers have been trying to get around it. One early approach was to use plug-ins to take the code out of the browser. (That failed.) Another idea was to make development tools that could convert code — in other words, take code written in another more respectable language, and transform it into JavaScript. That way developers could get the run-everywhere support they wanted but still keep their hands clean.

The process of converting one language to another is called transpiling, and it has some obvious stumbling blocks. High-level languages have different features, syntax, and idioms, and you can’t always map a line in one to an equivalent construct in another. And even when you can, danger lurks. What happens if the community stops developing your favorite transpiler? Or if the transpiler introduces bugs of its own? What if you want to plug into a JavaScript framework like Angular, React, or Vue? And how do you collaborate on a team if you don’t speak the same language?

As in many cases with coding, the tool is only as good as the community behind it.

Today, transpilers are common, but they’re almost always used in just one way — to handle backward compatibility.

Developers write the most modern JavaScript possible, and then use a transpiler like Babel to convert their code to the equivalent (but less elegant) old-school JavaScript code that works everywhere. Or — even better — they use TypeScript (a modernized flavor of JavaScript that adds features like strong typing, generics, and non-nullable types) and then transpile that into JavaScript. Either way, you’re still playing in the walled garden of JavaScript.

Asm.js: A stepping stone

The first glimmer of a new possibility came from asm.js, a quirky experiment cooked up by the developers at Mozilla in 2013. They were looking for a way to run high-performance code inside a browser. But unlike plug-ins, asm.js didn’t try to go beside the browser. Instead, it aimed to tunnel straight through the JavaScript virtual machine.

At its heart, asm.js is a terse, optimized JavaScript syntax. It runs faster than normal JavaScript because it avoids the slow dynamic parts of the language. But web browsers that recognize it can also apply other optimizations, boosting performance much more dramatically. In other words, asm.js follows the golden rule — don’t break the web — while offering a pathway to future improvements. The Firefox team used asm.js, along with a transpiling tool called Emscripten, to take real-time 3D games built in C++ and put them inside a web browser, running on nothing more than JavaScript and raw ambition.

The Unreal engine running on asm.js

The most important part of asm.js was the way it forced developers to rethink the role of JavaScript. Asm.js code is JavaScript, but it’s not meant for coders to read or write by hand. Instead, asm.js code is meant to be built by an automated process (a transpiler) and fed straight to the browser. JavaScript is the medium but not the message.

WebAssembly: A new technology

Although the asm.js experiment produced a few dazzling demos, it was largely ignored by working developers. To them, it was just another interesting piece of over-the-horizon technology. But that changed with the creation of WebAssembly.

WebAssembly is both the successor to asm.js, and a significantly different technology. It’s a compact, binary format for code. Like asm.js, WebAssembly code is fed into the JavaScript execution environment. It gets the same sandbox and the same runtime environment. Also like asm.js, WebAssembly is compiled in a way that makes further efficiencies possible. But now these efficiencies are more dramatic than before, and the browser can skip the JavaScript parsing stage altogether. For an ordinary bit of logic (say, a time-consuming calculation), WebAssembly is far faster than regular JavaScript and nearly as fast as natively compiled code.

A simplified look at the WebAssembly processing pipeline

If you’re curious what WASM looks like, imagine you have a C function like this:

int factorial(int n) {
  if (n == 0)
    return 1;
  else
    return n * factorial(n-1);
}

It would compile to WASM code that looks like this:

get_local 0
i64.eqz
if (result i64)
    i64.const 1
else
    get_local 0
    get_local 0
    i64.const 1
    i64.sub
    call 0
    i64.mul
end

When it’s sent over the wire, WASM code is further condensed into a binary encoding.

WebAssembly is designed to be a target for compilers. You’ll never write it by hand. (But you could, if you want to take a deep-dive exploration.)

WebAssembly first appeared 2015. Today, it’s fully supported by the big four browsers (Chrome, Edge, Safari, and Firefox) on desktop and mobile. It isn’t supported in Internet Explorer, although backward compatibility is possible by converting the WebAssembly code to asm.js. (Performance will suffer. Please let IE fade into obscurity!)

WebAssembly and the future of web development

Out of the box, WebAssembly gives developers a way to write optimized code routines, usually in C++. This is powerful ability, but it has a relatively narrow scope. It’s useful if you need to improve the performance of complex calculations. (For example, fastq.bio used WebAssembly to speed up their DNA sequencing calculations.) It’s also important if you’re porting high-performance games or writing an emulator that runs inside your browser. If this is all there were to WebAssembly, it wouldn’t be nearly as exciting — and it wouldn’t have any hope of displacing JavaScript. But WebAssembly also opens a narrow pathway for framework developers to squeeze their platforms into the JavaScript environment.

Here’s where things take an interesting turn. WebAssembly can’t sidestep JavaScript, because it’s locked into the JavaScript runtime environment. In fact, WebAssembly needs to run alongside at least some ordinary JavaScript code, because it doesn’t have direct access to the page. That means it can’t manipulate the DOM or receive events without going through a layer of JavaScript.

This sounds like a deal-breaking limitation. But clever developers have found ways to smuggle their runtimes in through WebAssembly. For example, Microsoft’s Blazor framework downloads a miniature .NET runtime as a compiled WASM file. This runtime deals with the JavaScript interop, and it provides basic services (like garbage collection) and higher-level features (layout, routing, and user interface widgets). In other words, Blazor uses a virtual machine that lives inside another virtual machine, which is either an Inception-level paradox or a clever way to create a non-JavaScript application framework that runs in the browser.

Blazor isn’t the only WebAssembly-powered experiment that’s out of the gate. Consider Pyodide, which aims to put Python in the browser, complete with an advanced math toolkit for data analysis.

This is the future. WebAssembly, which started out to satisfy C++, Rust, and not much more, is quickly being exploited to create more ambitious experiments. Soon it will allow non-JavaScript frameworks to compete with JavaScript-based standbys like Angular, React, and Vue.

And WebAssembly is still evolving rapidly. It’s current implementation is a minimum viable product — just enough to be useful in some important scenarios, but not an all-purpose approach to developing on the web. As WebAssembly is adopted, it will improve. For example, if platforms like Blazor catch on, WebAssembly is likely to add support for direct DOM access. Browser makers are already planning to add garbage collection and multithreading, so runtimes don’t need to implement these details themselves.

If this path of evolution seems long and doubtful, consider the lessons of JavaScript. First, we saw that if something is possible in JavaScript, it is done. Then, we learned that if something is done often enough, browsers make it work better. And so on. If WebAssembly is popular, it will feed into a virtuous cycle of enhancement that could easily overtake the native advantages of JavaScript.

It’s often said that WebAssembly was not built to replace JavaScript. But that’s true of every revolutionary platform. JavaScript was not designed to replace browser-embedded Java. Web applications were not designed to replace desktop applications. But once they could, they did.