A look into AssemblyScript
Ajit Singh
Software "Architect"
I delete node_modules for money
💶
Experts say that .....
for a stack-based virtual machine.
it is a
binary instruction format
In layman's terms..
...it is a
new,
low level code,
for the web.
Brand new !
...it is a
new,
low level code,
for the web.
One level closer !
...it is a
new,
low level code,
for the web.
wasm-function[0]:
sub rsp, 8 ; 0x000000 48 83 ec 08
mov edx, edi ; 0x000004 8b d7
mov ecx, edx ; 0x000006 8b ca
mov eax, edx ; 0x000008 8b c2
imul ecx, eax ; 0x00000a 0f af c8
mov eax, ecx ; 0x00000d 8b c1
nop ; 0x00000f 66 90
add rsp, 8 ; 0x000011 48 83 c4 08
ret ; 0x000015 c3and beyond !
...it is a
new,
low level code,
for the web.
*
* The WebAssembly System Interface: https://wasi.dev
So, how do I code in WebAssembly
Your Code + compile to WASM = WASM
"Human-Readable" format
(module
(func $add (param $n0 i32) (param $n1 i32) (result i32)
get_local $n0
get_local $n1
i32.add
)
(export "add" (func $add))
)Benefits
Hold your 🐎🐎🐎🐎🐎🐎
The Comfort of Familiarity!
Typescript
AssemblyScript
vs
export function add(a: number, b: number): number {
return a + b;
}The Comfort of Familiarity!
Typescript
AssemblyScript
vs
export function add(a: int32 , b: int32 ): int32 {
return a + b;
}vs
Looks like a duck but .....
Getting started
npm initnpm install --save @assemblyscript/loader
npm install --save-dev assemblyscriptnpx asinit .How many number type you want? Yes
Types are stronger in this one !
// 😢
function foo(a?) {
return a + 1
}
// 😊
function foo(a: i32 = 0): i32 {
return a + 1
}Types are stronger in this one !
// 😢
function foo(a: i32 | string): void {
}
// 😊
function foo<T>(a: T): void {
}Types are stronger in this one !
function doSomething(something: string | null): void {
if (something) {
something.length // works
}
}Types are stronger in this one !
// 😢
var a = {}
a.prop = "hello world"
// 😊
var a = new Map<string,string>()
a.set("prop", "hello world")
Equal Equal Equal
const a = "hello"
const b = a
const c = "h" + a.substring(1)
if (a === b) { /* true */ }
if (a === c) { /* false */ }
if (a == c) { /* true */ }Importing JS functions in WASM
// In your assemblyscript code
export declare function log(n: i32): void;
// In your js/ts code
const module = await WebAssembly.instantiateStreaming(
fetch("./build/optimized.wasm"),
// without annotation is file name and function name
index: {
log: console.log,
},
);
@external("demo", "log")
export declare function log(n: i32): void;
const module = await WebAssembly.instantiateStreaming(
fetch("./build/optimized.wasm"),
demo: {
log: console.log,
},
);Pointers ping pong
var { hello, memory,
__new, __pin, __unpin } = wasm.exports;
var input = "Stonks";
var length = input.length;
// allocate memory (usize, String (id=1))
var pt = __new(length << 1, 1);
// load bytes into memory
var ibytes = new Uint16Array(memory.buffer);
for (let i = 0, p = pt >>> 1; i < length; ++i)
ibytes[p + i] = input.charCodeAt(i);
// pin object
var pti = __pin(pt);
// call wasm
var pto = __pin(hello(pti));
// retrieve string size
var SIZE_OFFSET = -4;
var olength = new Uint32Array(memory.buffer)[pto + SIZE_OFFSET >>> 2];
// load string from memory
var obytes = new Uint8Array(memory.buffer, pto, olength);
var str = new TextDecoder('utf8').decode(obytes);
// unpin objects for GC
__unpin(pti);
__unpin(pto);
console.log(str);import loader from "@assemblyscript/loader";
const { __newString, __getString } = wasm.exports;
// Let loader take care of making pointer for the string
const stonkPointer = __newString("Stonks");
// Let loader take care of reading value from pointer
const returnValuePointer = functionTakingString(stonkPointer);
const getStonksValue = __getString(returnValuePointer);
console.log(getStonksValue);
Syntactic
import loader from "@assemblyscript/loader";
// in Assemblyscript
export const Int32Array_ID = idof<Int32Array>();
// In js/ts
const {multiply,Int32Array_ID,__newArray,__getArray} = wasm.exports;
const input = [1, 2, 3];
const ai = __newArray(Int32Array_ID, input);
// call wasm, output array
const ao = __getArray(multiply(ai, 2));
console.log(ao);Syntactic
Syntactic
export declare function log(n: i32): void;
const wasm = await loader.instantiate(fetch("./build/optimized.wasm"), {
index: {
log: console.log,
},
});
Clean that up!
Provides garbage collection
--exportRuntime compiler option needed for strings, arrays
Work in Progress 🚧
Also checkout the ecosystem
Yea 👍 or Nay 👎
Of course WebAssembly limitations apply!
Evolving language based for a specification that itself evolving.
NOT a drop in replacement for your Typescript code!
I don't know ! Haven't burned my fingers with it on prod yet !
Great way to get started with WebAssembly