Remix.run Logo
no_wizard 8 hours ago

>So it got completely rolled back, sacrificed to the altar of "web compatibility."

This is why I don't understand the lack of directives.

'use strict'; at the top of a file was ubiquitous for a long time and it worked. It didn't force rolling back incompatibilities, it let you opt into a stricter parsing of JavaScript.

It would have been nice for other wide changes like this to have like a 'strict datetime'; directive which would opt you into using this corrected behavior.

They couldn't and shouldn't do this sort of thing for all changes, but for really major changes to the platform this would be an improvement.

Or they could go all in on internal modules, like how you can import `node:fs` now. They could include corrected versions of globals like

`import Date from 'browser:date';`

has corrected behavior, for example

WorldMaker 3 hours ago | parent | next [-]

To be fair, the new opt-in "use strict" here is "switch to Temporal". It's a new, stricter namespace object. Old Date code gets the old Date code quirks, new code gets the nice new Temporal API.

Internal modules would be handy in theory to maybe keep from having to dig through a thesaurus every time browsers decide to add a new, stricter version of an older API. Internal modules have even been proposed to TC-39 as a recommended way to continue to expand the JS API. Last I checked on that proposal it was stuck behind several concerns including:

1. Feature detection: detecting if Temporal available is as easy as `if ('Temporal' in globalThis) {}`, but detecting if a module import is missing is a bit harder. Right now the standard is that loading a module fails with an Error if one of its imports fails. You can work around that by doing a dynamic import inside a try/catch, but that's a lot of extra boilerplate compared to `const thingINeed = 'someApi' in globalThis ? someApi() : someApiPolyfill()`. I've seen multiple proposals on that front from extensions to import maps and `with { }` options on the import itself.

2. Bikeshedding (and lots of it): defining a URI scheme like `browser:` or `standard:` takes a bunch of thought on how you expand it. If it is just `browser:some-api` you run the risk of eventually polluting all the easy names in the exact way people worry about the risk of over-polluting `globalThis` (and in the way that it can be weirdly hard to find an available one-word name on npm), you've just moved the naming problem from one place to the other. On the other side, if you go down the road of something like `es-standard:https://tc39.es/ecma262/2025/v1/final-draft/Temporal`, even (especially) assuming users would mostly importmap that to something shorter you've recreated XMLNS URIs in a funny new hat and people who use JS all certainly have plenty of opinions on XMLNS URIs, many are very vocal in their hatred of it, but also they came out of a strong backwards incompatibility fixing desire exactly like this. (As they say time is a flat circle.)

echelon 44 minutes ago | parent [-]

> To be fair, the new opt-in "use strict" here is "switch to Temporal".

This. Don't break old code, just provide new best practices.

Update linters (or ideally first class language rules, like in Rust's "edition"s), to gradually kill off old behavior. Without having to do a decade long Python 2 -> 3 migration.

Temporal is nice. It learned from the many failures and dead bodies that came before it. And it had lots of good implementations to look at: Joda Time, Chrono, etc.

josephg 2 hours ago | parent | prev | next [-]

> It would have been nice for other wide changes like this to have like a 'strict datetime'; directive which would opt you into using this corrected behavior.

That would be ugly, because you'd want some parts of your program (eg libraries) to use the old behaviour, and other parts might want the new behaviour. How would you minify multiple modules together if they all expect different behaviour from the standard library?

In my opinion the right way to do this is to have multiple constructors (as Obj-C, swift, C and rust all do). Eg:

    let d = new Date(...) // old behaviour (not recommended for new code)
    
    let d = Date.fromISOString(...) // fixed behaviour
The big downside of this is that its tricky to keep track of which fields and functions people should really stop using in modern javascript. It'd be nice if there was a way to enable more shouty warnings during development for deprecated JS features.
hnlmorg 5 hours ago | parent | prev | next [-]

This was the approach Perl took and much as I love(d) that language, it do get pretty out of hand after a while if you wanted to adopt any newer or stricter language features.

AceJohnny2 3 hours ago | parent [-]

> it do get pretty out of hand after a while if you wanted to adopt any newer or stricter language features.

How does it get out of hand?

FWIW, I just do `use v5.32;` or similar to opt-in to everything from that version.

https://perldoc.perl.org/functions/use#use-VERSION

Of course, if you instead want to pick-and-choose features, then I can see the list growing large.

thayne 3 hours ago | parent | prev | next [-]

Maybe something like rust's editions, where you can opt into a set of breaking changes made at a certain time.

3 hours ago | parent | prev [-]
[deleted]