Minimal JavaScript Shim
Recently, I was reading this article about compiling Ada to WebAssembly and running in the browser. I haven’t used Ada and I don’t plan to, but because I was curious about how they were doing OpenGL from WebAssembly, I took a peak at the JavaScript shim they were using and found code like this:
__adawebpack__html__Button__disabled_getter: function(identifier) {
return +(__adawebpack_o2i.too(identifier).disabled);
},
__adawebpack__html__Button__disabled_setter: function(identifier,to) {
__adawebpack_o2i.too (identifier).disabled = (to !== 0);
},
__adawebpack__html__Canvas__height_getter: function(identifier) {
return __adawebpack_o2i.too(identifier).height;
},
I’m sure that it works, but I found it looked a bit clunky. So I began thinking
about how I would get the same behavior while not having to produce so much
boilerplate code. The idea of using handles to reference JavaScript objects
is good, so I kept it, but tried to reduce the remainder to as few API calls
as I thought was reasonable. JavaScript helps here in that ever object except
window
can be accessed thru window
with indexing (i.e. []
)
Here is what I came up with:
handle_t jsapi_new_string( size_t len, char* start );
handle_t jsapi_new_number( float f );
handle_t jsapi_new_object( );
void jsapi_get_string( handle_t obj, size_t buffer_size, char* buffer );
void jsapi_get_number( handle_t obj, float* f );
void jsapi_release( handle_t );
handle_t jsapi_call( handle_t base, handle_t func, size_t argc, handle_t* argv );
handle_t jsapi_get_index( handle_t base, handle_t index );
void jsapi_set_index( handle_t base, handle_t index, handle_t value );
handle_t jsapi_eval( size_t len, char* code );
The first three functions are for creating new JavaScript objects. Add in
jsapi_set_index
and you can create any JavaScript literal excluding
functions from non-JavaScript code.
The next two functions are for getting results back from JavaScript.
Next is the only memory management function, which releases the reference to the object associated with a given handle.
Next is a generic function call interface, then index get and set, and
finally jsapi_eval
, which allows arbitrary JavaScript code execution
at the expense of being both slow and requires preparing the code for
anything other than static code includes which would be better place in
a static .js file and included into the web page.
This is still untested, as I am currently stuck working without my normal workstation making things take considerably longer than normal, but in the next few days that should no longer be the case and I will get a demo thrown together and posted to this blog.