Flutter Web and WASM
aseem wangoo
Posted on December 5, 2020
Website: https://web.flatteredwithflutter.com/#/
We will cover briefly about
- Precise Intro about WASM
- Web Assembly (WASM) using AssemblyScript
- Integrate with Flutter Web
Article here: https://flatteredwithflutter.com/flutter-web-wasm/
Intro to WASM
- WebAssembly (Wasm) is inspired by the Assembly language. Assembly language is the lowest form of text-based human-readable language which generates optimized fast programs in machine code.
WebAssembly is creating a language that can run as fast as closer to Assembly speeds but on the Web.
- The idea behind WebAssembly is to create a toolchain for other programming languages like C, C++, Rust, etc. to compile directly to WebAssembly. This way, web programmers can write programs in the language of their choice and run inside a browser.
Note: WebAssembly file is a binary file of standard WebAssembly instruction, and should not be written by hand instead compiled. However, it supports a Text Format called Wat that can be read by us.
Web Assembly (WASM) using AssemblyScript
There are different ways to write Web Assembly
In this article, we will write Wasm using Assembly Script
AssemblyScript is
- TypeScript-to-WebAssembly compiler.
- a limited subset of TypeScript, so it shouldn’t take long to get up to speed.
- similar to JavaScript, AssemblyScript lets web developers easily incorporate into their websites.
If you are lazy, you can simply code online using WebAssembly Studio
or if you prefer installing on our machine,
npm i assemblyscript
npm install --save @assemblyscript/loader
npm install --save-dev assemblyscript
For setting up the code structure
npx asinit .
For running the code (to generate Wasm)
npm run asbuild
We will write two functions (addition and multiplication)
export function add(a: i32, b: i32): i32 { return a + b; } export function mult(a: i32, b: i32): i32 { return a * b; }
For more data types in web assembly, see below
After building the code, using npm run asbuild
we see the following files generated
We are interested in the .wasm
binary.
Note:
.wat
is a human-readable format for the.wasm
binary
In case, you want to decode this .wasm
binary, refer to this.
Integrate with Flutter Web
We will add the .wasm
generated above in our assets.
As we know that, we can call Javascript functions inside the Flutter Web, we will utilize this feature. In case you don’t read this.
But during my research, I found a package (wasm_interop) that does all the JS interactions for us.
Step1:
Let’s create an abstract class for Wasm called WasmContract.
abstract class WasmContract { WasmContract.loadFromAsset(String path); Future<bool> initialized(); Object callfunc(String name, List<int> input); bool get isLoaded; }
Step2:
Now, we create WasmLoader class which extends the WasmContract.
- In the initialized function, we load the wasm file from the asset
final bytes = await rootBundle.load(_path); _wasmInstance = await Instance.fromBufferAsync(bytes.buffer);
What happens under the hood?
- JavaScript API has a global
WebAssembly
object available in the browser.
This object has the following static methods:
-
WebAssembly.instantiate():
Compile and instantiate bytes at the same time. -
WebAssembly.instantiateStreaming():
Same functionality as instantiate(), but uses streaming to compile and instantiate the module, which eliminates an intermediate step of converting the .wasm bytes into an ArrayBuffer. -
Instance.fromBufferAsyc
is a wrapper forWebAssembly.instantiateStreaming()
coming from the wasm_interop
Step3:
We override the callfunc (from WasmContract) by
@override Object callfunc(String name, List<int> input) { final _func = _wasmInstance.functions[name]; return _func.call(input.first, input.last); }
- Here,
name
is the function name defined in our Wasm (add and mult
) - We use the
.functions
, which returns an ExportedFunction - Finally, we invoke the function (
.call
)passing the params (which are 2 in our case)
Last Step:
We have 2 buttons on the front end. Load the wasm module first
Future<void> _init() async {
loader = WasmLoader.loadFromAsset(WebAssets.wasmOps);
final isLoaded = await loader.initialized();
}
for calling the functions, we use .callFunc
Pass in the function name and the list of params.
// 'add' is the function defined in our wasm void _addition(List<int> input) { _sum = loader.callfunc('add', [1, 3]) as double; } // 'mult' is the function defined in our wasm void _multiply(List<int> input) { _mult = loader.callfunc('mult', [3, 3]); }
Hosted URL : https://web.flatteredwithflutter.com/#/
Posted on December 5, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.