Skip to Content
Technical Articles

Consuming WebAssembly modules from OpenUI5/SAPUI5 Applications

Introduction

In this article I will show you how to consume WebAssembly modules from OpenUI5/SAPUI5 application. We will fetch WebAssembly module (built with Rust), parse its metadata and render available functions and their signatures inside sap.m.List control!

We will learn following:

  • Brief introduction to WebAssembly
  • How to create WebAssembly modules
  • How to fetch them in JavaScript
  • How to call WebAssembly functions from our OpenUI5/SAPUI application

The final result is located at GitHub: https://github.com/gladimdim/webasm-ui5-loader.

What is WebAssembly

WebAssembly is a new binary format designed to be very compact and fast. WebAssembly target is to be almost the same performant as native applications written in C/C++. This format is now supported by all major browsers: Chrome, Safari, Edge and Firefox. You might already use WebAssembly apps on the web.

List of browsers with WebAssembly support:

WebAssembly is not a standalone language, though you can manually write binary code or use WebAssembly Text Format to create programs in it. Other languages must compile to WebAssembly. One of the best tools for WebAssembly are provided by Rust Language [https://www.rust-lang.org/] and C/C++.

You can read more about WebAssembly here:

https://www.infoworld.com/article/3291780/web-development/what-is-webassembly-the-next-generation-web-platform-explained.html

How to create WebAssembly [wasm] modules

For this article we will use Rust language to compile to wasm binary format.

We will write several functions like sum and multiply in Rust and then compile them into wasm.

To compile Rust code to WebAssembly we will be using wasm-pack: https://github.com/rustwasm/wasm-pack

Rust project is located at GitHub inside subfolder: https://github.com/gladimdim/webasm-ui5-loader/tree/master/wasm-math

Also repository contains already built wasm module: https://github.com/gladimdim/webasm-ui5-loader/blob/master/webapp/wasm_math_bg.wasm

Rust code at https://github.com/gladimdim/webasm-ui5-loader/blob/master/wasm-math/src/lib.rs contains two functions:

#[wasm_bindgen]
pub fn add_two(a: i32, b: i32) -> i32 {
    a + b
}

#[wasm_bindgen]
pub fn multiply_by(a: i32, b: i32) -> i32 {
    a * b
}

We will call these functions from JavaScript (OpenUI5 application).

If you want to compile that code on your own, then follow detailed steps provided at this README: https://github.com/gladimdim/webasm-ui5-loader/tree/master/wasm-math

Once you compiled that project, you can copy the result (wasm file) into webapp folder.

How to call WebAssembly functions from JavaScript

GitHub repository is a valid OpenUI5/SAPUI5 application. So you can deploy it to SAP Web IDE and run the code there, or you can do it from your machine.

We will initialize WebAssembly module just inside onInit method of our Controller:

/***********************/
return Controller.extend('com.gladimdim.webasmloader.controller.App', {
        onInit: function() {
            this.aSearchFilters = [];
            this.aTabFilters = [];

            fetch('./wasm_math_bg.wasm')
/***********************/

We use standard Fetch API to load wasm file from the server:

fetch('./wasm_math_bg.wasm')
   .then(response =>
        response.arrayBuffer()
   )
   .then(bytes => {
      return WebAssembly.instantiate(bytes);
})

From response we get ArrayBuffer and ask WebAssembly to instantiate the module from it.

WebAssembly.instantiate returns a promise, which resolves an object with our functions:

 

Now we can call our functions just from Dev Tools Console:

var { add_two } = results.instance.exports;

add_two(5, 3); // 8

var { multiply_by } = results.instance.exports;

multiply_by(10, 20); // 200

Reading MetaData from WebAssembly Module

For educational purpose, I decided to use https://www.npmjs.com/package/@webassemblyjs/wasm-parser library to get meta information about exposed functions.

We can use wasm-parser Decode function to create a JSON with needed info:

fetch('./wasm_math_bg.wasm')
    .then(response =>
        response.arrayBuffer()
    )
    .then(bytes => {
        var ast = _webassemblyjs_wasmParser.decode(bytes);
        // read only exported functions
        var exportedFunctions = ast.body[0].fields.filter(f => f.name !== "memory" && f.type ===
            "ModuleExport").map(f => f.name);
        // update functionsMeta variable with a list of exported functions and their meta data
        functionsMeta = ast.body[0].fields.filter(f => {
            if (f.type === "Func" && exportedFunctions.indexOf(f.name.value) >= 0) {
                return true;
            } else {
                return false;
            }
        });
        // continue initialization process for WebAssembly module
        return WebAssembly.instantiate(bytes);
    })

Once ‘functionsMeta’ are initialized, we can create JSONModel and render our list:

.then(results => {
    webAssemblyModule = results.instance;

    var functions = {
        "wasmFunctions": functionsMeta.map(exportedFn => {
            return {
                exec: webAssemblyModule.exports[exportedFn.name.value],
                name: exportedFn.name.value,
                arguments: exportedFn.signature.params,
                results: exportedFn.signature.results[0]
            };
        })
    };
    oModel = new JSONModel(functions);
    this.getView()
        .setModel(oModel, "Functions");
});

Running OpenUI5 with WebAssembly

You can use official OpenUI5 Command Line Tools https://github.com/SAP/ui5-cli to run on your local machine.

Running Locally

Open command line and enter following commands:

npm install
ui5 serve

Then open this URL in the browser:

http://localhost:8080/index_ui5.html

Running in the SAP WebIDE

You can also run the same project in SAP WebIDE.

For this you have to clone the repo, then run index.html as you do with any other SAP WebIDE project.

 

You will see a list of exported functions from WebAssembly module. i32 is a name of WebAssembly type (integer 32bit). We bind them to ObjectListItem to let the user now, that function returns integer.

Be the first to leave a comment
You must be Logged on to comment or reply to a post.