I was a huge MooTools fan back in the day. I literally have a t-shirt in my closet[1] and an inordinate amount of MooTools left on my personal site. Even so, I think trying not to break it is beyond silly.
It made the decision to extend prototypes. In hindsight, a huge mistake. At the time, almost nothing in JavaScript had changed in over a decade, it seemed safe, an unmoving target.
Douglas Crockford really doesn't get enough credit for the work he did getting ECMAScript into a living standard again. How soon people forget, but in the mid-aughts any mention of JavaScript was followed by a scoff.
Anyway, JavaScript shouldn't be trying specifically not to break MooTools. MooTools was trying to fix JavaScript.
> It made the decision to extend prototypes. In hindsight, a huge mistake.
I think it was a mistake at the time, but I still believe prototypal inheritance is pretty great idea. And JS desperately needs standard library, which IMO should extend built-in prototypes, so the language would be more coherent. ES1995 [0] was a funny take on this direction, but people (mainly non-JS people) would like to seriously use it. Go figure.
> here’s the kicker — if you overwrite a non-enumerable property, e.g. Array.prototype.sort = whatever, it remains non-enumerable.
One thing I never understood about this problem: Why not change the behavior so that overriding non-enumerable properties makes them enumerable? That seems to be the behavior that library developers (e.g. MooTools) were already expecting anyway.
My guess is that they don't do that because that would change behavior for developers that are intentionally overriding existing methods-- like one might do if monkey-patching a method to work around a bug, or polyfill newer functionality, or add instrumentation.
Basically, anything they could do here is a behavior change for someone. So, if they insist on not breaking things for anyone, the only option they have available (short of moving towards Windows-style app-specific compatibility workarounds) is to not change anything here, and just use a different name for the new method.
Yes. At a certain point you stop searching and move forward. Which is what many other comments are asking for without realizing the scope of what would break at the give-up point alternatives they prefer.
That's exactly what I would like to know -- what are the trade-offs involved in going with my preferred solution of changing modified non-enumerable properties to be enumerable? Every possible solution to the problem could create breakage somewhere, so what is the breakage that would be created with this solution and why is it less favourable than the solution they ended up with?
MooTools is simply setting a value to a property that did not exist before the assignment. It isn't using Object.defineProperty() to create the property. You cannot call Object.defineProperty() twice for the same property (it throws an error).
If assigning a value to a property that was previously defined as non-enumerable were to make it enumerable, then the very act of defining a property would have no value, except in the case where you are making a read-only property (ie using the "writable: false" option for Object.defineProperty).
You can specify the value as part of the options to defineProperty, and also it is legal to call defineProperty twice on the same property but with a different value.
I get the whole “don’t break the web” thing, but surely it still has to come down to how significant the websites are that you’re breaking or how ludicrous the reason for the breakage is, right? Like surely I can’t prevent any new array methods from ever existing by making a website with a list of known array prototype properties and throwing an error if any new ones show up, right? I’d like to hear more details about how these decisions are actually made.
> surely it still has to come down to how significant the websites are that you’re breaking
As determined by whom, with what criteria and what methodology?
> or how ludicrous the reason for the breakage is
This behavior in MooTools (and Prototype.js and probably others) of monkey-patching built-ins was widely considered ludicrous at the same time as they were widely used across huge chunks of the web.
A more recent example: I consider real world use of alert to be ludicrous for nearly every usage I can imagine, and I hate when I interact with its usage even for benign things, but when Google tried to remove it from Chrome I objected along with a lot of others who have no personal love for alert itself. I opposed its removal because alert has certain guarantees, and removing it would break an untold number of sites in totally unpredictable ways. There are a bunch of “why don’t you just…?”-type suggestions in other comments, but the fact is you can’t “just” substitute anything for alert without recreating all the things people hate about it.
> I’d like to hear more details about how these decisions are actually made.
They discuss some of that in the article, but if you want more detail there’s a ton of public record in the various TC39 repos on GitHub[1], including repos detailing their process as well as per-proposal repos demonstrating application of their process. If you’re particularly interested, you’re in for a lot of good reading.
At the end of the day, it comes down to whether browser vendors are willing to ship the feature even though it breaks said websites, and they do have visitor data to back those decisions. If the rule was "never break any website ever", you'd be able to block proposals you don't personally like by crafting a website that "gets broken" by that proposal.
At least in the array grouping proposal, they did evaluate amount and popularity of possibly breaking sites, before eventually renaming the method from .groupBy to .group
I wish Chrome devs did. They have been actively breaking the Web on multiple occasions. Just try to launch some unmaintained HTML5 game from a few years ago and watch it trip over a non-working audio context. They reverted their window.alert change after deploying it only because the resulting breakage was too big to ignore. "Don't break the Web" is a myth, it's actually "don't break the Web so much that the user will notice enough things stopping to work after browser update to blame it on the browser".
Frankly, I think the web should have stopped breaking itself years ago. The widespread adoption of JavaScript is a mistake fuelled by the trainwreck that we call modern app distribution. If the App Store/Play Store hadn't succeeded, there might still be a distinction between Apps and Websites.
In particular, given that Javascript predates App Stores by many years (I would hazard an unresearched guess at over a decade), and that Javascript serves myriad purposes in websites that have nothing to do with apps, this assertion requires extraordinary justification.
> Like surely I can’t prevent any new array methods from ever existing by making a website with a list of known array prototype properties and throwing an error if any new ones show up, right?
No, and that’s not what’s happening here. MooTools was very popular and is still used on many websites.
They are adding ‘flat’ even though in some obscure corner of the internet that’s going to break something.
Also, is this fixable downstream? I imagine they could have kept a kind of "mixin prototype" object sitting around, and they could enumerate the properties of that object instead of Array, and in doing so attach their custom properties to Array as well as Elements and whatever else.
It seems less flaky anyway, compared to relying on this subtle enumerability property.
They did fix it downstream. I remember maintaining a JS tool many years ago that was being embedded on client's websites, and before we added a bunch of hacks to make it not break with bad Mootools versions we did manage to convince some non-zero number of clients to fix their sites by updating it.
In fairness, one of the nicest things about early JS was the flexibility it offered. It was never meant to be a language for building large libraries and huge applications. Coming from strongly typed languages it was sort of liberating, at a certain point. Now... well, arguably it's okay that it's so loose because it's allowed things like TypeScript to spring up, but you can still just override Array if you feel like it. (Until one day you can't, hah).
They could of course fix it downstream any number of ways, many more straightforward than adding a layer of indirection to keep monkey patching the built-ins. But that wouldn’t fix sites still running the older code.
It's probably not worth engaging in these threads, since everyone now knows it was a joke, but Twitter doesn't put old things into read-only model unfortunately.
That broken version was 8 years old at the time of the bug? Screw that. I’d you’re running an 8 year old unmaintained script you have different issues.
This is a really great summary with a lot of amusing little details. A couple comments:
1. It sounds like there was confusion for a period of time because the developer made a joke. I think there really should be a specification for how to annotate humorous comments made on the web.
2. I loved the section spelling out the principle of "don't break the web." This is important, and as we get more and more legacy web the more valuable this principle becomes. That said, I wonder if a day is coming where the browser is disrupted because browser devs are moving too slowly on account of this.
i ThInK tHeRe ReAlLy ShOuLd Be A sPeCiFiCaTiOn FoR hOw To AnNoTaTe HuMoRoUs CoMmEnTs MaDe On ThE wEb.
The specification exists, it's just not enforced. If Google and Meta aren't going to step up, I think we should prosecute non-compliance with the full weight of the legal system. This is an existential threat to our society.
That's really less of a humor tag and more of a condescending sarcasm tag though. I don't see it used as a joke so much as to do an imitation of someone else speaking, repeating something they said (or might allegedly say) in such a way as to make it appear stupid.
At the same time, the reason Safari doesn't report MacOS 11 is because too many sites had poorly written detectors that threw exceptions if they didn't see Mac OS 10_???? in the UA string. Here's the userAgent on Safari
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15
Even though I'm on MacOS 12.6 on an M1 MacBookPro.
So there's at least one more example of "don't break the web'
#2 isn’t a going concern, if anything people now complain that it moves too quickly. IMO that’s a silly complaint but a steady stream of years-long processes being completed is always gonna upset someone.
Delaying the punchline until after 2. made your joke much funnier. When we write the spec for joke syntax we'll have to include this sort of... what is it, lazy-evaluation?
You joke, but it is sorely needed, because people simply don’t understand sarcasm very well on the web these days. Personally I think it should be considered a sort of disability, and having these kind of annotations should be a requirement if a website wants to be ADA compliant.
In addition, having non-joke annotations helps people identify when a person is being dead serious. Even here on hackernews, Poe’s Law reigns supreme as people struggle to differentiate parody from genuine opinions.
I'm kinda just reiterating what other people have said here, but I don't really get the "don't break the web" thing.
Apparently it was just fine to break the web when it meant shutting off Flash and breaking millions of existing games and movies - but a few old sites that could trivially be wrapped that use Mootools are somehow good enough to change "flatten" to "flat"?
Flash was never a web standard, there weren't enough independent implementations, it was proprietary only, and it had mountains of security issues. I agree with trying to not break the web, but the death of Flash on the web was great, and the only tragedy is that there's still not a great, reasonable FOSS solution for running arbitrary swf files offline.
I’m not sure I understand your logic. MooTools isn’t a web standard either. How is breaking all the websites relying on flash acceptable while breaking all the websites relying on MooTools not?
I hear you and I am nostalgic for old flash content, but replacing a method name that hasn’t shipped in a production build is an easier thing to do than maintaining an interactive multimedia plugin that was never designed to be a web standard.
Lets code dynamically change things that other code depends on. Including behavior in built-in object prototypes.
Has weird properties like "enumerable" on members of those prototypes, so that changing a property doesn't do the same thing as adding one... but the API for both is the same.
It's like the language is built to cause breaking changes. "Don't break the Web" indeed.
The root cause here is writing millions of lines of code in something that was originally just supposed to validate forms.
> Lets code dynamically change things that other code depends on. Including behavior in built-in object prototypes.
Not exactly uncommon for languages that feature reflection.
Heck the win32 api allows you to hook and intercept function calls. So do plenty of other native C and C++ APIs.
It is a powerful feature that allows for a lot of functionality, including extending out libraries and fixing bugs in SDKs that you'd otherwise have to wait an entire release cycle for, or that may never get fixed. (And release cycles used to be years long!)
I for one am quite ready to replace the bad decision of Javascript with the differently-bad decision of WASM. I would cherish never having to touch Javascript Object oddities again.
How is that any different than any language introducing a new keyword that existing code previously used as variable names? Normally this wouldn't break anything since the developer has to opt in to update the compiler/runtime. The problem is the runtime (browser) autoupdates and the developer has no way to opt out of their code running on the new runtime.
Doesn't matter which is more common. All actively developed languages eventually get new keywords and breaking changes. However, most of them will not interfere with existing code running under previously defined behaviors.
Even node 10 applications that use MooTools (i.e. JavaScript executing in a different runtime) will continue to work just fine if `flatten` is added as proposed in node 11+. The developers will eventually need to patch it but it's not like this bug where one day users autoupdate their browser and half the websites they visit are broken.
Can we please do “stricter mode” for some of this? “strict mode” was a great hack, and we are long overdue for fixing stuff
My white whale: make “let” mean what “const” means, and “var” mean what “let” currently means. But there are definitely better things to get done
I’m for keeping things working generally of course. People being against “don’t break the web” is a bit odd to me. But we are long overdue for versioning so we can actually fix stuff, especially given how much modern code goes through transpilers and the like
The trend seemed to be in the opposite direction. In the early days, you could use the language attribute of the script tag to specify a version, e.g. language="JavaScript1.2". But that failed to become a standard.
HTML used to be versioned by the DOCTYPE, but that fell out of favor with HTML5.
Apparently it was fine to rename "flatten" to "flat," because that's what they did, but it wasn't okay to rename "flatten" to "smoosh." What's the difference?
Probably that flatten has a near-universal meaning across many programming languages, and flat is so close to flatten as to have its meaning be almost implicitly clear, whereas smoosh has absolutely zero precedent and its behavior would be completely uninferrable without looking up documentation.
It actually wasn’t fine to rename flatten() to flat() - flat isn’t a verb, flatten() seems natural, and now you have to explain to everyone that yes it’s called flat() because someone on a standards committee really likes unmaintained web sites that probably have expired domains, expired certs, non paid for hosting but might run mootools.
It seems like there could be a sort of quirks mode for old JS libraries, in which browsers recognise either key functions or specific hashes and could then apply library-specific mitigations. It wouldn't solve every instance of this problem, but it would solve the mootools-using majority without needing the awkward name change.
Is it possible to poison future web API implementations by making a really popular library that would fall apart if any new Array/Object methods were added, or something like that?
Mostly, though, they just taught TC39 to have less fun and to ignore the "just break the web it's okay!" crowd.
Why TC39 operates under this never-break-the-web imperative: because if they didn't, every proposal they consider might devolve into an unresolvable discussion of "well is THIS thing important enough to break the web over? how much usage would this change break? how valuable do we think this is?". The easiest, and only, way to resolve all possible such discussions is to just not have them.
Seems weird to jump through hoops to keep an outdated JavaScript library with a custom prototype working. When you create custom prototypes this is the risk you take. Name your prototypes accordingly, so they are unlikely to clash anything. As an example mtflatten, or _flatten (like underscore.js and other libraries).
The problem with prototypical inheritance is that people will use it. And now you can’t add anything ever again without this risk.
I absolutely love the ability to monkey patch in upcoming features. But I avoid adding my own array functions. Unfortunate, IMO, because it’s a really neat trick.
Well, you can subclass it, but you would have to convert regular array to your subtype every type you would want to use some extra property. With proposed way, you can still enjoy the terseness of the language.
smoosh is a better name than flat; verbs are better for callables: they do something. Flat is an adjective; seeing Array.prototype.flat I'd assume its a boolean attribute indicating whether the array was "flat"
From the article: “As it turns out, “don’t break the Web” is the number one design principle for HTML, CSS, JavaScript…”. So window.alert() is safe for all time? More breathtaking hypocrisy from Google.
Root cause seems to be JavasScript itself. Not only is it possible for any random piece of code to add/replace implementations of bulit-in functions, but it's widely practiced and encouraged somehow.
It made the decision to extend prototypes. In hindsight, a huge mistake. At the time, almost nothing in JavaScript had changed in over a decade, it seemed safe, an unmoving target.
Douglas Crockford really doesn't get enough credit for the work he did getting ECMAScript into a living standard again. How soon people forget, but in the mid-aughts any mention of JavaScript was followed by a scoff.
Anyway, JavaScript shouldn't be trying specifically not to break MooTools. MooTools was trying to fix JavaScript.
[1]: https://twitter.com/donatj/status/1468728094588506115