Photo by Markus Winkler on Unsplash
WebAssembly Plugin in JavaScript with Extism
Write Wasm plugins with Extism and JavaScript π
In the last few days, we have used the Go PDK (Plugin Development Kit) to develop WebAssembly applications and run them with the Extism CLI.
As I said in the first article, there are PDKs for several languages, including JavaScript (and I'm a big fan of JavaScript). But how is this possible? Indeed, we can't compile JavaScript to native Wasm code.
In fact, this PDK uses (among other things) the QuickJS project to run JavaScript code in a Wasm program.
Of course, it won't run as fast as a Wasm program compiled with TinyGo or Rust, but it allows you to run JavaScript functions in a completely "sandboxed" environment. As Shopify does (this PDK is a fork of the Javy project initiated by Shopify.
Shopify developed the Javy project to bring JavaScript support to Shopify Functions. Shopify Functions allow developers to create custom extensions and features for the specific needs of merchants in JavaScript, which is a popular and familiar language for many web developers.
So, imagine that you decide to create a FaaS platform JavaScript oriented and that you want to give your users the possibility to create and publish their functions. Going through a similar mechanism will have at least two advantages:
Encourage adoption (JavaScritp is well-known)
Guarantee the integrity of your platform (functions are executed in a sandboxed environment)
Some reading: Bringing Javascript to WebAssembly for Shopify Functions
But let's get back to our main topic, and let me explain how to create an Extism plugin in JavaScript.
Prerequisites
You will need Extism 0.4.0 and Extims-js PDK to build Wasm modules with JavaScript:
Note, if you encounter a problem installing the PDK, you can do it manually this way (modify according to your environment):
export TAG="v0.5.0" export ARCH="aarch64" export OS="linux" curl -L -O "https://github.com/extism/js-pdk/releases/download/$TAG/extism-js-$ARCH-$OS-$TAG.gz" gunzip extism-js*.gz sudo mv extism-js-* /usr/local/bin/extism-js chmod +x /usr/local/bin/extism-js
The simplest Extism plugin
In a directory, create a file index.js
with the following content:
function say_hello() {
// read function argument from the memory
let input = Host.inputString()
let output = "param: " + input
console.log("π Hey, I'm a JS function into a wasm module π")
// copy output to host memory
Host.outputString(output)
return 0
}
module.exports = {say_hello}
You can see that the code is straightforward and has an entirely similar logic to what we have seen in the previous articles.
Compile the Wasm plugin
To compile the program, use the command below, which will produce a file named hello-js.wasm
:
extism-js index.js -o hello-js.wasm
And now, we will run our Wasm plugin as we did in the previous examples.
Run the say_hello
function of the Wasm plugin
For this, we will use the Extism CLI.
To run the say_hello
function with the parameter "π Hello World π! (from JavaScript)"
, use the following command:
extism call ./hello-js.wasm \
say_hello --input "π Hello World π! (from JavaScript)" \
--wasi \
--log-level info
You will get:
extism_runtime::pdk INFO 2023-07-18T07:08:34.347325607+02:00 - π Hey, I'm a JS function into a wasm module π
param: π Hello World π! (from JavaScript)
If you try to run the plugin without specifying the log level like this:
extism call ./hello-js.wasm \
say_hello --input "π Hello World π! (from JavaScript)" \
--wasi
You will only get this:
param: π Hello World π! (from JavaScript)
In the case of the JavaScript PDK
console.log()
is a kind of alias for calling the host log function of the Extism CLI.
That's all for today. I'll let you familiarize yourself with the development of Extism plugins. If all goes well, we'll write a host application in Go tomorrow.