• A Complete Introduction to WebAssembly and It’s JavaScript API
  • By Mahdhi Rezvi
  • The Nuggets translation Project
  • Permanent link to this article: github.com/xitu/gold-m…
  • Translator: JohnieXu
  • Proofreader: Samyu2000, plusMultiply0

The performance of native applications has improved considerably since the dawn of computers. By contrast, Since JavaScript was not invented to run faster, Web applications are very slow. However, intense competition among browsers and the rapid development of JavaScript engines such as V8 make iT possible to run JavaScript quickly on computers. But it still can’t beat the performance of native applications. The main reason for this is that JavaScript code needs to be compiled multiple times to generate machine code.

With the birth of WebAssembly, Web applications as we know them promise to be revolutionized. It makes Web applications run faster. Let’s take a look at what WebAssembly is and how it can be integrated with JavaScript to build applications that run incredibly fast.

What is a WebAssembly?

Before we understand WebAssembly, let’s look at what an Assembly is.

Assembly language is a low-level programming language, and the underlying machine instructions have a very close relationship. In other words, assembly is the process of converting this language into machine-readable code, called machine code.

WebAssembly can be colloquially understood as assembly language used in Web applications. It is a low-level assembler like language with a compact binary format that allows you to run Web applications at near-native speeds. It also provides compilation targets for languages such as C, C++, and Rust to enable client applications to run on the Web with near-native performance.

Also, WebAssembly is meant to work with JavaScript, not replace it. Using the WebAssembly JavaScript API, your application can achieve excellent performance from WebAssembly while using JavaScript to achieve versatility and compatibility. This opens up a whole new chapter in Web applications, where some of the code and functionality that was previously unavailable for Web systems can now be run on web systems.

How is WebAssembly different

Lin Clark predicts that the launch of WebAssembly in 2017 could bring Web development to an inflection point. It happened after the introduction of the JIT compiler in modern browsers, which was also an inflection point because IT made JavaScript nearly 10 times faster.

If you carefully compare JavaScript to WebAssembly code compilation, you will notice that several steps have been stripped out of the WebAssembly compilation process, while others have been removed. Here is a comparison of the two compilation processes.

If you compare the two processes, you’ll notice that the retuning part of WebAssembly has been stripped completely. This is mainly because the compiler doesn’t need to make any assumptions about the WebAssembly code because the things that need to be clearly defined in the code, such as data types, are already clearly defined.

This is not the case with JavaScript, because the JIT should make assumptions to run the code, and if those assumptions fail, it should re-optimize its code.

How do I get the WebAssembly code

Next comes the most important question developers face. WebAssembly is a great technology, so how can developers take full advantage of its power?

There are several ways to use it.

  • Write WebAssembly code from scratch – this is not recommended unless you know the basics very well.
  • Compile from C to WebAssembly
  • Compile to WebAssembly from C++
  • Build from Rust to WebAssembly
  • Use AssemblyScript to compile a strict variant of Typescript into WebAssembly. This is a great choice for Web developers unfamiliar with C/C++ or Rust.
  • It also supports more language compilations to choose from, which are covered below.

In addition, there are tools such as Emscripten and WebAssembly Studio that can help with the above code compilation process.

JavaScript WebAssembly API

To take full advantage of WebAssembly’s features, we must integrate it with JavaScript code. This can be done with the help of the JavaScript WebAssembly API.

Module compilation and instantiation

The WebAssembly code resides in a file with the suffix.wasm, which needs to be compiled on the client side to the corresponding machine code for the corresponding system. The WebAssembly module can be compiled using the WebAssembly.compile method. After receiving a compiled WebAssembly module, instantiate it using the webassembly.instantiate method. Alternatively, it can be instantiated by converting the contents of the retrieved.wasm file into an ArrayBuffer and passing it to WebAssembly.instantiate.

let exports;

fetch('sample.wasm').then(response= >response.arrayBuffer(); ) .then(bytes= >WebAssembly.instantiate(bytes); ) .then(results= > {
  exports = results.instance.exports;
});
Copy the code

