/react-native-webassembly

⚛️ 🏎 WebAssembly for React Native powered by C++ TurboModules.

Primary LanguageCMIT LicenseMIT

react-native-webassembly

This package enables WebAssembly for React Native powered by C++ TurboModules and Wasm3, a fast and universal WebAssembly runtime.

react-native-webassembly provides React Native applications with the capability to execute universal Wasm binaries with native speed.

✏️ This project is still in active development. The following tasks are still remaining to be completed:

  • Sanitize C++ memory management practices.
  • Normalize execution and result handling of userland export functions.
  • Test framework implementation.

Pull Requests are welcome! 🙏

📡 Installation

  1. First, ensure your React Native application supports the New Architecture:
  2. Install react-native-webassembly:
    yarn add react-native-webassembly

✍️ Usage

The goal of react-native-webassembly is to export a browser-equivalent interface to the WebAssembly API.

To initialize a new WebAssembly module, we'll need to instantiate an module using a buffer populated with a .wasm binary. In the snippet below, we show how to download and instantiate the reference Hello World example:

import axios from 'axios';
import * as WebAssembly from 'react-native-webassembly';

const {
  data: bufferSource,
} = await axios({
  url: 'https://github.com/torch2424/wasm-by-example/raw/master/examples/hello-world/demo/assemblyscript/hello-world.wasm',
  method: 'get',
  responseType: 'arraybuffer',
});

const module = WebAssembly.instantiate<{
  add: (a: number, b: number) => number;
}>(bufferSource);

You'll notice that in our call to instantiate, we can also pass typing information for the Exports of the module. In this case, the hello-world.wasm binary exports a function to add two numbers, add.

Once configured, we can execute the compiled wasm module from our JavaScript code, using the type-safe exported interface:

module.instance.exports.add(1, 2); // 3.

It's also possible to declare an importObject to receive callbacks from the compiled module, which declares a list of callback function implementations which can be invoked by the WebAssembly runtime.

Warning

Some native modules require the presence of certain function implementations. Without specifying module-specific required dependencies, instantiation will fail.

For example, the Circom library converts arithmetic circuits used for generating, evaluating and verifying SNARKs are expressed as WASM modules which require the runtime to define an exceptionHandler function.

It's simple to define an importObject:

const module = WebAssembly.instantiate<{
  getVersion: () => number;
  getFieldNumLen32: () => number;
  // ...
}>(bufferSource, {
  imports: {
    exceptionHandler: (value: number) => console.error(value),
  },
});

Here, we declare an exceptionHandler as imports to the compiled module. Without declaring this required dependency, the module would fail to compile.

You can find a working implementation of this process in the Example App.

✌️ License

MIT