Hacker News new | ask | show | jobs
by Arnavion 756 days ago
Components are basically COM / CORBA for WASM. Just like COM enabled multiple languages to exchange structs and function calls with each other, WASM components do the same.

The C ABI approach works fine but becomes complicated when you want to pass things that aren't fixed-length, because unlike the C ABI usage when linking different libraries into the same address space, the host and the module run in different address spaces. Eg if the host wants to pass a string to a module fn, it first needs to call a different "malloc" module fn to allocate some space in the module address space and return that address, then the host writes the string to that address, then calls the original fn it wanted to call with that address, then calls a third "free" function at the end to release that allocation. Does that work? Of course it does. But the component ABI abstracts over all that for you and lets you call the function with the host's string type, and the runtime on the host side and bindings on the module side handle all the thunking so that it appears on the module side as the module's string type.

TFA doesn't seem to have any arguments other than "It's too many new words for me to learn so it's unnecessary I decided." Eg:

>And don't get me started on WIT's kebab-case identifiers (function names, interface names...). Why??? How can a specification about cross-language interoperability can come with a convention that basically no programming language use?

The point of the kebab case is that it does *not* show up in the generated bindings. It's processed by the bindings generator into the appropriate casing for the language. Eg a function name `foo-bar` becomes `foo_bar` in Rust, and a type named `foo-bar` becomes `FooBar`.

2 comments

I think the argument here is that you don’t need a full N:1:M mapping of data types to make this work. Transparency is a myth. If you try it (as in Sun RPC, DCE, CORBA, COM, etc.) you end up just writing wrappers anyway as you hit some edge case that the universal type system doesn’t support. E.g., look at the clunky IDL interfaces COM had to invent to get interop with JavaScript objects because IDL had baked-in assumptions about how records work.

Since the point is to enable component-level interop, not fine-grained function interop, you can instead define a simple interchange format (more JSONish than IDLish) and write the library interfaces accordingly. More of a microservice approach than a linker approach.

Counter-point: I happen to be working at $dayjob on things related to Components (both on the host side and the module side), including using some "WIP" things like the "resource" feature (opaque handles with methods), and haven't hit any edge cases.
Sure, it’s expected that you won’t hit problems if you’re using the paradigms that existed when the IDL was defined. On the other hand, trying to apply Sun RPC after everything became object-oriented…well, that’s when we blew it up and invented CORBA. So I’m just saying the cycle is likely to continue with this approach. In other words, come back in ten years and see how it aged.

The alternative is to use something so simple it can’t become outdated. Dumb down the interface rather than making the interop omniscient. (Kind of like the dumb network principle.)

I just realized: The very fact that WASI isn’t using any of the previous N attempts at a supposedly universal IDL, but instead inventing yet another one, itself demonstrates the problem with this approach.
It's entirely reasonable for WASM to use its own IDL. Afaik Chrome already uses an IDL to describe the interaction between native C++ classes and their Javascript bindings.

Integrating WASM modules with each other, WASM with JS, and WASM with native functionality seamlessly is a huge and unsolved challenge.

Or it just points towards NIH syndrome, combined with hype and anti-hype driven mentality of programmers, and general forgetting of previous technologies. Or even when the differences are close to 0, doing a new not exactly same implementation for ... whatever reason.
Or COM's evolution, WinRT, where the .NET metadata also doesn't really map to JavaScript or C++, without some additional kludges with metadata as workaround.
Don't forget the extra fun that happens when you call free() from a different allocator than the one that allocated the memory object, though I suspect WASM's module approach might make it difficult to happen...
Yes, that won't happen here, because the host is just calling some global malloc and free exported by the module. Well, obviously the implementations of those globals can be buggy in some way, but that's the module's bad.