One drawback of the above approach is that since the Webassembly.instantiate method cannot access the bytecode directly, the obtained module file contents need to be converted to ArrayBuffer for compilation and instantiation.

There is another method, using the WebAssembly.com pileStreaming and WebAssembly instantiateStreaming method to achieve the above the function of the compilation, instantiation, the advantage of this approach is able to directly access the bytecode, Without having to convert the contents of the file to an ArrayBuffer first.

let exports;

WebAssembly.instantiateStreaming(fetch('sample.wasm'))
.then(obj= > {
  exports = obj.instance.exports;
})
Copy the code

It is worth noting that both of the above methods of instantiating a WebAssembly module return a compiled module instance object to quickly start the module instance.

let exports;
let compiledModule;

WebAssembly.instantiateStreaming(fetch('sample.wasm'))
.then(obj= > {
  exports = obj.instance.exports;
  //access compiled module
  compiledModule = obj.module;
})
Copy the code

Import Objects

After you have instantiated a WebAssembly module, you can pass in an Import Object to the module instance. The Import Object can have one of four types of attribute values.

  • Globals
  • Functions
  • Memory
  • Table (Table)

An import object can be understood as a set of helper methods that are attached to a module instance to implement a particular function, and the compiler assigns default values if an import object is not provided.

Globals

With WebAssembly you can create global variables that can be accessed in JavaScript and WebAssembly modules. These variables can be imported, exported, and used in one or more instances of the WebAssembly module.

You can use the constructor webassembly.global () to create instances of Global variables.

const global = new WebAssembly.Global({
    value: 'i64'.mutable: true
}, 20);
Copy the code

The constructor takes two arguments:

  • The first argument is an object whose value property indicates the type of the value, and whose mutable property indicates whether the value can be changed. The allowed types are:i32,i64,f32f64;
  • The second argument is the value of the variable, whose value must be of the same type as specified in the first argument, for example, if the type in argument 1 isi32, the type of the value must be a 32-bit integer if the type in parameter 1 isf64, the type of the value must be 64-bit floating point.
const global = new WebAssembly.Global({
    value: 'i64'.mutable: true
}, 20);

let importObject = {
    js: {
        global}}; WebAssembly.instantiateStreaming(fetch('global.wasm'), importObject)
Copy the code

The global object instance created above must passWebAssembly.instantiateStreamingWebAssembly.instantiateMethod is passed to the import object of the WebAssembly instance object to ensure that the WebAssembly instance object can be accessed correctly.

Memory

WebAssembly module objects need to pass an allocated memory object through an import object during the instantiation process. If such an object is not passed, the JIT will automatically pass in the default memory object at compile time.

The memory object passed in can also be an ArrayBuffer, so that the stored memory value can be easily accessed through the index value. Therefore, data values passed through memory objects can be shared between JavaScript and WebAssembly.

Table (Table)

A table is an array of variable-length data that sits outside WebAssembly memory and stores values that are references (Pointers) to the data. It looks very similar to Memory objects, but the biggest difference is that Memory objects store raw bytes of data, while tables store Pointers to Memory data.

Tables, the WebAssembly data structure, were introduced to improve runtime security.

Tables can be manipulated using the set(), grow(), and get() methods.

A sample

Below I will use an application created by WebAssembly Studio to compile into a.wasm file to demonstrate how to use WebAssembly. You can also view this demo online.

Here we create a function to exponentiate a number, which passes in a value and then receives the output in a JavaScript program.

You need to take extra care when manipulating strings in WASM. There is no string data type in WASM. Strings are processed using ASCII characters in WASM. The JavaScript is passed the memory address to store the results of the calculation. Also, since the memory object is an ArrayBuffer, it needs to be aligned for traversal to be converted to a string.

JavaScript files

let exports;
let buffer;
(async() = > {let response = await fetch('.. /out/main.wasm');
  let results = await WebAssembly.instantiate(await response.arrayBuffer());
  / / or
  // let results = await WebAssembly.instantiateStreaming(fetch('.. /out/main.wasm'));
  let instance = results.instance;
  exports = instance.exports;
  buffer = new Uint8Array(exports.memory.buffer);

  findPower(5.3); printHelloWorld(); }) ();const findPower = (base = 0, power = 0) = > {
  console.log(exports.power(base,power));
}

