• Running JavaScript in WebAssembly with WasmEdge
  • Originally written by Michael Yuan
  • The Nuggets translation Project
  • Permanent link to this article: github.com/xitu/gold-m…
  • Translator: CarlosChenN
  • Proofread: nia3y, PassionPenguin

Use WasmEdge to run JavaScript in WebAssembly

WebAssembly was originally designed as an alternative language to JavaScript in browsers. The idea is to make high-performance applications compiled like C/C++ or Rust run safely in the browser. In the browser, WebAssembly and JavaScript run in parallel.

As WebAssembly is increasingly used in the cloud, it is now a universal runtime for native cloud applications. WebAssembly runtimes have lower resource consumption and higher performance than Docker-like application containers. The following is a common example of using WebAssembly in the cloud.

  • Provides the runtime for Serverless function-as-a-Service (FaaS).
  • Embed user-defined functions into SaaS applications or databases.
  • Provides the runtime for sidecar applications in the service grid.
  • Programmable plug-in for Web proxy.
  • Provides runtimes for edge devices including software-defined vehicles and smart factories.

However, in these native cloud use cases, developers often want to write business applications in JavaScript. This means that we must now support writing WebAssemblies in JavaScript. Not only that, we should have JavaScript running in the WebAssembly runtime call C/C++ or Rust functions to maximize WebAssembly efficiency. The WasmEdge WebAssembly runtime allows us to do just that.

WasmEdge

WasmEdge is a leading cloud-native WebAssembly runtime hosted by CNCF (Cloud Native Computing Foundation) and the Linux Foundation. It is currently the fastest WebAssembly runtime on the market, supporting all standard WebAssembly extensions as well as proprietary extensions such as Tensorflow Inference, KV Store and Image Processing. Its compilation tool chain supports not only WebAssembly languages such as C/C++, Rust, Swift, Kotlin, and AssemblyScript, but also common JavaScript.

WasmEdge applications can be embedded into C, Go, Rust, JavaScript programs, and CLI of other operating systems. Runtime can also be used by Docker tools (such as CRI-O), authoring tools (such as K8s), Serverless platforms (such as Vercel, Netlify, AWS Lambda, Tencent SCF), And data flow tools such as YoMo and Zenoh.

You can now run JavaScript programs in WasmEdge with Serverless Functions, microservices, and AIoT applications. It not only runs simple JavaScript programs, but also allows developers to create new JavaScript interfaces using Rust and C/C++ in a secure WebAssembly sandbox.

Build a JavaScript engine in WasmEdge

First, let’s build a WebAssembly-based JavaScript interpreter for WasmEdge. It is based on QuickJS with WasmEdge extensions, such as Network Sockets and Tensorflow Inference, encapsulated in an interpreter of JavaScript APIs. You will need to install Rust to build the interpreter.

If you only want to run JavaScript programs with this interpreter, you can skip this section.

Let’s start by forking or cloning the WASMegde-QuickJS Github repository.

$ git clone https://github.com/second-state/wasmedge-quickjs
Copy the code

You can build a WasmEdge JavaScript interpreter by following the clone instructions given in the repository.

$ rustup target add wasm32-wasi
$ cargo build --target wasm32-wasi --release
Copy the code

The WebAssembly-based JavaScript interpreter program is placed in the build target directory.

$ ls target/wasm32-wasi/debug/quickjs-rs-wasi.wasm
Copy the code

Next, let’s try some JavaScript programs.

An example of a JavaScript network communication application

The interpreter supports the WasmEdge Network socket extension, so your JavaScript can do HTTP connections to the Internet. Here is an example of JavaScript.

let r = GET("Http://18.235.124.214/get? a=123", {"a":"b"."c": [1.2.3]})
print(r.status)
    
let headers = r.headers
print(JSON.stringify(headers))

let body = r.body;
let body_str = new Uint8Array(body)
print(String.fromCharCode.apply(null,body_str))
Copy the code

You can use the CLI to run JavaScript in the WasmEdge runtime.

$ wasmedge --dir .:. target/wasm32-wasi/debug/quickjs-rs-wasi.wasm example_js/http_demo.js
Copy the code

You should now see the result of an HTTP GET request printed in the console.

JavaScript Tensorflow inference example

The interpreter supports simple inference extensions with WasmEdge Tensorflow, so you can run the ImageNet model to classify images. Here is an example of JavaScript.

import {TensorflowLiteSession} from 'tensorflow_lite'
import {Image} from 'image'

let img = new Image('./example_js/tensorflow_lite_demo/food.jpg')
let img_rgb = img.to_rgb().resize(192.192)
let rgb_pix = img_rgb.pixels()

let session = new TensorflowLiteSession('./example_js/tensorflow_lite_demo/lite-model_aiy_vision_classifier_food_V1_1.tflite')
session.add_input('input',rgb_pix)
session.run()
let output = session.get_output('MobilenetV1/Predictions/Softmax');
let output_view = new Uint8Array(output)
let max = 0;
let max_idx = 0;
for (var i in output_view){
    let v = output_view[i]
    if(v>max){
        max = v;
        max_idx = i;
    }
}
print(max,max_idx)
Copy the code

You can use the CLI to run JavaScript in the WasmEdge runtime.

$ wasmedge --dir .:. target/wasm32-wasi/debug/quickjs-rs-wasi.wasm example_js/tensorflow_lite_demo/main.js
Copy the code

You should now see the name of the food element recognized by TensorFlow’s lightweight Imagenet model.

Merge JavaScript into Rust

The two examples above show how to pre-build quickJS-Rs-WasI. wASM applications in WasmEdge. In addition to using the CLI, you can launch WebAssembly applications using the Docker/Kubernetes tools, embed them in your own applications or in the frameworks we discussed earlier in this article.

Alternatively, you can create your own Rust function, which is embedded into a JavaScript program as a string variable or gets JavaScript programs from function input arguments. You can refer to the main.rs application template, which reads the JavaScript program as a string from a file.

fn main() {
    use quickjs_sys as q;
    let mut ctx = q::Context::new();

    let file_path = args_parse();
    let code = std::fs::read_to_string(&file_path);
    match code {
        Ok(code) => {
            ctx.eval_str(code.as_str(), &file_path);
        }
        Err(e) => { eprintln! ("{}", e.to_string()); }}}Copy the code

This approach allows developers to create a single.wASM application file using easy-to-use JavaScript mixed with high-performance Rust, making it easier to deploy and manage.

QuickJS considerations

For now, choosing QuickJS as our JavaScript engine can improve performance. Isn’t QuickJS much slower than V8 because it doesn’t have JIT support? Yes, but…

First, QuickJS is much smaller than V8. In fact, he has only 1/40 (or 2.5%) of the v8 runtime resources. You can run more QuickJS functions on a single physical machine than V8.

Second, for most business logic applications, raw performance is not important. The application may have computationally intensive tasks, such as AI reasoning. WasmEdge allows QuickJS applications to use high-performance WebAssembly without easily adding these extension modules to V8.

Finally, we know that many JavaScript security issues occur on jIts. Perhaps it would be a good idea to turn off JIT in a cloud native environment!

JavaScript in cloud-native WebAssembly is still new territory in the next generation of cloud and edge computing infrastructures. We’re just getting started. If you’re interested, join us in the WasmEdge project (or let us know what you want by requesting features).

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.