Typescript allows us to code with types, but WebAssembly only supports primitive types.
Doubly frustrating, a WebAssembly supported language like Zig can easily represent the same type.
Are we screwed? Do we have to pass each field as a function parameter? That would work, but we can do better.
The trick is remembering, in a system language like Zig, a struct is simply a memory layout. All we need todo is write the TypeScript object into WebAssembly memory, and Zig will be able to read it natively.
If we line up all our ducks in a row on the Zig side, we can interpret the pointer directly as a pointer to a
Holup, didn't we say WebAssembly only supports primitive types? How is it possible to receive a Person pointer? Recall pointers are just memory addresses. The WebAssembly memory address space is 32-bit; thus, pointers are
*Person is the same as
What black magic is this
encodePerson? How does it take in a TypeScript person and produce a WebAssembly memory address?
The memory layout is specified by the C ABI. Here is how Bob, with a GPA of 3.6, would be laid out.
The address of the person
0x0000AA00 is returned by the allocator. Same for the address of name
Once we understand the memory layout,
encodePerson is straightforward.
encodePerson allocated memory, we need to clean this up on the Zig side.
try..finally. Just note that
defers are executed last in, first out.
Person from Zig to Typescript is the same process but reverse. Allocate memory for
Person in Zig, pass over the pointer, decode
Person out of memory in Typescript, and deallocate memory.
See full code sample for passing
Person in either direction.
Do you want to learn the latest web tech while building esports? You're in luck, Battlefy is hiring.