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.)
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
I worked on the original interface-types proposal a little bit before it became the component model. Two goals that were added were:
1. Support non-Web API's
2. Support limited cross language interop
WebIDL is the union of JS and Web API's, and while expressive, has many concepts that conflict with those goals. Component interfaces take more of an intersection approach that isn't as expressive, but is much more portable.I personally have always cared about DOM access, but the Wasm CG has been really busy with higher priority things. Writing this post was sort of a way to say that at least some people haven't forgotten about this, and still plan on working on this.
> Two goals that were added were: 1. Support non-Web API's. 2. Support limited cross language interop.
I mean, surely it does not come to a surprise to anyone that either of these is a huge deal, let alone both. It seems clear that non-Web runtimes have had a huge influence on the development priorities of WebAssembly—not inherently a bad thing but in this case it came at the expense of the actual Web.
> WebIDL is the union of JS and Web API's, and while expressive, has many concepts that conflict with those goals.
Yes, another part of the problem, unrelated to the WIT story, seems to have been the abandonment of the idea that <script> could be something other than JavaScript and that the APIs should try to accomodate that, which had endured for a good while based on pure idealism. That sure would have come useful here when other languages became relevant again.
(Now with the amputation of XSLT as the final straw, it is truly difficult to feel any sort of idealism from the browser side, even if in reality some of the developers likely retain it. Thank you for caring and persisting in this instance.)
You seem to be implying that these goals were optional, but I don’t understand how #2 cross-lang interop could ever have been optional. Isn’t running non-JS languages the entire point of WebAssembly?
Given that, do you really think goal #1 non-Web APIs really added much additional delay on top of the delay necessitated by goal #2 anyway?
> but I don’t understand how #2 cross-lang interop could ever have been optional
This problem hasn't been solved outside the web either (at least not to the satisfaction of Rust fanboys who expect that they can tunnel their high level stdlib types directly to other languages - while conveniently ignoring that other languages have completely different semantics and very little overlap with the Rust stdlib).
At the core, the component model is basically an attempt to tunnel high level types to other languages, but with a strictly Rust-centric view of the world (the selection of 'primitive types' is essentially a random collection of Rust stdlib types).
The cross-language type-mapping problem is where every interop approach eventually runs aground. The component model's challenge is the same one that hit every bridge technology before it: whose type system is "canonical"?
.NET's Common Type System was supposed to be the neutral ground for dozens of languages. In practice, it had strong C# biases — try using unsigned integers from VB or F#'s discriminated unions from C#. The CLR "primitive types" were just as much a random collection as the WIT primitives are being described here.
The practical lesson from two decades of cross-runtime integration: stop trying to tunnel high-level types. The approaches that survive in production define a minimal shared surface (essentially: scalars, byte buffers, and handles) and let each side do its own marshaling. It's less elegant but it doesn't break every time one side's stdlib evolves.
WASM's linear memory model actually gets this right at the low level — the problem is everyone wants the convenience layer on top, and that's where the type-system politics start.
Technology with "web" in the name, invented by Web fanboys, not really much good for working with key web API's like the DOM.
Cool parts of the webassembly technology aside - this should be no surprise to anybody. News at 11.
The non-sequitur in the title of this post should be enough to give everybody pause.
Waiting for someone to chime in and tell me that the "web" in "webassembly" wasn't meant to refer to the "world wide web". Go on. I dare you!
The web part is the security model and the tradeoffs between security and performance. PNaCL was in browsers but not "web" for this reason.
Like the assembly part means low-level and meant as a compilation target, not CPU instructions.
So websssembly is an assembly language for the web, like webgl is opengl for the web and webgpu are gpu APIs for the web. And behold none of those can access DOM APIs
> So webassembly is an assembly language for the web.
But is isn't, at most WAT is (the WASM text format). WASM itself is a bytecode format. Nobody calls CPU machine code 'assembly' (nitpicking, I know, but the 'web' part of the name makes a lot more sense than the 'assembly' part).
At least the 'web' part makes more sense than the 'assembly' part ;)
WASM was designed as a successor to asm.js, and asm.js was purely a web thing. While non-web-platforms were considered as a potential use case (in the sense of "using WASM outside the web should be possible", it wasn't clear at the time what the successful usages outside browsers would even look like).
Web assembly has never had anything to do with the web.
At least that's been my experience whenever I find it in production.
This is retconning the history of WASM. While WASM was designed to be also be usable outside browsers, nobody could really predict at the time what this usage would look like exactly.
It definitly had to do everything with Web, it was the agreement between Mozila going with asm.js, Chrome pushing for PNaCL, Adobe with CrossBridge, Sun with Java, Microsoft with ActiveX,....
Then some folks rediscovered UNCOL from 1958, all the systems influenced by it, and started to sell the dream of the bytecode that was going to save the world.
[dead]
I really want stringref to make a comeback.
My god yes.
I'm building a new Wasm GC-based language and I'm trying to make as small as binaries as possible to target use cases like a module-per-UI-component, and strings are the biggest hinderance to that. Both for the code size and the slow JS interop.
Yeah it's really frustrating and JS string builtins are not a good fit for me as I do not want to deal with 16-bit code units.
Who killed stringref and why?
It couldn't get past a vote in the Wasm community group to advance from phase 1 to phase 2.
Here's a quote from the "requiem for stringref" article mentioned above:
> 1. WebAssembly is an instruction set, like AArch64 or x86. Strings are too high-level, and should be built on top, for example with (array i8).
> 2. The requirement to support fast WTF-16 code unit access will mean that we are effectively standardizing JavaScript strings.
Can you use WTF-16 for strings in your language?
The lack of DOM access IS a non issue. Nobody who uses webassembly wants anything to do with the web. The web is a pile of garbage.
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.
https://www.justice.gov/archives/opa/media/1344546/dl?inline
This is a nice conspiracy theory but doesn't match facts like Safari implementing the WebGPU standard at a faster pace than Firefox. Safari might not be great in some areas, but their WASM/WebGPU/WebAudio support is in pretty good shape.
Push Notifications, Web Bluetooth, Web NFC, User Idle Detection, the list goes on and on. Not even counting the hundreds of #wontfix bugs in their css engine. Its not a conspiracy theory if you recognize their incentives and consistent anti-consumer behavior for fucking decades.
I for one am thankful to them for it. I think we need a return to the real native. The JS/Web-slop has gone too far.
I personally hate that I need to download app from every company for every service they offer. On the other hand I love tje simplicity of opening webpage, do what I want to do there and forget it. Probably 80% of app in my phone are used very rarely, often just once yet they still sit there, getting updates, requesting permissions and sometimes eating battery... good web app can do everything native app can.
> good web app can do everything native app can.
I could not disagree more
[dead]
But the app-slop is totally fine right? Apple controlling every piece of software on my phone hasn't gone too far? Empowering the web to compete with Apple and Google's native locked down options is the only viable alternative I see.
Problem, as I see it, is that these "native locked down options" are very often just webpages in disguise, which is also webslop imo
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.
I agree that a lot of the tooling is still early days. There has also been a lot of churn as the wasm component spec has changed. We personally have a goal that in most cases web developers won't need to write WIT and can just use Web API's as if they were a library. But it's early days.
I am excited by the prospect of booting Wasm binaries without any JS glue, but when I've looked at the documentation for the component model and WIT it says that resources are references passed using a borrow checking model. That would be a serious downgrade compared to the GC-managed reference passing I can do today with Wasm GC. Do you know if there are any plans to resolve this mismatch?
What do you mean by churn in this context?
The tooling has been in it's early days for a long time. As quickly as that can improve, so will the uptake. The technology itself is quite capable.
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.
I love WebAssembly components and that's great progress. But I feel like everyone is missing a golden opportunity here to take apart the giant OS-sized web API and break some of it out into smaller standard or subscribable subsets that also don't try to mix information presentation and applications in a forced way.
Example subsets:
- (mainly textual) information sharing
- media sharing
- application sharing with, small standard interface like WASI 2 or better yet including some graphics
- complex application sharing with networking
Smaller subsets of the giant web API would make for a better security situation and most importantly make it feasible for small groups to build out "browser" alternatives for information sharing, media or application sharing.
This is likely to not be pursued though because the extreme size of the web API (and CSS etc.) is one of the main things that protects browser monopolies.
Even further, create a standard webassembly registry and maybe allow people to easily combine components without necessarily implementing full subsets.
Do webassembly components track all of their dependencies? Will they assume some giant monolithic API like the DOM will be available?
What you're doing is essentially creating a distributed operating system definition (which is what the web essentially is). It can be designed in such a way that people can create clients for it without implementing massive APIs themselves.
Yeah, the web API layer stack is essentially inverted, and important parts are missing entirely. Ideally there would be a 3D API at the bottom, on top of that a text-and-font API (e.g. allow to render high quality text into a 3D-API surface without bringing your own text renderer), to the side a vector/shape rendering API as the base for SVG, and a layouting/compositing API, the DOM should only be implemented on top that.
The chance for that ever materializing is most like zero though.
iirc webassembly components need to explicitly import anything they use, so it should be transparent which dependencies something has by just grepping its WIT for `import`
I wonder what a 'mixed model' would look like (e.g. is it even possible), e.g. an application which wants to call into component model APIs, but at the same time also needs to call into JS code which then accesses the same APIs. This hybrid model will definitely be needed for any non-trivial web application.
you can just expose javascript functionality as a component, if need be
This was supposed to happen already in the 2000s. JVM in everywhere, especially in the browser. There was Java rings you could wear, Java Card VM (JCVM), Squawk VM, Java ME.
"Java the language is almost irrelevant. It's the design of the Java Virtual Machine. And I've seen compilers for ML, compilers for Scheme, compilers for Ada, and they all work. Not many people use them, but it doesn't matter: they all work." --James Gosling
Then Microsoft happened. MS realized that "Write Once, Run Anywhere" kills their OS monopoly, so they polluted Java with brilliant Embrace, Extend, Extinguish strategy (Sun vs. Microsoft revealed the emails where the stated goal was "Kill cross-platform Java" by growing the "polluted" Java market.):
Embrace: Microsoft licensed Java from Sun Microsystems and built the MSJVM. It was the fastest JVM for some time.
Extend: They created a programmer tool for Java with proprietary Windows-specific "extensions" and also removed standard features like RMI and JNI.
Extinguish: Developers using MS tools (90% of devlopers at the time) produced "Write Once, Run Only on Windows" software and killed it and pivoted to C# and .NET
Java failed because of its security model - trying to run trusted and untrusted code in the same VM without a hard boundary - a given call is trusted if every call stack entry at the time of the call is in a trusted class. There were too many confused deputies - if you can set up a trusted object to make a call that requires trust later on without your involvement, then you have privilege escalation.
The solution was to sandbox the whole VM but this breaks all the existing code designed for partial sandboxing (e.g. most of the standard library). WASM uses this approach from the start.
Again: Microsoft. Microsoft actually promoted their own version of "fine-grained permissions" before Sun released JDK 1.2 just to make it incompatible. Customers did not care abut security. Microsoft provided shortcut to speed. Sun already lost.
Don't be surprised if Google adds something similar to Chrome for WASM.
Which is very much Google's approach to Android. AOSP could be targeted directly by devs, but Google pushes everyone to use Google services in their apps (and assume it's available on any android device) which means Android with Google services is the only viable version of Android out there.
Google and Apple both.
Most "apps" in phones could be just something you install trough browser and cache in a sandbox if we developed good standards.
JVM bytecode didn't have support for C and required GC. Even in the early days it was a lot heavier than Wasm.
JCVM did not require GC. It was designed to run on extremely resource-constrained devices-think 16-bit or 32-bit microcontrollers with only a few kilobytes of RAM. Java Card 2.2 and 3.x specifications added optional GC.
The phrase "first-class" matters here because most developers do not reject a platform over peak performance, they reject it over friction. If the happy path still requires language-specific glue, generated shims, and a mental model of two runtimes, then WebAssembly remains something you reach for only when the pain is already extreme.
What would really change perception is not just better benchmarks, but making the boring path easy: compile with the normal toolchain, import a Web API naturally, and not have to become a part-time binding engineer to build an ordinary web app.
Not only are they a decade late while everyone expected WASM to liberate us from JS, and it ended up being a useless toy in JS whose improvements would have been crushed by having to send all progress to JS to apply it, but then giving it access to DOM is also something you'll realize wasn't enough a decade later. Flutter doesn't need DOM; it has all of its own engine. The browser should give the whole viewpoint to the WASM so that apps can directly implement their own GUIs. And then there will be an app revolution. You can directly port your GUI to the web and have it work. No more your GUI as a WASM worker that has to have its frames painted by JS on a canvas; direct painting. You could have wxWidgets, GTK, Flutter, ... all working insanely fast, insanely beautiful. And then people can do amazing things. Imagine a web alternative that is powered by maestro Knuth's TeX; imagine operating systems as web pages, imagine alternative layout systems that do not have to rely on Web events and frame timing. That is all if the browser allows for WASM to bypass the web part and do it itself.
And it would be 100% inaccessible.
You can't pin requirements on other people who don't have them. If someone doesn't have a requirement to make an accessible product, it's unlikely to be accessible.
If you’d like to get acquainted with modern WebAssembly, check out the component model book:
https://component-model.bytecodealliance.org/
It includes high level concepts, practical code samples and more that introduce the really powerful parts of WebAssembly.
With regards to the JS ecosystem specifically there are 3 projects to know:
https://github.com/bytecodealliance/StarlingMonkey
https://github.com/bytecodealliance/ComponentizeJS
https://github.com/bytecodealliance/jco
The most mature tool chain right now is Rust, but there is good support for most things with LLVM underneath (C/C++ via clang). Golang, python and support for other languages is getting better and better (tinygo and big go) and there’s even more to come.
One of the goals of WebAssembly is to melt right into your local $TOOLCHAIN as a compilation target, and we are getting closer every week.
Hello COM, CORBA, RMI, Jini, .NET Remoting, Tcl Agents,..., that is basically what it is.
Very reductive :) there are flavors and hints of all these previous technologies /paradigms in WebAssembly + Component Model today, because only fools would attempt to build something without considering relevant prior art.
Won't bother trying going through differences/how-this-is-not-that but I'll say this: This time, it's slightly better, just like every time before.
I'd even go so far as to say this iteration is much better than what came before, and the speed of adoption by multiple language toolchains, platforms, operating systems, browsers proves that.
So far I haven't seen that on the existing tooling, nothing that would make me say it is much better, rather it looks much worse given the developer experience.
Zero IDE integration, no right mouse click to generate or consume interfaces/stubs, no debugging tools, no integration with existing toolchains like those alternatives, no wire debugging,....
It feels designed for those that never left the command line, vim and emacs kind of world.
I think we probably disagree on the most important parts of the tooling. I’m a lot more focused on what it lets me do/whether the abstractions are right.
That said, people have worked on IDE integration (it’s not zero, ex. WIT syntax highlighting), there is existing integration with upstream language tool chains, but trying to debate that seems silly. Whether tech is good or worth exploring is not dictated by IDE support, I think!
There has been substantial work on improving debugging, DX and documentation! Hopefully in the LLM age the existing can move even faster
Why would "right mouse click" be part of a protocol?
Tooling, for adoption.
Get your blatant component model propaganda outta here ;)
(to elaborate: WASM works just fine without the component model, it's not "the future of WebAssembly", just an option built on top of it, and of questionable value tbh)
You're replying to a comment on an article about how WASM does not work fine in the browser
The entire article boils down to one specific problem: string marshalling overhead can be optimized to be about 2x faster. Integrating the component model into browsers is overkill for that (and everything else belongs into the toolchains without touching the browser guts).
> The entire article boils down to one specific problem: string marshalling overhead
No, I don't think so at all. 80% of the article is about other problems (JS bindings are complicated to generate and a leaky abstraction, additional tools beyond the compiler are required, compiler authors don't want to deal with them, they increase the friction for getting started, they're hard to debug, ...)
...all those problems should be fixed in the toolchains, not in the browser.
Emscripten exists, DWARF debugging support exists and works (I can step from C/C++ code into JS code and back with the WASM DWARF debugging extension for VSCode), other language ecosystems just need to catch up.
> Get your blatant component model propaganda outta here ;)
It's perfectly good content, sir!
> (to elaborate: WASM works just fine without the component model, it's not "the future of WebAssembly", just an option built on top of it, and of questionable value tbh)
WebAssembly absolutely works fine without the component model, and I'd argue it's much better with the component model.
Here's my simple pitch.
world before component model:
> be me
> build a webassembly core module
> give it to someone
> they ask what imports it needs
> they ask how to run it
> they ask how to provide high level types to it
world after component model: > be me
> write an IDL (WIT[0]) interface which specifies what the component should do
> write the webassembly component
WebAssembly gives us an incredible tool -- a new compilation target that is secure, performant and extensible. We could crudely liken this to RISCV. In $CURRENT_YEAR it doesn't make sense to stop at the RISCV layer and then let everyone create their own standards and chaos in 50 directions on what the 1/2/3 step higher abstractions should be.Emscripten carried the torch (and still does great work of course) in building this layer that people could build on top of, but it didn't go far enough. Tools like wasm_bindgen in Rust work great but lack cross-platform usage.
The Component Model is absolutely the future of WebAssembly. Maybe not the future of WebAssembly core, but if you want to be productive and do increasingly interesting things with WebAssembly, the Component Model is the standards-backed, community-driven, cross-platform, ambitious way to do things with WebAssembly.
To be incredibly blunt, the failure of other attempts to centralize community, effort, and bring people along to build a shared thing that is just low cost enough that everyone can build on top is impressive. Nothing against other efforts, but I just can't find any similar efforts that others have standardized on in any meaningful way.
We're talking about a (partially already here) world where every popular programming language just outputs to WebAssembly natively and computers on every popular architecture/platform have an easy time running those binaries and libraries? If that's not the future, paint me a different one/show me movement in that direction -- genuinely would love to see what I'm missing!
And in all of this, the Component Model is optional -- if you don't like it, don't use it. If WebAssembly core works for you, you are absolutely free to build! wasm32-unknown-unknown is right there, waiting for you to target it (in Rust at least).
It's still not a great idea IMHO ;)
(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.
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.
IMHO the bang-for-the-buck proportion isn't right. The core problem is slow string marshalling in the JS shim (because it needs to create a JS string object from an ArrayBuffer slice - where the array buffer is the WASM heap).
Integrating the component model into browsers just for faster string marshalling is 'using cannons to shoot sparrows' as the German saying goes.
If there would be a general fast-path for creating short-lived string objects from ArrayBuffer slices, the entire web ecosystem would benefit, not just WASM code.
I agree there are some cases that won't see a huge boost, but also DOM performance is a big deal and bottleneck for a lot of applications.
And besides performance, I think there are developer experience improvements we could get with native wasm component support (problems 1-3). TBH, I think developer experience is one of the most important things to improve for wasm right now. It's just so hard to get started or integrate with existing code. Once you've learned the tricks, you're fine. But we really shouldn't be requiring everyone to become an expert to benefit from wasm.
> DOM performance is a big deal and bottleneck for a lot of applications
What are examples of such applications? Honest question - I'm curious to learn more about issues such applications have in production.
> But we really shouldn't be requiring everyone to become an expert to benefit from wasm.
If the toolchain does it for them, they don't need to be experts, no more than people need to be DWARF experts to debug native applications.
I agree tools could be a lot better here! But as I think you know, my position is that we can move faster and get better results on the tools side.
> What are examples of such applications? Honest question - I'm curious to learn more about issues such applications have in production.
any application you use today that is written in JavaScript rendering to the DOM, is much harder to write in not-JavaScript
Slack, Teams, Outlook, Word, OpenAI, Anthropic, Github, Twitter, Instagram (web), Notion, Google Docs, ...
Sorry, I'll ask my question in a better way: what applications written in wasm that exist today would benefit from this?
Now, maybe there aren't many because of performance - maybe they haven't used wasm because it was too slow. But I would appreciate seeing data on that - an application that tried wasm and gave up after seeing the overhead, at the least. But I would also expect to see apps that use wasm even despite some DOM overhead, because of the speedup on non-DOM code - and I'd like to see data on how much DOM overhead they are currently suffering.
I am asking because I'm familiar with a lot of apps ported to wasm, and they don't do this. That may just be because I am seeing one particular slice of the ecosystem! So I am very curious to learn about other parts.
[dead]
The onboarding cliff is real. I've pointed experienced JS devs at wasm-bindgen docs and watched their eyes glaze over before they've even gotten to the actual interesting part. Most end up cargo-culting a template they found and never really understand what the glue is doing.
Hopefully native component support makes that "aha, I get it now" moment happen earlier.
> just to get 2x faster string marshalling
That is a useful benefit, not the only benefit. I think the biggest benefit is not needing glue, which means languages don't need to agree on any common set of JS glue, they can just directly talk DOM.
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.
With Google now pushing developer certification, Android and iOS practically being mandatory for certain basic functions like accessing your bank or certain government services, Webassembly would make web apps first class citizens that aren't subject to mobile operating system lockdown.
Being able to complete on efficiency with native apps is an incredible example of purposeful vision driving a significant standard, exactly the kind of thing I want for the future of the web and an example of why we need more stewards like Mozilla.
FWIW my home computer emulators [1] already run at about the same performance (give or take 5..10% depending on CPU type) in WASM versus their natively compiled counterparts.
Performance is already as good as it gets for "raw" WASM, the proposed component model integration will only help when trying to use the DOM API from WASM. But I think there must be less complex solutions to accelerate this specific use case.
How does WASM solve the platform lockdown problem? That WASM will run in a third-party app that is subject to those restrictions. The system interface exposed within that runtime is still going to be limited in the same way a native app can't get real access to the filesystem, etc.
Removing JS glue doesn't enable anything you couldn't do before. Those banks and governments still need to write the web apps, and they need to uncheck the security box which requires a hardware-attested environment.
Except that the Web is basically ChromeOS Platform nowadays, thanks to all those folks targeting only Chrome, complaining about Safari, and shipping Elecron crap.
If it "only" speeds up DOM access, that's massive in itself. DOM is obviously a crucial element when running inside a browser.
agreed. no one needs the component model, and it's just a attempt for people to create work for themselves.
especially now with coding agents, the DX they think they are bringing to the table is completely irrelevant.
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.
webassembly components use a borrow checking model[1], so I assume that would be used to manage DOM components?
I'm not exactly sure how this works when binding it to GC languages.
[1] https://component-model.bytecodealliance.org/design/wit.html...
Proving the point of how it is dominated by Rust folks.
Maybe they should have spent some time wondering how previous component models work, e.g. COM, CORBA, RMI, .NET Remoting,....
This is my main confusion, too! I have an existing Wasm GC language implementation and I'm not sure how to reconcile it with the component model.
I would think you could treat it as a normal GC reference and then just drop the resource when the GC collects the object.
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.
Your comment - and your last two comments too - all sound very LLM-written. Using an LLM for commenting is explicitly against the site rules (https://news.ycombinator.com/newsguidelines.html#generated).
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.
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.
I'm not mad, it's kind of beautiful.
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.
What makes WASM execution riskier than JS?
Novelty - JS has had more time and effort spent in hardening it, across the browsers, WASM isn't as thoroughly battle-tested, so there will be novel attacks and exploits.
That would be more true if WebAssembly didn't share so much sandboxing infrastructure with JS. If anything, I'd argue that WebAssembly is a much smaller surface area than JavaScript, and I think that will still be true even when DOM is directly exposed to WebAssemly.
I don't think it's "much smaller" once you aim for feature parity (DOM). It might be more regular than an implementation of a higher-level language, but we're not getting rid of JS.
By the same token, was Java or Flash more dangerous than JS? On paper, no - all the same, just three virtual machines. But having all three in a browser made things fun back in the early 2000s.
It is much smaller.
WASM today has no access to anything that isn't given to it from JS. That means that the only possible places to exploit are bugs in the JIT, something that exists as well for JavaScript.
Even WASM gets bindings to the DOM, it's surface area is still smaller as Javascript has access to a bunch more APIs that aren't the DOM. For example, WebUSB.
And even if WASM gets feature parity with Javascript, it will only be as dangerous as Javascript itself. The main actual risk for WASM would be the host language having memory safety bugs (such as C++).
So why was Java and Flash dangerous in the browser (and activex, NaCL).
The answer is quite simple. Those VMs had dangerous components in them. Both Java and Flash had the ability to reach out and scribble on a random dll in the operating system or to upload a random file from the user folder. Java relied HEAVILY on the security manager stopping you from doing that, IDK what flash used. Javascript has no such capability (well, at least it didn't when flash and Java were in the browser, IDK about now). For Java, you were running in a full JVM which means a single exploit gave you the power to do whatever the JVM was capable of doing. For Javascript, an exploit on Javascript still bound you to the javascript sandbox. That mostly meant that you might expose information for the current webpage.
I think even when WebAssembly has access to every API that JavaScript does, it's still architected in a way that I think is less likely to lead to sandbox escapes. The thing doing the sandboxing doesn't have the full complexity of a programming language; some of that complexity lives either in the compiler or inside the sandbox. Some things that would be vulnerabilities in JavaScript become "it rather involved being on the other side of this airtight hatchway" problems in WebAssembly.
There is very significant overlap between browsers’ implementation of JS and WASM. For example in V8, the TurboFan compiler works for both JS and WASM. Compilation aside, all the sandboxing work done on JS apply to WASM too. This isn’t NaCl.
> Novelty - JS has had more time and effort spent in hardening it
Taking this argument to its extreme, does this mean that introducing new technology always decreases technology? Because even if the technology would be more secure, just the fact that it's new makes it less secure in your mind, so then the only favorable move is to never adopt anything new?
Supposedly you have to be aware of some inherent weakness in WASM to feel like it isn't worth introducing, otherwise shouldn't we try to adopt more safe and secure technologies?
To be fair I think this could be true for certain industries/applications. And while I obviously don't agree with the extreme example, any new technology, especially if it brings a new paradigm has more unknown unknowns which carries potential voulnerabilities.
> Taking this argument to its extreme, does this mean that introducing new technology always decreases technology?
I assume you mean "decreases security" by context. And in that case - purely from a security standpoint - generally speaking the answer is yes. This is why security can often be a PITA when you're trying to adopt new things and innovate, meanwhile by default security wants things that have been demonstrated to work well. It's a known catch-22.
> JS has had more time and effort spent in hardening it
JS required the time and effort because it's a clown-car nightmare of a design from top to bottom. How many person-hours and CPU cycles were spent on papering over and fixing things that never should have existed in the first place?
This doesn't even count as a sunk cost fallacy, because the cost is still being paid by everyone who can't even get upgraded to the current "better" version of everything.
The sooner JavaScript falls out of favor the better.
On one hand, yes, new attack surface is new attack surface. But WASM has been in browsers for almost a decade now.
Without the bindings this talks about, so it really couldn't do nearly as much.
WASM has access to everything JS has via JS in the same sandbox that JS runs in.
JS didn't magically become more "secure". Multiple things happened:
- ActiveX and Flash got booted from browsers
- Browsers got much better sandboxes
Essentially limited what untrusted code can run and sandboxed that untrusted code. Before NaCl and PNaCl it was wild west in browsers.
The same sandbox runs WASM. It even goes through the same runtime in every browser. It's no different from compiling language of your choice to subset of JavaScript (see asm.js).
>20 years of serious browser security bugs caused chiefly by JavaScript
I think you may be confusing Javascript the language, with browser APIs. Javascript itself is not insecure and hasn't been for a very long time, it's typically the things it interfaces with that cause the security holes. Quite a lot of people still seem to confuse Javascript with the rest of the stuff around it, like DOM, browser APIs, etc.
That’s not entirely true. Security issues in the JIT of V8 are found every now and then. See https://v8.dev/blog/sandbox
Javascript isn't more insecure than any other language. Any language can have the same or other security issues.
Reality is a bit more nuanced that that. Some languages are easier to interpret and optimize than others, leading to less error-prone interpreter/compiler code. JS is definitely on the “harder to optimize” side of the spectrum, leading to very complex code with a higher chance of subtle errors.
V8 does some crazy stuff that makes JS one of the fastest interpreted language there is. But had JS been designed differently (Dart was an attempt at fixing some of those mistakes), it’s likely there would be less security vulnerabilities in its interpreter.
Yeah, but you're not normally going to random websites, downloading an exe and running it. But every website you visit can run JS on your computer (as long as you don't disable JS). So maybe JS should be more secure than any other language.
> Yeah, but you're not normally going to random websites, downloading an exe and running it.
Most or many of secure mobile operating system zero days are caused by image parsing. There is a threat at least as big, if not bigger, in parsing complex file formats.
Sure gopher or gemini would be more secure, but even without JS the web ecosystem would be venerable.
>So maybe JS should be more secure than any other language.
And it probably is. The sandboxing and security have been around a very long time.
If Python were the de-facto browser language, people would also blame it for "security problems", and would be just as paranoid about python running when they visit a website. I know whatever language it would be, people would still be paranoid.
I personally don't see any problem with Javascript. If someone knows how to use it, it can be very simple and powerful.
Before Javascript ever existed, I was wishing that websites had a scripting language. I didn't really care what it was, but Javascript answered my prayers rather nicely. But it wouldn't really matter what the language is, I'd still be coding for the web browser, and other people would be hating it for whatever reasons.
> 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.
Mobile OSes don't allow random people to run code on your device. They allow you to install software you want and sort-of trust, which is conceptually close to the desktop model. There are some safeguards on top of that, but the primary line of defense is that cheap-pillz.virus-basket.ru can't actually execute anything on your device.
Desktop model at least on Apple, Google and Microsoft platforms is slowly adopting similar security models, boiling water and frogs kind of approach.
mobile operating systems review all the code that gets installed on every device
Security does not depend on code review. They have stronger sandboxing and have granular permissions that the user must allow. My point is running untrusted code securely should be the operating systems job. It is possible to do this at the operating system level, a browser is not required. The problem is the security model for desktop operating systems is ancient and has not kept up with today's requirements.
Wasm is safer since it has a much smaller attack surface.
Nothing is being ripped out or replaced.
I only got mad when people wanted to add browser features that clearly break sandboxing like WebUSB. How does wasm break this?
It's worth it if it gets rid of JavaScript
"out of the frying pan into the fire"...
I'd like to avoid wasm too...
I feel like the bottleneck for WASM integration isn't WASM itself but rather how to interface with it.
Quite often it comes with a mandatory service worker which has to be communicated to in a specific fashion, then some specific headers need to be available server side, etc. I'm not saying it's not required but ... I imagine most Web developer are used to requiring a library, calling its function, getting the result. Until it reaches that stage then JavaScript fallbacks will be preferred until there is absolutely no alternative but the WASM binary.
PS: this might sound like such a low bar... but the alternative is giving up entirely on either, starting a container with a REST API then calling it with a client. That's very easy and convenient when you've done it once and you decouple. So maybe I'm finicky but when very popular alternatives exist I believe the tipping point won't happen unless it becomes radically easier than what exists.
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:
https://github.com/WebAssembly/component-model/blob/main/des...
The concurrency part of the C-M is complicated (I think for inherent reasons), but won't be exposed to end users. It's basically defining an API that language toolchains can use to coordinate concurrency.
For end users, they should just see their language's native concurrency primitives (if any). So if you're running Go, it'll be go routines. JS, would use promises. Rust, would have Futures.
Real programs, whether native JavaScript or in any other language that targets Wasm, have concurrency. Would you rather the component model exclude all concurrent programs, and fail to interact with concurrent JavaScript? The component model is meeting the web and programmers where they're at. Unless you're one of the few people implementing the low level bindings between components and guest or host languages, you don't have to ever read the CM spec or care about the minutae of how it gets implemented.
I was looking there because the high-level documentation doesn't seem detailed enough to understand how it works. Maybe some intermediate-level explanations are needed?
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)
Probably needs to be fixed by bundling runtimes for things like Go, or bringing back cross-website caching in some secure way if that's possible
That's an orthogonal problem. First it needs to be possible and straightforward to write GCed languages in the sandbox. Second, GCed languages need to be willing to fit with the web/WASM GC model, which may not exactly match their own GC and which won't use their own GC. And after that, languages with runtimes could start trying to figure out how they might reduce the overhead of having a runtime.
> Second, GCed languages need to be willing to fit with the web/WASM GC model
Suppose the Go people make a special version of Go for Wasm. What do you think are the chances of that being supported in 5 years time?
I think it'd be supported by them the moment they ship it. Whether others will be excited to use it is an open question. There's no central registry of "languages supported for WebAssembly", by design; it supports any language that can compile to standards-compliant WebAssembly.
> Second, GCed languages need to be willing to fit with the web/WASM GC model
I think most languages could pretty easily use WASM GC. The main issue comes around FFI. That's where things get nasty.
WasmGC doesn't support interior pointers, and is quite primitive in available set of operations, this is quite relevant if you care about performance, as it would be a regression in many languages, hence why it has largely been ignored, other than the runtimes that were part of the announcement.
Oh interesting.
In java land the fact that you effectively don't have pointers but rather everything is an object reference, this ends up not being an issue.
I wonder if the WASM limitation is related to the fact that JavaScript has pretty similar semantics with no real concept of a "pointer". It means to get that interior pointer, you'd need to also introduce that concept into the GC of browsers which might be a bit harder since it'd only be for WASM.
Object references are pointers. WasmGC only supports pointers which point to the start of an object. However, some languages have features which require pointers that point inside of an object while still keeping that object alive.
Limiting WASM to what is capable in JavaScript is quite a silly thing to do. But at the same time there are vastly different GC requirements between runtimes so it's a challenging issue. Interior pointers is only one issue!
> Object references are pointers
I know this is pedantic, but they aren't. At least not in the sense of what it means for something to be a pointer.
Object references are an identifier of an object and not a memory pointer. The runtime takes those object references and converts them into actual memory addresses. It has to do that because the position of the object in memory (potentially) changes every time a GC runs.
This does present it's own problems. Different runtimes make different choices around this. Go and python do not move objects in memory. As a result, it's a lot easier for them to support interior and regular pointers being actual pointers. But that also means they are slower to allocate, free, and they have memory fragmentation issues.
I'm not sure about C# (the only other language I saw with interior pointers). I think C# semi-recently switched over to a moving collector. In which case, I'm curious to know how they solved the interior pointer problem.
> I'm not sure about C# (the only other language I saw with interior pointers). I think C# semi-recently switched over to a moving collector. In which case, I'm curious to know how they solved the interior pointer problem.
Objects references are just pointers in .NET. See the JIT disassembly below. It's been using a moving GC for a long time, too.
https://sharplab.io/#v2:C4LghgzgtgNAJiA1AHwAICYCMBYAUKgZgAIM...
Interesting. I wonder how C# handles the moving. I'm guessing it has to go in and fix up the pointers in the stack after a gc run? Or is this some OS level virtual pointer weirdness going on? How does C# guard against someone doing something silly like turning a pointer into a long and then back into a pointer again later?
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...
I don't use WASM as a replacement for JS. I never have a need to manipulate DOM, etc from WASM. JS is perfectly fine and performant for those purposes.
As I see it, WASM is used to augment the JS/WebAPI ecosystem. For example, when you need to do heavy bit manipulation, complex numerical processing. The round-trip JS->WASM->JS is an overhead. So the WASM modules should perform a substantial amount of processing to offset that inefficiency.
I frequently find that V8 optimisations yield sufficient performance without needing to delve into WASM.
IMHO if you want to write WebApps in Rust, you're holding it wrong.
I disagree. That's how WASM is now, and I guess that's fine, but that's not all it could be. I really think it would be awesome if you could write code for the web in your preferred programming language.
Say goodbye to writing multiple kinds of plugins and userscripts for random websites I guess. I don't want the transition to wasm because it looks like it will make most things unchangeable binary blobs
I don't follow? when you write userscripts you modify the dom not the already running scripts usually, no?
Wouldn't there be a point where the mainstream approach is to just have compiled blobs write directly to the canvas, say a point where someone compiles a qt application and hosts it on their website.
What can you even modify there, when all the structure is flattened into a single layer
I agree with the direction, but it seems to miss the golden hour. This concept should have been on the roadmap at least several years ago. After all, in most use cases, execution speed is not the main issue with JavaScript.
I believe that the need for JavaScript glue code has significantly hindered the appeal and interest in WASM, as well as the resulting ecosystem growth.
I'd really like to be able to run _any_ language in the browser. WASM is a great first step.
Internet Explorer used to support any language that Windows Script Host could run. By default, that was JScript and VBScript, but there were third-party engines for Python, Perl, Ruby, Lua, and many others.
Possibly disabled now as they announced VBScript would be disabled in 2019.
Also Visual Basic: https://news.microsoft.com/source/1996/10/28/microsoft-intro...
That was something else entirely. Not for scripting but to write compiled ActiveX browser add-ons.
Yes, we used the plugins from ActiveState on Tcl.
This is exactly what we need!
The web doesn't work without dynamic feature detection. I couldn't find anything in the component model about how this is expected to work.
The DOM is not a static interface, it changes both across browsers based on implemention status and also based on features enabled on a per page load basis.
The multi browser ecosystem also mainly works because of polyfills.
It's not clear how to polyfill random methods on a WIT interface or how to detect at runtime which methods exist.
OTOH the JS bridge layer we use today means you can load JS side polyfills and get wasm that's portable across browsers with no modifications. There's more to the ecosystem than just performance.