const printHelloWorld = () = > {
  let pointer = exports.helloWorld();
  let str = "";
  for(leti = pointer; buffer[i]; i++){ str +=String.fromCharCode(buffer[i]);
  }
  console.log(str);
}
Copy the code

C file

#define WASM_EXPORT __attribute__((visibility("default")))
#include <math.h>


WASM_EXPORT
double power(double number,double power_value) {
  return pow(number,power_value);
}

WASM_EXPORT
char* helloWorld(a){
  return "hello world";
}
Copy the code

Usage scenarios

The birth of WebAssembly opened up another world of possibilities.

  • It gives the Web environment the ability to use ready-made libraries or projects developed in c, C++ and other languages

For example, if you can’t find a JavaScript version of a feature that doesn’t have WebAssembly, you need to start from scratch and use JavaScript to implement the feature. Now, if you can find a library that does this in another language, you can reuse that library directly with the power of WebAssembly. From a technology development perspective, this can be a huge time saver and a huge breakthrough.

Squoosh uses WebAssembly for QR codes and image recognition, allowing the application to run at near-native speeds in older browsers. EBay also implemented barcode scanning by compiling the original C++ library into WebAssembly.

  • Existing C and C++ projects can be modified to run in a Web environment with near-native speed

Applications like AutoCAD, QT, and Google Earth can run on the Web with near-native performance by simply modifying existing code bases, ultimately thanks to WebAssembly’s capabilities.

  • Libraries developed in languages such as C, C++, or Rust can be compiled to run on the Web side with WebAssembly, even though the corresponding library may already have a JavaScript version implemented. Applications will run faster and have better performance

In Squoosh, the Google team compiled JPEG and MozJPEG decoders like those developed in C or C++ into WebAssembly versions, replacing the previous decoders. The compiled decoder further reduces the size of image files without sacrificing image quality.

Supported programming languages

Not only C, C++, or Rust support compilation to WebAssembly, but many other languages are actively working to support WebAssembly compilation. The following is a list of programming languages that currently support compiling WebAssembly.

  • C/C++
  • Rust
  • AssemblyScript (TypeScript like syntax)
  • C#
  • F#
  • Go
  • Kotlin
  • Swift
  • D
  • Pascal
  • Zig

Deficiency in

WebAssembly allows programs to execute compiled binaries directly, which introduces many security issues. For example, This example – / holes can be used (vulnerabilities can be exploited] (vulnerabilities can be exploited] (www.virusbulletin.com/virusbullet… WebAssembly already has some security features, but I personally don’t think they are enough and need to be improved. The use of these new features will cause traditional layers of protection, such as antivirus and URL filtering, to fail. Failure to address these issues means that these common browsers will become much less secure in the future.

You can read the article below to learn more about WebAssembly security.

  • The dark side of WebAssembly
  • Wasm security concerns
  • Official complete description

To summarize

Despite the hype on the web that WebAssembly is about to replace JavaScript, I don’t agree that JavaScript will be replaced. WebAssembly was created to work with JavaScript, not replace it. In addition, debugging JavaScript code is much easier than debugging WebAssembly code, and JavaScript’s free and flexible syntax is not supported in WebAssembly.

It’s safe to say that WebAssembly will pave the way for more types of Web application development.

“While there is no way to predict what new applications these performance improvements will lead to, if there is a hint from the present or past, we will be surprised in the future.” – Lin Clark

Refer to the article

  • An Abridged Cartoon Introduction To WebAssembly by Lin Clark
  • Creating a WebAssembly module instance with JavaScript by Lin Clark
  • Memory in WebAssembly by Lin Clark
  • WebAssembly table imports… what are they? by Lin Clark
  • WebAssembly Official Website
  • Google IO 2019 — WebAssembly for Web Developers
  • MDN Docs — WebAssembly
  • MDN Docs — WebAssembly JavaScript API

If you find any mistakes in your translation or other areas that need to be improved, you are welcome to the Nuggets Translation Program to revise and PR your translation, and you can also get the corresponding reward points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.


The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.