WebAssembly in NodeRED

HTML tagJavaScript tagNodeRED tagwebassembly tag View on NodeRED

Alongside an investigation into the use of WebAssembly (Wasm) for cross-platform code deployment, I became aware that extensibility and vendor lock-in are concerns for adopters of low-code platforms. NodeRED was therefore used to prove the concept that Wasm can be used to overcome these limitations.

Wasm is designed to act as a middleman between programming languages and the hardware they run on. It implements an efficient, sandboxed memory-safe format, similar to regular assembly. Instead of creating build outputs for every known architecture and operating system, programmers can now target the binary instructions Wasm provides, relying on the platform itself to translate the Wasm instructions into efficient machine code. Adoption initially focused on bringing non-JavaScript languages to the web, but now non-web embeddings are supported too.

Ordinarily, each low-code platform has it’s own structure, format, and language choice for building functionality. To gives just two examples, NodeRED uses JavaScript and HTML files to implement features, but Outsystems uses C# (.NET). Their code is incompatible. Make.com uses JavaScript, but access to system features, like the filesystem, is denied. Even when two platforms are built with the same programming language, bespoke functionality cannot be transferred between them without significant development effort.

The language-agnostic, cross-platform nature of Wasm therefore makes it worthwhile for demonstrating how low-code platforms could be extended while avoiding vendor lock-in.

Features

The wasmer node is shown in purple with a NodeRED flow

The appearance of the node within a flow.

URL Restrictions

Options for the WebAssembly URL

Once downloaded, the Wasm file is stored on disk so that unnecessary network requests are avoided. To ensure the file can still be updated remotely, the ‘age’ parameter is used to trigger a fresh download when the file is too old.

As well as specifying the address and age of a Wasm file, an allowlist can use regular expressions to restrict where they can be fetched from. The URL is checked against syntactic rules and, depending on the ‘mode’ selected, it will be downloaded or denied. This is especially important for this NodeRED node as it’s possible to specify the address of the Wasm file at runtime.

URl Allowlist interface

URL Allowlist interface

Arguments and Input

Function name and arguments in the editor

The simplest way to use a Wasm module within NodeRED is to specify the name of the function to execute and the arguments to pass to it. This can be done through the editor or with messages.

Standard Input

Standard input in the editor

If a Wasm module asks for user input, it can be specified through the editor or in a message. This will be passed to the function after it first executes.

Environment Variables

Environment variables in the editor

Some modules may make use of environment variables, typically when a value remains constant. These can be configured in the editor.

Directories and Files

Directories and files in the editor

The underlying Wasmer library provides support for a virtual filesystem. By specifying paths for folders and content for files, these will be made available to the Wasm module. Paths and files generated by the module are also passed into the next message in the flow.

How to Install

Follow the instructions on the NodeRED website, or run ‘npm i @jackcarey/node-red-wasmer’ in your server directory.

How to Use

Inputs

  1. Allowlist : ‘allowlist (regex)’ : An allowed list of URL regular expression patterns.
  2. URL: ‘url (string)’ : The address to fetch the WebAssembly file from.
  3. Function: ‘functionName (string)’ : The name of the function to run.
  4. Standard Input: ‘stdin (string)’ : Text to pass to the function after it first executes.
  5. Environment Variables: ‘env (JSON)’ : Environment variables that can be accessed withing the function.
  6. Arguments: ‘args (array[string])’ : Arguments to pass into the function separated by spaces.
  7. Directories: ‘dirs (JSON)’ : Virtual file paths made available to the module, and their contents.
  8. Age: ‘maxHours (number)’ : The maximum number of hours before attempting to re-fetch the ‘.wasm’ file.

Overriding Inputs: The following inputs can be overridden by passing them inside ‘msg.payload’: ‘url’, ‘functionName’, ‘stdin’, ‘args’, ‘dirs’.

Outputs

Available inside ‘msg.wasmer’.

  1. Exit Code : ‘exitCode (number)’ : The exit code of the function that ran.
  2. Standard Input : ‘stdin (string)’ : The input buffer as a string.
  3. Standard Output : ‘stdout (string)’ : The console output of the function that ran.
  4. StdErr : ‘stderr (string)’ : Any error messages.
  5. Directories : ‘dirs (JSON)’ : The path and contents of each virtual file.

Example Flow:

Check out the example ‘flows.json’.

Future

Future development of the project may see the node reach feature parity with wasmer-js, as the current version doesn’t support referencing external JavaScript functions. Also, the user interface could be updated to take better advantage of complex typed inputs. With that said, adapters should be written for other low-code platforms to ensure the bespoke functionality targeting WebAssembly is truly portable. Cosmonic is one such platform that goes further, by using only WebAssembly for its nodes.