JS0 is a brilliantly bad idea


Whenever a new JavaScript feature rolls out, the question of “When can I actually use this?” inevitably comes up. The average user isn’t particularly concerned with updating their browser so some software engineering intern can write “efficient and optimal frontend code 🤓”. Especially in an enterprise context, where updates are often handled by an overworked and underpaid IT department, updating everyone’s browser isn’t going to be a priority when the CEO is breathing down your neck because they forgot their prassword.

To tackle this issue of feature availability and implementation cycles, the TC39 recently came out with a proposal to split up the JavaScript standardization process into two parts: JS0 and JSSugar. While JS0 is a sort of “LTS” version of JavaScript, JSSugar is supposed to be its fast-moving sibling. The idea behind this is that developers, who are typically using a build system anyway, can just “babel” their JSSugar into JS0 and thus get all the shiny new language features faster.

I think this proposal is too cagey in its messaging and ultimately a bit misguided. It doesn’t eliminate the problem, it just postpones it, without taking the broader JS ecosystem into account. Inspired by the proposal, I have created my own little “counterproposal,” described here.

Don’t get me wrong, splitting the language into JS0 and JSSugar is an interesting idea. But the proposal is so vague about what exactly will be part of JS0 versus JSSugar that it’s hard to imagine it solving more problems than it creates.

It also feels like the whole thing is trying to split JavaScript into two versions: one that people actually use, and another that’s more of an intermediate representation. The problem is, we already have an intermediate language for the web: it’s called WASM.

WASM as a first-class citizen

Instead of trying to create a new intermediate language for the web, why not stick with the one we already have? And I’m not talking about the bolted on “feature” of a WASM runtime we have now. I’m talking about proper, first-class WASM integration. This would let us use languages with the features we actually want and that make sense in their own language context (yes, I’m looking at you, JS classes).

Want a match statement? Rust works in the browser.

Looking for a good functional language? GHC has a WASM backend.

Need a pipe operator? Maybe just write better code instead (but if you’re set on it, F# compiles to WASM too).

If you would want to use those languages now, you’d have to mess around with bindings, set up WASM contexts, deal with buffers to pass data back and forth, and write a ton of tedious boilerplate code. Imagine a world where you just drop your binary into a script tag, and everything ✨just works✨!

<script src="index.wasm" type="application/wasm"></script>
<button id="button"></button>
fn web_main() -> anyhow::Result<()> {
    let el = document::get_element_by_id("button")?;
    el.on_click(|_| {
        window::alert("Hello, world!");
        Ok(())
    });
    Ok(())
}

Isn’t that nicer than writing all that WebAssembly.instantiateStreaming(fetch(....)) crap? You can still keep the old APIs and instantiate WASM code the old fashioned way, but now people could build entire websites without ever touching a single line of JavaScript.

Feature freeze JS (in the browser)

In my opinion, the direction we should be heading towards is a feature freeze of JS in the browser. Call it JS legacy or JS0 - I don’t care; just stop piling on features. The JS spec could still evolve and you could write “modern” JavaScript in Node, Bun, Deno, or <insert-hot-new-js-runtime> and have the latest and greatest JS features - just keep the browser landscape out of it.


But what about feature parity??

You already don’t have feature parity! If you don’t believe me, ask anyone still targeting IE 11. There never really was feature parity between browser JS and server-side JS. That’s the entire reason Babel exists: “Use next generation JavaScript today”.

If you really want to have next-gen JS features in a legacy JS browser ecosystem, Babel is still alive and well.


But I need <insert-dumb-feature-request-here> in the browser!!

Do you really? Like you needed classes in JS, or you needed yet another comparison operator, or you needed try/catch…you get the idea. More often than not, these features try to keep an already comatose language alive artificially while grappling with the monster of a language that the same people asking for these features created. You don’t need another language feature, you need therapy.


But frontend development will be much harder/much less accessible!!

Skill issue. Or in other words: frontend development was never easy, and efforts to simplify it have only made it more complicated. It’s already inaccessible because you have to learn ten frameworks and write a hundred config files just to get started. My counterproposal also aims to make web development more accessible by keeping language features in the browser to a minimum until you really need them. Most people already use build tools anyway; those who don’t probably don’t need the added complexity of new language features. And if their project ends up being more complex than expected, they’ll likely have to bring in different libraries, making the need for a build tool inevitable.

Conclusion

The point of my proposal is to enable people to use the right tool for the job - in this case the right language. This way we can finally eliminate the need for a “common denominator” language that is already overloaded with features, rather than just piling more on top.

I think the JS0 proposal isn’t a terrible idea. However, I believe it’s ultimately a bit misguided and far too vague about what it actually needs to achieve. JavaScript needs to be, slowly but surely, deprecated. While it wasn’t a bad language at its inception, it has turned into a frankensteined mess that it was never intended to be. At the end of the day, the web should be considered as one language use case, and JavaScript should ideally not be a DSL.


LinkedIn
GitHub