Home / Blog Menu ↓

Blog: #learning-webtech

Learning WebAssembly, part 2

Continuing on with the AssemblyScript concepts chapter.


No any or undefined — interesting. And good, I think. But no union types yet? A little sad.

Okay, so module imports and exports are the main way (possibly the only way) the host communicates with the Wasm script. I knew about exports but didn’t know about declare and module imports. Nice.

The tree-shaking approach to compiling is interesting — dead code doesn’t get type checked, for example.


Not as much type inference as TypeScript. Good to know.

Oh, interesting: WebAssembly has distinct operations for signed and unsigned comparisons. (gt_s vs. gt_u, for example.) Also, == === ===. (Couldn’t resist. But yes, given that the basic types aren’t nullable etc., makes sense that == is also doing strict equality.)

Standard library

I think the reason I like reading through standard library docs is the same reason I like reading through dictionaries — both open up a world of possibilities. And each time I go exploring, I find something new. Need to do more of both.

I like that the low-level WebAssembly instructions are available to AssemblyScript.

Nice, there’s manual memory management when you need it.

StaticArrays for C-like arrays with better performance, got it.

The string considerations section was interesting.

Implementation status

Some drama with WASI and the component model. I don’t know enough about the situation to comment, but I hope things get sorted out in a way that’s good for standards and the web platform.

Ah, there aren’t closures, Promises, exceptions, or rest parameters in AssemblyScript. That’s very good to know.

Using the runtime

A few different runtime options, including support for a custom runtime. Interesting.

Reading about the memory layout was fun. Reminds me of writing C twenty-some years ago. I need to come up with a low-level project to work on sometime.

And that’s a wrap on the documentation. I’ve decided that my learning project for AssemblyScript will be a small convex hull implementation. Notes on that coming soon!

Reply via email

Learning WebAssembly, part 1

I’m having so much fun learning Elixir that I’ve decided to do a similar thing with web technologies I haven’t used yet. Similar to the 12in23 posts, these will be long and informal and more stream-of-consciousness, and I will say “interesting” and “looks like” far too often.

First up: WebAssembly. Other things I’m looking forward to trying out afterwards: WebGPU, WebRTC, WebGL (I’ve used Three.js on several projects but haven’t used WebGL directly if I recall correctly), WebSockets, service workers, web components, and a number of smaller things (primarily CSS features I haven’t yet used).

So, Wasm. I’ve read bits and pieces about it over the years but haven’t yet actually tried it on anything. I’m going to start arbitrarily with AssemblyScript. Later on I’ll use Rust, and I want to try writing the Wasm text format manually, too.

To begin, I’m going through the AssemblyScript Book.

Getting started

I generated a new AS project with asinit and have been exploring the files it produced, starting with release.js (to get a feel for how the Wasm code gets pulled in). This sample project just adds two numbers together, by the way. The actual AssemblyScript source is straightforward.

In release.js, I initially wasn’t sure what compile meant (in this context) since the example is compiling release.wasm which is already a binary. Looked up the compile page, which explained that the Wasm binary needs to be compiled into a Module, which the MDN key concepts page tells me is executable machine code. And it’s stateless. Okay, that makes sense.

I also wasn’t sure what instantiate did in this particular context. Found the instantiate page, which said it turns a Module into a stateful Instance. That also makes sense now. I imagine the reason one might want to instantiate a Wasm module more than once would be splitting the work up across workers, but I haven’t verified that. Also, looks like instantiateStreaming is now preferred, which simplifies things a little, so you don’t need both compile and instantiate. (That won’t matter for this AssemblyScript experimentation since I’ll be writing AssemblyScript and not finagling with the final JS unless I really can’t resist.)

Looking now at release.wat, because I’m intrigued and I also sometimes like to go in blind and figure things out on my own.

I completely forgot that the Wasm text format is Lispy.

Hmm, I see the $i32_i32_=>_i32 type defined. (By the way, seeing a type defined in an assembly language that looks like Lisp is kind of trippy but also quite cool.) I don’t see that type being used anywhere, though. Must be implicit. I imagine it applies to the exported function. If there’s more than one exported function, maybe they apply in order?

There’s a memory being exported alongside the add function. Interesting. I imagine this gives access to the memory the Wasm script is being executed in (the sandbox), but I’m not entirely sure why — what the host would use it for, I mean. Something to look into when I get back to the text format later.

The function definition itself looks fairly straightforward. Arguments and result type followed by the body of the function. Based on the i32.add instruction not taking any arguments, I’m guessing local.get pushes things onto a stack which i32.add then pops from.

I’m excited to dive deeper into the text format! But back to AssemblyScript proper.

Using the compiler

Okay, looks like memory can be both imported and exported, and the size can be specified as well. Interesting that this is set here (where the AssemblyScript is being compiled into a Wasm binary) rather than in the host when the Wasm is instantiated. My mental model of WebAssembly is more patchy than I realized — it’s been a while since I read an intro — but I’m having fun figuring things out archaeologically right now, so I’ll keep going like this for a bit longer.

Looks like there are several small runtimes that can be compiled in, some with garbage collection. Interesting, didn’t know that. (Looks like it’s a WIP.) And there are threads now. Wow.

Ooh, the compiler API can be used programmatically. I guess I shouldn’t be surprised.

Looks like it’s still just low-level data types that can be passed across module boundaries. Nice that AssemblyScript generates bindings for strings, arrays, and objects, though. That makes it far more usable.

Transforms are intriguing. Probably not useful for most projects, but still intriguing.

I’m going to stop here for this post, to try to keep things from going on too long in any given post. Looking forward to working through the concepts chapter next!

Reply via email