I have recently started using WebAssembly for some of my projects. I am doing this because I heard that WASM is faster than JavaScript.
When I actually started my first WASM project, I realized that I didn't know how to manipulate the DOM in C++.
Is there any way to do this using WASM?
I have recently started using Web Assembly for some of my projects. I am doing this because I heard that wasm is faster than javascript.
WebAssembly is faster than JavaScript, but only for certain use-cases. With WebAssembly your browser has to do less work to download and compile your code, giving it faster start-up times. However, the runtime performance of WebAssembly is typically only 2 to 3 times faster than JavaScript. See the following article for a very good and practical comparison:
https://hacks.mozilla.org/2018/01/oxidizing-source-maps-with-rust-and-webassembly/
However, WebAssembly has no direct DOM access, so despite its superior performance, you may find that it is slower than JavaScript for your use case due to extra I/O overhead.
For this reason, currently people are finding most success with WebAssembly for algorithmic / compute-intensive tasks.
i realized that I didnt know how to manipuate the dom in c++. Is there any way to do this using wasm?
In order to manipulate the DOM you have to do this via the JavaScript host - your WebAssembly module has to send messages to JavaScript 'asking' it to manipulate the DOM on its behalf.
As this is quite a common challenge, there are various community project that have solutions to the problem. As you are using C++, this one might be of interest to you:
https://github.com/mbasso/asm-dom
In the future, this will get easier, proposals such as Interface Types are making it easier to interop with the host environment and could allow Web APIs to be called directly from WebAssembly.
Unfortunately, the DOM can only be accessed within the browser's main JavaScript thread. Service Workers, Web Workers, and Web Assembly modules would not have DOM access. The closest manipulation you'll get from WASM is to manipulate state objects that are passed to and rendered by the main thread with state-based UI components like Preact/React.
JSON serialization is most often used to pass state with postMessage()
or Broadcast Channels. Bitpacking or binary objects could be used with Transferrable
ArrayBuffers for more performant messages that avoid the JSON serialization/deserialization overhead.
There are now WASM libraries that implement wrappers for things like JQuery or native JS that provide access to the DOM. Not really appropriate to plug specific projects here, but there's several out there. They basically expose a native language interface to the WASM side(your code), but internally they execute JavaScript. They usually handle complexities such as wrapping JavaScript objects handles with objects/classes in WASM. There are not yet specifications for these features in WASM spec. There's lots of ways to accomplish the same goal by passing around object IDs and managing collections of these internally, for example, to effectively have object handles without it being in the spec. So you could call something like 'JQ.Select(".someClass")' on the wrapper and get back an indirect handle to the DOM then call '.Remove()' or '.Text = "Something"' to manipulate it. Of course will vary by library, but point being you get to benefit from the strengths of your WASM language and still interact with the DOM. Some of these wrappers also implement event subscription, so DOM events bubble up into your WASM layer as first class events in your language. In particular a wrapper implementing the full JQuery API would have this capability. I know some people hate on JQuery, but it has a pretty expressive API and the design of having everything being a JQ collection actually simplifies implementing a wrapper greatly.
Quoting from MDN's https://developer.mozilla.org/en-US/docs/WebAssembly/Concepts#porting_from_cc page:
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. Emscripten therefore creates the HTML and JavaScript glue code needed to achieve this.
Note: There are future plans to allow WebAssembly to call Web APIs directly.
I'm not sure what exactly "HTML and JavaScript glue code needed to achieve this" means. Doing a quick search through the Emscripten reference docs, I don't see anything for DOM-mutating APIs. I do see https://emscripten.org/docs/api_reference/html5.h.html, but that seems to just be for events. I think you might need to write some of your own layer of JS functions that do DOM modifications, and write the bindings to call those JS functions from the WASM side. For that, see https://emscripten.org/docs/porting/connecting_cpp_and_javascript/index.html.
I am doing this because I heard that Wasm is faster than javaScript.
Although you're not wrong, however I must say, - and I say this as an avid user of WASM as well as someone who absolutely hates JS - you shouldn't use WASM just because its faster. You should always use the right tool for the job.
And ironically, if you do want the fastest and most powerful webapp, you'll have to ditch DOM entirely (which is what a lot of WASM projects do) in favor of WebGL-centric. DOM engines are very slow, bogged down by decades of compatibility and sad engineering, and will only drag WASM to a crawl if you choose to interact with it.
So unless you're making something like figma.com (C++), I suggest sticking to JS (or if your like me and hate everything about that language, use typescript).
WASM has no DOM interaction because the designers of WASM did not want the efficiency of WASM and the inefficiencies of DOM to overlap, and neither should you.
© 2022 - 2024 — McMap. All rights reserved.