Nice to see momentum here. Even outside of direct access to WebAPIs, having the ability to specify interfaces for WASM modules is a big deal, and unlocks all sort of cool options, like sandboxed WASM plugins for native apps...
JavaScript is the right abstraction for running untrusted apps in a browser.
WebAssembly is the wrong abstraction for running untrusted apps in a browser.
Browser engines evolve independently of one another, and the same web app must be able to run in many versions of the same browser and also in different browsers. Dynamic typing is ideal for this. JavaScript has dynamic typing.
Browser engines deal in objects. Each part of the web page is an object. JavaScript is object oriented.
WebAssembly is statically typed and its most fundamental abstraction is linear memory. It's a poor fit for the web.
Sure, modern WebAssembly has GC'd objects, but that breaks WebAssembly's main feature: the ability to have native compilers target it.
I think WebAssembly is doomed to be a second-class citizen on the web indefinitely.
E.g. it feels like a lot of over-engineering just to get 2x faster string marshalling, and this is only important for exactly one use case: for creating a 1:1 mapping of the DOM API to WASM. Most other web APIs are by far not as 'granular' and string heavy as the DOM.
E.g. if I mainly work with web APIs like WebGL2, WebGPU or WebAudio I seriously doubt that the component model approach will cause a 2x speedup, the time spent in the JS shim is already negligible compared to the time spent inside the API implementations, and I don't see how the component model can help with the actually serious problems (like WebGPU mapping GPU buffers into separate ArrayBuffer objects which need to be copied in and out of the WASM heap).
It would be nice to see some benchmarks for WebGL2 and WebGPU with tens-of-thousands of draw calls, I seriously doubt there will be any significant speedup.
Your logic is circular though. You are saying that there won't be much speedup for the sort of things people already do in WASM - but the reason they're doing them in WASM is because they're not slowed down too much.
What you don't get much is people doing standard SPA DOM manipulation apps in WASM (e.g. the TodoMVC that they benchmarked) because the slowdown is large. By fixing that performance issue you enable new usecases.
Yeah, I don't think it bears out that DOM operation invocations constitute a major bottleneck for a lot of web applications. Certainly the execution of those operations (like layout invalidation and calculation) can be expensive, but those would not benefit. I can't think of applications with a massive amount of DOM calls that would benefit from lower latency.
This (appears as though it) all could have happened half a decade ago had the interface-types people not abandoned[1,2] their initial problem statement of WebIDL support in WebAssembly in favour of building Yet Another IDL while declaring[3] the lack of DOM access a non-issue. (I understand the market realities that led to this, I think. This wasn’t a whim or pure NIH. Yet I still cannot help but lament the lost time.)
I have to wonder if Apple will allow any of this to move forward in the W3C standards committee since they've been blocking many things that would make web browsers as capable as native apps.
Apple perceives web-based applications as chipping away at their app store (which makes them money), and so they cripple their Safari browser and then force all mobile browsers on iOS to use their browser engine, no exceptions, so that developers are forced to make a native app where Apple can then charge the developers (and thus the users) for a cut of any sales made through the app.
It's one reason the DOJ started suing Apple, but I fear that may have been sidelined due to politics.
The WASM cliff is very real. Every time I go to use it, because of the complexity of the tool chain and process of going from zero to anything at all, I feel like I'm already paying a cognitive tax. I worry that I should update my tooling, look into the latest and greatest, understand the tooling better, etc... It would be incredible to see that improved.
The difference in perf without glue is crazy. But not surprising at all. This is one of the things I almost always warn people about, because it's such a glaring foot gun when trying to do cool stuff with WASM.
The thing with components that might be addressed (maybe I missed it) is how we'd avoid introducing new complexity with them. Looking through the various examples of implementing them with different languages, I get a little spooked by how messy I can see this becoming. Given that these are early days and there's no clearly defined standard, I guess it's fair that things aren't tightened up yet.
The go example (https://component-model.bytecodealliance.org/language-suppor...) is kind of insane once you generate the files. For the consumer the experience should be better, but as a component developer, I'd hope the tooling and outputs were eventually far easier to reason about. And this is a happy path, without any kind of DOM glue or interaction with Web APIs. How complex will that get?
I suppose I could sum up the concern as shifting complexity rather than eliminating it.
The whole WASM thing just went sideways from the start. It feels like the property of being practically unreadable and unwritable for humans was a design criterium, it is certainly the primary "feature" enabled by the stack approach.
Then there is the single array of memory that makes modern memory allocators not really work, resulting in every WASM compiler scrounging up something that mashes the assumptions of the source language into a single array.
The “single array of memory” is not the problem; that’s what all these languages already expect. The problem is the lack of meaningful memory APIs, e.g. virtual memory capabilities. I am co-champion of a proposal to fix this but have not been able to prioritize it for a while, unfortunately: https://github.com/WebAssembly/memory-control/blob/main/prop...
Great to see it happening finally. Can we also get compute shaders with WebGL2 now? I don't want to move everything to WebGPU just for compute shaders and I don't know why they kept rejecting the proposals.
At a high level this sounds great. But looking into the details about how the component model will be implemented, it looks very complicated due to concurrency:
This is the right direction. Another important bit I think it’s the GC integration. Many languages such Go, C# don’t do well on wasm due the GC. They have to ship a GC as well due the lack of various GC features(I.e interior pointers)
Every new standard today doesn't care about being clean and simple to use. They all maximize the JS boilerplate needed to make a basic example work. Everything is designed today for 'engineers' and not 'authors' without any friendly default workflow. I'm glad they still care about this.
Another important aspect is that, without an external library like `wabt`, I can't just open Notepad, write some inline WASM/WAT in HTML and preview it in a browser, in the same way that HTML+CSS+JS works. Having to obtain a full working toolchain is not very friendly for quick prototyping and demonstrative needs.
> Thankfully, there is the esm-integration proposal, which is already implemented in bundlers today and which we are actively implementing in Firefox.
From the code sample, it looks like this proposal also lets you load WASM code synchronously. If so, that would address one issue I've run into when trying to replace JS code with WASM: the ability to load and run code synchronously, during page load. Currently WASM code can only be loaded async.
We could finally write programs for the browser in any language that compiles to WebAssembly. And even mix and match multiple languages. It would be amazing.
The web is fascinating: we started with a seemingly insane proposition that we could let anyone run complex programs on your machine without causing profound security issues. And it turned out that this was insane: we endured 20 years of serious browser security bugs caused chiefly by JavaScript. I'm not saying it wasn't worth it, but it was also crazy.
And now that we're getting close to have the right design principles and mitigations in place and 0-days in JS engines are getting expensive and rare... we're set on ripping it all out and replacing it with a new and even riskier execution paradigm.
> The web is fascinating: we started with a seemingly insane proposition that we could let anyone run complex programs on your machine without causing profound security issues.
Isnt this what an OS is supposed to do? Mobile operating systems have done a pretty good job of this compared to the desktop OS.
0-days mostly got expensive from compiler optimizations and other security guarantees that carry over to webassembly, like ASLR and pointer authentication, as well as sandboxes and multi-process architectures. It's not all thrown away here.
Browsers are millions of lines of code, the amount of UAFs, overflows, etc so far is not the bottleneck.
Agree with the points. But when reading this, it seems much more complicated than using JavaScript on the web when developing realworld applications. However I think that will not be an issue because of AI.
Agree with the points. But when reading this, it seems much more complicated than using JavaScript on the web when developing real-world applications. However I think that will not be an issue because of AI.
This article perfectly captures the frustration of the "WebAssembly wall." Writing and maintaining the JS glue code—or relying on opaque generation tools—feels like a massive step backward when you just want to ship a performant module.
The 45% overhead reduction in the Dodrio experiment by skipping the JS glue is massive. But I'm curious about the memory management implications of the WebAssembly Component Model when interacting directly with Web APIs like the DOM.
If a Wasm Component bypasses JS entirely to manipulate the DOM, how does the garbage collection boundary work? Does the Component Model rely on the recently added Wasm GC proposal to keep DOM references alive, or does it still implicitly trigger the JS engine's garbage collector under the hood?
Really excited to see this standardize so we can finally treat Wasm as a true first-class citizen.
I’m wondering if the recent improvements in sending objects through sendMessage in v8 and Bun change the math here enough to be good enough.
SendMessage itself is frustratingly dumb. You have excessively bit fiddly or obnoxiously slow as your options. I think for data you absolutely know you’re sending over a port there should be an arena allocator so you can do single copy sends, versus whatever we have now (3 copy? Four?). It’s enough to frustrate use of worker threads for offloading things from the event loop. It’s an IPC wall, not a WASM wall.
Instead of sending bytes you should transfer a page of memory, or several.
This is a great step, if only because it enforces more convention for the "right" way to do things by providing a simpler mechanism for this.
WRT WebAssembly Components though, I do wish they'd have gone with a different name, as its definition becomes cloudy when Web Components exist, which have a very different purpose. Group naming for open source is unfortunately, very hard. Everyone has different usages of words and understanding of the wider terms being used, so this kind of overlap happens often.
I'd be curious if this will get better with LLM overseers of specs, who have wider view of the overall ecosystem.
What's there is already dead simple. The JS side and the WebAssembly module instance share a memory image and tables of imported and exported functions and variables. Everything else is left as an exercise to the programmer. It's hard to imagine a simpler, more conceptually straight-forward approach to it. An interface description language and component model at best makes some use cases more accessible at the expense of simplicity.
Not that I necessarily think it's unwarranted. While I appreciate the simplicity of the current approach to interop because it gives you free reign and is easy to grasp, I think anyone who has spent some time rawdogging JS-WebAssembly integration has considered inventing their own WASM IDL analog. If that can be specified as part of the standard it can also be made quicker.
> Yet, it still feels like something is missing that’s holding WebAssembly back from wider adoption on the Web.
> There are multiple reasons for this, but the core issue is that WebAssembly is a second-class language on the web
It would be nice if WebAssembly would really succeed, but I have to be honest: I gave up thinking that it ever will. Too many things are unsolved here. HTML, CSS and JavaScript were a success story. WebAssembly is not; it is a niche thing and getting out of that niche is now super-hard.
83 comments
[ 0.25 ms ] story [ 64.7 ms ] threadhttps://news.ycombinator.com/item?id=47167944
JavaScript is the right abstraction for running untrusted apps in a browser.
WebAssembly is the wrong abstraction for running untrusted apps in a browser.
Browser engines evolve independently of one another, and the same web app must be able to run in many versions of the same browser and also in different browsers. Dynamic typing is ideal for this. JavaScript has dynamic typing.
Browser engines deal in objects. Each part of the web page is an object. JavaScript is object oriented.
WebAssembly is statically typed and its most fundamental abstraction is linear memory. It's a poor fit for the web.
Sure, modern WebAssembly has GC'd objects, but that breaks WebAssembly's main feature: the ability to have native compilers target it.
I think WebAssembly is doomed to be a second-class citizen on the web indefinitely.
(there was also some more recent discussion in here: https://news.ycombinator.com/item?id=47295837)
E.g. it feels like a lot of over-engineering just to get 2x faster string marshalling, and this is only important for exactly one use case: for creating a 1:1 mapping of the DOM API to WASM. Most other web APIs are by far not as 'granular' and string heavy as the DOM.
E.g. if I mainly work with web APIs like WebGL2, WebGPU or WebAudio I seriously doubt that the component model approach will cause a 2x speedup, the time spent in the JS shim is already negligible compared to the time spent inside the API implementations, and I don't see how the component model can help with the actually serious problems (like WebGPU mapping GPU buffers into separate ArrayBuffer objects which need to be copied in and out of the WASM heap).
It would be nice to see some benchmarks for WebGL2 and WebGPU with tens-of-thousands of draw calls, I seriously doubt there will be any significant speedup.
especially now with coding agents, the DX they think they are bringing to the table is completely irrelevant.
What you don't get much is people doing standard SPA DOM manipulation apps in WASM (e.g. the TodoMVC that they benchmarked) because the slowdown is large. By fixing that performance issue you enable new usecases.
Better late than never I guess.
[1] https://github.com/WebAssembly/interface-types/commit/f8ba0d...
[2] https://wingolog.org/archives/2023/10/19/requiem-for-a-strin...
[3] https://queue.acm.org/detail.cfm?id=3746174
Apple perceives web-based applications as chipping away at their app store (which makes them money), and so they cripple their Safari browser and then force all mobile browsers on iOS to use their browser engine, no exceptions, so that developers are forced to make a native app where Apple can then charge the developers (and thus the users) for a cut of any sales made through the app.
It's one reason the DOJ started suing Apple, but I fear that may have been sidelined due to politics.
https://www.justice.gov/archives/opa/media/1344546/dl?inline
The difference in perf without glue is crazy. But not surprising at all. This is one of the things I almost always warn people about, because it's such a glaring foot gun when trying to do cool stuff with WASM.
The thing with components that might be addressed (maybe I missed it) is how we'd avoid introducing new complexity with them. Looking through the various examples of implementing them with different languages, I get a little spooked by how messy I can see this becoming. Given that these are early days and there's no clearly defined standard, I guess it's fair that things aren't tightened up yet.
The go example (https://component-model.bytecodealliance.org/language-suppor...) is kind of insane once you generate the files. For the consumer the experience should be better, but as a component developer, I'd hope the tooling and outputs were eventually far easier to reason about. And this is a happy path, without any kind of DOM glue or interaction with Web APIs. How complex will that get?
I suppose I could sum up the concern as shifting complexity rather than eliminating it.
Then there is the single array of memory that makes modern memory allocators not really work, resulting in every WASM compiler scrounging up something that mashes the assumptions of the source language into a single array.
https://github.com/WebAssembly/component-model/blob/main/des...
From the code sample, it looks like this proposal also lets you load WASM code synchronously. If so, that would address one issue I've run into when trying to replace JS code with WASM: the ability to load and run code synchronously, during page load. Currently WASM code can only be loaded async.
And now that we're getting close to have the right design principles and mitigations in place and 0-days in JS engines are getting expensive and rare... we're set on ripping it all out and replacing it with a new and even riskier execution paradigm.
I'm not mad, it's kind of beautiful.
Isnt this what an OS is supposed to do? Mobile operating systems have done a pretty good job of this compared to the desktop OS.
Browsers are millions of lines of code, the amount of UAFs, overflows, etc so far is not the bottleneck.
The 45% overhead reduction in the Dodrio experiment by skipping the JS glue is massive. But I'm curious about the memory management implications of the WebAssembly Component Model when interacting directly with Web APIs like the DOM.
If a Wasm Component bypasses JS entirely to manipulate the DOM, how does the garbage collection boundary work? Does the Component Model rely on the recently added Wasm GC proposal to keep DOM references alive, or does it still implicitly trigger the JS engine's garbage collector under the hood?
Really excited to see this standardize so we can finally treat Wasm as a true first-class citizen.
SendMessage itself is frustratingly dumb. You have excessively bit fiddly or obnoxiously slow as your options. I think for data you absolutely know you’re sending over a port there should be an arena allocator so you can do single copy sends, versus whatever we have now (3 copy? Four?). It’s enough to frustrate use of worker threads for offloading things from the event loop. It’s an IPC wall, not a WASM wall.
Instead of sending bytes you should transfer a page of memory, or several.
I'm not exactly sure how this works when binding it to GC languages.
[1] https://component-model.bytecodealliance.org/design/wit.html...
WRT WebAssembly Components though, I do wish they'd have gone with a different name, as its definition becomes cloudy when Web Components exist, which have a very different purpose. Group naming for open source is unfortunately, very hard. Everyone has different usages of words and understanding of the wider terms being used, so this kind of overlap happens often.
I'd be curious if this will get better with LLM overseers of specs, who have wider view of the overall ecosystem.
Not that I necessarily think it's unwarranted. While I appreciate the simplicity of the current approach to interop because it gives you free reign and is easy to grasp, I think anyone who has spent some time rawdogging JS-WebAssembly integration has considered inventing their own WASM IDL analog. If that can be specified as part of the standard it can also be made quicker.
> There are multiple reasons for this, but the core issue is that WebAssembly is a second-class language on the web
It would be nice if WebAssembly would really succeed, but I have to be honest: I gave up thinking that it ever will. Too many things are unsolved here. HTML, CSS and JavaScript were a success story. WebAssembly is not; it is a niche thing and getting out of that niche is now super-hard.