Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wasm access DOM

Is there any way to get read/write access to DOM and/or the WebAPIs(i.e. fullscreen API) without JavaScript?

I'm trying to build a basic application in C(C source being actually the result of transpilation from a GC language). The app I'm building will run as Desktop app(it's not meant to run in "real" browsers yet) so I can tweak the environment(i.e. the layout engine) if necessary.

like image 403
themihai Avatar asked Mar 06 '17 14:03

themihai


People also ask

Can WASM access the DOM?

wasm binary. By itself, WebAssembly cannot currently directly access the DOM; it can only call JavaScript, passing in integer and floating point primitive data types. Thus, to access any Web API, WebAssembly needs to call out to JavaScript, which then makes the Web API call.

Can WebAssembly modify Dom?

"Unfortunately, the DOM can only be accessed within the browser's main JavaScript thread" - while that is true, it is not the reason why WebAssembly cannot interact with the DOM.

Can you run WASM outside of browsers?

WebAssembly started as a technology for writing applications running in the browser without using JavaScript. Now it can also be used to run applications outside of the browser, thanks to WASI.

Is WASM slower than JavaScript?

If you're already familiar, feel free to skip to the next section. WebAssembly is a low-level assembly language that can run in any major browser. It's designed to be fast, much faster than JavaScript, in order to handle the modern use cases of the web that require higher performance.


3 Answers

In the WebAssembly Minimal Viable Product the only way to call into and out of WebAssembly is through imports and exports. In the future, WebAssembly may gain capabilities which allow the embedder expose APIs directly, in a browser embedding this could include the DOM.

Imports and exports aren't very complicated though: from your C code's point of view they just look like an extern call, similar to a DLL on the Windows platform. You'd likely compile the C code using Emscripten, see its documentation "Call JavaScript functions from C/C++" for details on how this works (since this isn't the question you're asking, but I'm guessing it's the next question).


It's not clear from your question if you:

  1. Want to compile C code and run it within WebAssembly inside a browser.
  2. Want to compile C code and run it within WebAssembly outside a browser.

Or both.

like image 161
JF Bastien Avatar answered Oct 17 '22 08:10

JF Bastien


It all depends on compiler capabilities.

Currently there is no way to access the DOM or any other browser API directly. It is also not possible to store JavaScript references inside of Wasm linear memory or Wasm tables. It is also not possible to use JavaScript references as function arguments or return values. They just do not exists in the MVP type system. However, there is the Reference Type Proposal, which might someday become part of the Wasm runtime, but there is no official release date available.

So, how can Wasm to Host Environment interaction be done? Well, it turns out that the Wasm module system with imports and exports can be used to create an emulation layer. Creating this layer by hand is painful, so it is a good task for a compiler to create it. But how?

For instance, we want to set the document title in the current browser window. The Wasm needs to access the current window instance, select the document, and set the title property of it. As the Wasm runtime cannot access the references, we need to create a mapping table on JS side and some JS functions with mapping logic and import them into the Wasm module.

So, we create a function called getWindow. This function takes the global window reference, puts it into a mapping table and returns the index in the table. This index will be accessible as an I32 on Wasm side. This function is imported into the Wasm module.

Now, we create a function called getDocumentFromWindow. This function takes an index into the mapping table, and returns another index. The implementation looks up the window reference from the mapping table and resolves its document property, and puts this document into the mapping table and returns that index to Wasm. This function is also imported into the Wasm module.

On the Wasm side, we can now indirectly manipulate Wasm host references by our imported functions. Our mapping table emulates JS references by integer indices. This is a slower version of what might come with the Wasm Reference Type proposal.

So this whole mapping logic can be created by the compiler. Once reference types are available, the compiler can be changed and use the new type system for more efficient code.

It you want to see such kind if compiler in action, take a look at https://github.com/mirkosertic/Bytecoder. It can compile JVM bytecode to JavaScript and WebAssembly and provides a transparent way for DOM and Browser API interaction in both ways. It is possible to call DOM from Wasm, and it is also possible to call Wasm from DOM, for instance to implement click-listeners and other cool stuff like interaction with high level frameworks like vue.js.

Disclaimer: I am the inventor of Bytecoder, but the described logic can be adapted to any other compiler.

like image 23
Mirko Sertic Avatar answered Oct 17 '22 09:10

Mirko Sertic


WebAssembly folks haven't any strong idea yet for what JS objects in WebAssembly are going to look like, it seems.

I'd look through PR #1080, which is about the Garbage Collection spec being spun off into it's own repo for now. But while that's happening they're removing the only mentions of the web platform & interop with JS objects that exist in the spec, which is described as:

It's more aspirational that concrete,

like image 4
rektide Avatar answered Oct 17 '22 08:10

rektide