Hacker News new | past | comments | ask | show | jobs | submit login

These "what ifs" are kinda funny because the origins of JSX can be traced back to Facebook's XHP[1], which took explicit inspiration from E4X[2], an early JS standard that looked and behaved similar to the library described here.

[1] https://engineering.fb.com/2010/02/09/developer-tools/xhp-a-...

[2] https://en.m.wikipedia.org/wiki/ECMAScript_for_XML




E4X had the unfortunate downside of returning actual DOM instances, which needed to be updated imperatively. That's why JSX eclipsed it, and there hasn't been a serious proposal for HTML templating in JS since then.

But maybe we can revive the general idea with a modern take: https://github.com/WICG/webcomponents/issues/1069


> had the unfortunate downside of returning actual DOM instances, which needed to be updated imperatively.

Isn't this what we have in TFA?


Yes, for elements. The project here also supports a notion of components, though, which E4X didn't contemplate.


There are separate proposals from web components that get rid of imperative updates. https://eisenbergeffect.medium.com/the-future-of-native-html...


Also E4X was only ever implemented in Firefox, never really got traction even in Firefox.

But even considering the single implementation problem, it also was just not a good language model, nor was it well specified or defined and it brought with it a pile of weird baggage and complexity.

Then because it was The Future there was no real thought into proper interop with JS (it was essentially a completely independent spec so adopted general syntax but specified in a way that meant JS could not simply adopt that syntax).


> E4X had the unfortunate downside of returning actual DOM instances, which needed to be updated imperatively

Firefox never shipped the optional E4X DOM APIs. I wrote a polyfill for them at the time.[1]

1. https://github.com/eligrey/e4x.js/blob/master/e4x.js


With "imperatively" you mean that the user of the templating system has to do it imperatively, and that is bad? Asking because imperative updates seem to be the way to go within the implementation, instead of creating new instances of elements every time.


> which needed to be updated imperatively

VanillaJSX seems to suffer from the same problem though.


Fun fact, E4X is the reason JavaScript has ‘for(of)’ instead of ‘for each’ (the reason we didn’t get ‘for (:)’ is even dumber - it would conflict with ‘:type’ annotations a few TC39 members were convinced would magically be in the language)


Like the type annotations that are now in TypeScript?


Yup, that were in typescript, pascal (and rust, etc when they came out).

But there was no real progress after years of them pushing this syntax, but failing to actually define a type system that was coherent, or a model that would allow it.

As a result I proposed `for (of)` largely to prevent sane enumeration from being blocked on the intransigence of two people.

It's also worth noting that for(:) enumeration would not even preclude their syntax - it's certainly not grammatically ambiguous - and most real world code in languages that support enumeration directly and support inference doesn't explicitly specify the types , so the ugliness of `for(let a:type:expression)` would have be rare anyway.

shrug

Given that ECMA literally killed E4X a few years later the blanket ban on "for each" or "foreach" (because it would be "confusing" in E4X) is arguably worth than for(:), but again shrug


There is a proposal to add them, though it does seem to be stalled.


There were proposals almost 2 decades ago. They've never gone anywhere because proponents of type specifiers don't want to do the necessary corollary: specifying the type system.

Typescript and similar can do it because they don't have to specify the type system, and can't change it in meaningful ways over time. Things in the language standard cannot be easily changed, if they can be changed at all.


> the necessary corollary: specifying the type system.

It's clearly not strictly necessary though. Python has shown that.

I mean I agree it is pretty mad to just say "you can write types but they mean whatever" but surprisingly in practice it seems to work ok.


It is necessary if you’re creating a standard.

The Python implementation can do whatever it wants because “Python” does not mean “The Python Language Specification”. It means the one specific implementation, and whatever that impl does is definitionally correct.

The ability for a language specification does to hand wave behaviour is very limited, and for JS is non existent (the only places where there is divergence between implementations is some squirrely edge cases of property and prototype chain mutation during for(in) enumeration).

So you can’t say “types mean whatever”, you have to specify what the implementation is required to do when it encounters those annotations. Even if they are not meant to have any semantic impact the lack of semantic impact must be specified: e.g the language specification would be required to state “here is the valid grammar for these annotations”, and specify that they are explicitly ignored and must not be evaluated or examined in any way.


> The Python implementation can do whatever it wants

No you're misunderstanding how it works in Python. This isn't like Rust where "the implementation is the specification".

The Python type checking standards explicitly don't define semantics (though I think they give guidelines). The standard Python implementation - CPython - does not include a static type checker. There is no "official" implementation.

In fact there are at least 4 Python static type checkers and they are all third party projects and they do differ in interpretation of types sometimes. The most popular ones by far are Mypy and Pyright (and Pyright is the far superior option).

So it is exactly the same as what is proposed for JavaScript. It definitely sounds mad and I do agree that it would be better if they just actually specified semantics, but not bothering isn't the complete disaster you might imagine.


No I think you’re misunderstanding my point, in your defense I was unclear: in an environment like JS you cannot leave anything as “it’s up to the environment” - the js engines must be 100% consistent which means the exact semantics of the syntax must be specified. E.g if you were to say add an optional type suffix to the language, say:

    OptionalType := (‘:’ <Expression>)?
You have to specify what that means.

Does the expression get evaluated? E.g

    let x : Foo.Bar = …;
Does this resolve Foo or subsequent property access of Bar.

Is the expression unrestricted? E.g could it be (a=>a)()

If you want something to be invoked at runtime you have to specify how and when that occurs (and you’re now going to have to specify what is being passed).

You have to specify when evaluation or calls happen, etc.

The problem for an environment like JS is you cannot add a language feature and not specify the exact behaviour.

E.g it’s not “you must define a type system” (though for the parties involved in pushing this when I was involved it would have been), it’s that even if you aren’t actually interested in defining a type system you have to do a lot of design and specification work because there cannot be ambiguity or gaps where different engines will disagree on what is valid, or will disagree on what portions result in any evaluation, or what semantic effects occur. The specification also needs to handle other things that don’t matter in the Python use cases: what happens if I do have a library that does type checking, but then my code is included in an environment that also does type checking but does it differently.

In Python it’s acceptable to say “don’t do that”, but in JS that’s not sufficient, the implementations need to agree on the result, so the result needs to be specified, and ideally the specification would need to provide semantics that simply support that.

Note that none of this is unsolvable, it’s just a lot of work, and not defining the type system doesn’t remove that specification work.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: