Calling JS object member functions from Wasm
The pong tutorial (https://labs.leaningtech.com/cheerp/tutorials/pong) shows how to handle interactions between JS and Wasm using static functions and global instances.
What is the recommended approach for accessing member functions of dynamically created JS objects from Wasm?
Example code:
Leaning Technologies Developer
Pong with Cheerp - Cheerp Documentation
C/C++ compiler targeting WebAssembly and JavaScript.
11 Replies
WebAssembly provides very little access to JavaScript object. This applies to the standard itself, not to the Cheerp compiler.
The most common solution is to use indexes into a global
[[cheerp::genericjs]]
array or table, then use a global or static [[cheerp::genericjs]]
method to invoke the method from the array
The indexes can be indirectly stored as integers inside any [[cheerp::wasm]]
data structure
This might sound convoluted, but it's what WebAssembly structurally can allow
Some amount of interoperability can be achieved with WasmGC, and we have plans to support than in the short/medium term, but it will come with other side effects, so it's no silver bulletThank you! I will try it
Also, earlier I found this article by @Yuri (https://medium.com/leaningtech/adding-anyref-support-in-a-c-to-webassembly-compiler-2bba3fac707f). Enabling
externref
made it possible to bring Foo entirely to the Wasm world with a couple of changes to that example code. The generated JS+Wasm seems not to be working, though. Maybe I forgot something? Even then, it seems like this feature could be helpful in some use cases. Is it still being supported/developed?@Pedro could you post your code?
The feature is supported, although a bit limited at the moment. We plan to expand it in the future, also in connection with WasmGC support.
@Pedro Anyref allows to pass javascript objects as arguments and use them as return types. There is no support for storing them in a linear memory structure, which is what your code tries to achieve. WebAssembly linear memory is just a large array of bytes, and
externref
is something that does not have a user-visible representation in bytes.Of course
main.cpp:
Makefile:
Oh, I see, thank you for the explanation! Yuri did mention it in his article. Also, I indeed had to make some changes to the code to make it work, more specifically, now I get a reference to the span element every time I want to access it.
It still doesn't seem to work, though, despite compiling. I reckon I may have done something wrong. The browser complains of an invalid character in the string that is passed to
document.createElement
in the generated JS.I think that there is a compiler bug happening here. We need to investigate this further.
As a general advice, to solve the issue of storing js data and use it from wasm: instead of trying to convert everything to wasm, try to have the "top-level" of your code in js, and call into a wasm function with the state it needs as parameters.
You cannot store pointers to js memory in a
[[cheerp::wasm]]
struct, but you CAN do the opposite.Hi @Pedro, we have fixed several bugs related to externref in the latest nightly build of cheerp. Please try again with the new build and let us know if you encounter any more issues.
Hello, thank you! Will try it