How we implemented support for the experimental anyref feature in the Cheerp C++ to WebAssembly compiler, and what you can do with it.

WebAssembly in its current MVP form is shipped by all major browsers and is already capable of amazing things. This does not mean that its development has concluded: on the contrary, there are many post-MVP feature proposals at different stages of development.

One such proposal is about adding the so-called anyref / externref type (and related instructions) to the specification. But what is anyref, and why is it desirable to add it to WebAssembly?

WebAssembly Anyref

The full proposal is explained in detail in this repo, but the basic idea is to be able to represent opaque host references (JavaScript objects in the case of a Web Browser) from WebAssembly. Even with this proposal, these references can only be passed around via function arguments and return values, and stored and loaded in tables. Future proposals will expand what is possible to do, and eventually lead to full GC support in WebAssembly.

The current specifications of anyref are quite limiting, and in particular, they don’t allow to store these references in linear memory directly. They need to be stored in a table at an index, and then the index itself can be stored in linear memory. Doing this requires some runtime bookkeeping of tables, to “allocate” and “deallocate” slots and give out indices.

Integrating anyref support directly in languages like C/C++ and Rust (i.e. directly representing a DOM object as anyref) is not straightforward, and the current mainstream opinion seems to be to use anyref under the hood in autogenerated glue code while keeping the actual user-written code dealing with just indices (see here for an interesting thread discussing this).

Image for post

Demo application of a C++ application compiled to Wasm with anyref support

Cheerp

I work on Cheerp, a C++ to JavaScript and WebAssembly compiler based on LLVM.

The Cheerp compiler is in an interesting and unique position here: since its inception, it has supported an object memory model, where C++ objects are stored as JavaScript garbage collected objects, in addition to being able to store them in a contiguous linear memory (which is the memory model of WebAssembly).

This allows Cheerp to compile C++ code to regular JavaScript, and interoperate easily with JavaScript libraries (including the native browser APIs). It is also possible to mix and match these two representations and choose one or the other for any declared struct/class.

There are some limitations: while linear memory objects (declared with the cheerp::wasm attribute) can be used by code compiled to both WebAssembly and JavaScript, garbage collected JavaScript objects (declared with the cheerp::genericjs attribute) cannot be accessed by code compiled to WebAssembly. This is enforced by our compiler frontend. anyref can allow us to relax some of the current restrictions since we are now able to pass around references to JavaScript objects in WebAssembly code!

#wasm #webassembly #cplusplus #developer

Adding Anyref Support in a C++ to WebAssembly Compiler
2.55 GEEK