#zig-js - interact with the JS host environment from WASM

1 messages · Page 1 of 1 (latest)

onyx sundial
#

https://github.com/mitchellh/zig-js

This makes it relatively easy to interact with a JS host environment from a WASM-compiled binary. I'm still going to flesh this out more and add function calls and so on very soon but this is up. This is loosely based on Go's syscall/js.

GitHub

Access the JS host environment from Zig compiled to WebAssembly. - GitHub - mitchellh/zig-js: Access the JS host environment from Zig compiled to WebAssembly.

fathom pendant
#

Cool stuff. Mach has something similar with sysjs, and I wonder what kind of applications could be built on this.

The optimal way to use WASM is more like a GPU: have the host (or wasm module) preload a bunch of work into a byte buffer and send it over in one single call.
Basically the reason virtual doms exist... Which makes me wonder if a library like this could offer batch commands? Would need some added runtime code on the JS side to decode a command buffer, and encode results into yet another buffer for the wasm side to decode—but what affect will it have in performance for applications that need to use Web APIs frequently?

onyx sundial
#

Oh man I totally didn't even know sysjs exists. That would've been useful damn it lol.

#

Oh well, the more the merrier I suppose. 😄

#

And yeah, I actually do plan on adding batching.

#

I'm using this already to port my font rendering engine to the browser powered by Canvas (for glyph rasterization) and WebGL (rendering).

#

Honestly now that I look at it, really funny how similar our implementations are, probably based off the same ideas really.

fathom pendant
#

Yeah, it's basically reimplementing Go's wasm glue for Zig

onyx sundial
#

I'm also planning a more Zig-like API on top of my low-level "Value" interface. So you can do something more like obj.get(bool, "property"), i.e. fn get(obj: Object, comptime T: type, p: []const u8) T basically.

#

and also want to do some sort of "autorelease-pool" type thing, so you don't need to defer deinit() everywhere to de-reference values.

#

you can just create a pool/arena, create a bunch of values, then deinit the arena and it'll batch them over to the JS side

#

Just trying to make the Zig side more ergonomic

onyx sundial
#
fn set_title_() !void {
    const doc = try js.global.get(js.Object, "document");
    defer doc.deinit();

    try doc.set("title", js.string("Hello!"));
}

fn alert_() !void {
    try js.global.call(void, "alert", .{js.string("Hello, world!")});
}

I did it.

#

It generates more code because of comptime expansion so you can still use the low-level js.Value if you want but this is a lot more ergo

west epoch
#

This is really cool. I like the high level API. Really excited to see how it comes together.

Mach sysjs is indeed based on syscall/js. It was actually created for mach sysaudio so it has a few additional specific features. It can be used for general purpose but it's missing docs.

(I m the original author of sysjs btw)

onyx sundial
#

Thanks! The downside of the high-level API is that since it uses comptime stuff its going to generate a lot more code. I'm going to continue using it in my project, then compare the code sizes with ReleaseSmall between the two. At the very least for prototyping, its a really nice thing to have!

And thanks for sysjs, sorry I didn't find it first 😦

keen copper
onyx sundial
#

Great! That's good to hear since I've been using it as well and no bugs... yet!

  1. You need to think about it like C: pass a pointer and a length. The pointer needs to be to the linear memory of the wasm blob. I solve this by exposing a malloc function out to JS from WASM and then using a Utf8Encoder on the JS side to write into an ArrayBuffer (may have the JS object names wrong here, but something like that.). It is cumbersome but you can build decent abstractions around it. You'll have to consider who "owns" the memory of course to determine who frees, up to you.

  2. Nothing yet, I haven't needed that yet as far as I know. It has been awhile since I dove into the zig-js internals so not sure off the top of my head what options you have there.

keen copper
# onyx sundial Great! That's good to hear since I've been using it as well and no bugs... yet! ...
  1. Thanks, I'll try that!
  2. I need it to addEventListeners. I've checked how does it work in the Go implementation, (here and here). It basically stores the Go function in the shared memory (or a pointer to it probably) and then creates a wrapper function in the JS that basically calls that function using its ID. I've thought that maybe it could be stored in the shared memory as a pointer to a Zig function, but then I can't find the way to call it from the JS, any ideas? I've seen the funcApply function, but I don't think this works here
GitHub

The Go programming language. Contribute to golang/go development by creating an account on GitHub.

GitHub

The Go programming language. Contribute to golang/go development by creating an account on GitHub.

alpine wasp