5 ms·
> Trivia: the JavaScript spec people wanted to name it contains, but this was apparently already used by Mootools so they used includes That sounds ... unfortu
by oneeyedpigeon 9y ago
> Trivia: the JavaScript spec people wanted to name it contains, but this was apparently already used by Mootools so they used includes
That sounds ... unfortunate, to say the least. Why is the language spec. beholden to one framework written in that language? Doesn't mootools [1] check first for functions it might be overriding?
> Emojis and other double-byte chars are represented using multiple bytes of unicode. So padStart and padEnd might not work as expected!
It's a shame this isn't followed up on. What's the solution? Only use ASCII? Don't use padStart/padEnd? Does anyone know anything about monospace fonts and any guarantees they make wrt. unicode?
[1] https://mootools.net/core/docs/1.5.2/Types/Array#Array:contains https://mootools.net/core/docs/1.5.2/Types/Array#Array:conta...
- kevincennis 9y agoThe problem is that mootools did it first. But (I think, I’m on my phone and can’t check), they won’t replace the method if it already exists. So the problem is that if the spec differs in behavior at all from the mootools implementation, existing websites will break (meaning that the website was expecting the behavior of mootools’ implementation and got the spec version instead). Even if TC39 didn’t care about breaking old websites, the browser vendors do. So they simply wouldn’t implement the spec if it broke a bunch of websites. Backwards incompatible changes don’t really hurt developers as much as they hurt users. And the browser vendors don’t want people to start complaining about how websites are broken in [X].
- oneeyedpigeon 9y agoExisting websites will break if they depend on whatever the implementation difference is. Does anyone know what that difference actually is? Seems significant.
- DCoder 9y agoEven if their implementation is identical to the standard, it is still problematic. The key problem is the way MooTools tries to copy over that method (and many other methods): > Currently, Array.prototype.flatten = mooToolsFlattenImplementation creates an enumerable flatten property, so it’s later copied to Elements. But if we ship a native version of flatten, it becomes non-enumerable, and isn’t copied to Elements. Any code relying on MooTools’ Elements.prototype.flatten is now broken. > Although it seems like changing the native Array.prototype.flatten to be enumerable would fix the problem, it would likely cause even more compatibility issues. Every website relying on for-in to iterate over an array (which is a bad practice, but it happens) would then suddenly get an additional loop iteration for the flatten property. > The bigger underlying problem here is modifying built-in objects. Extending native prototypes is generally accepted as a bad practice nowadays, as it doesn’t compose nicely with other libraries and third-party code. Don’t modify objects you don’t own!
- geoelectric 9y agoOn Chrome and Firefox, at least, as long as I delete Array.prototype.whatever first, I get an enumerable property when I polyfill it. Not saying that's the ideal solution, and there are certainly other issues with extending built-ins and clobbering the original name. The Chrome blog also mentions forcing a patch to legacy websites is an unacceptable solution (though I'm not sure I agree with that unless we want to maintain name compatibility with every library forevermore). However, it's certainly not a matter where MooTools would have to completely rework what they're doing, or where the browser would have to make the property enumerable from the start. In fact, it'd be easy enough to use a compatability shim on the site side that'd nuke all the conflicting properties from Array.prototype before Mootools ever loads, if they know they're on ES5 and would never use the native ones. > Array.prototype.map = () => { console.log('map, yo'); } function Array.prototype.map() > [].map() map, yo undefined > for (k in []) console.log(k) undefined > delete Array.prototype.map true > Array.prototype.map = () => { console.log('map, yo'); } function Array.prototype.map() > [].map() map, yo undefined > for (k in []) console.log(k) map undefined
- DCoder 9y ago> as long as I delete Array.prototype.whatever first, I get an enumerable property when I polyfill it. The key point there is "deleting first". If you assign to a property without deleting it first, it continues to be non-enumerable. > it's certainly not a matter where MooTools would have to completely rework what they're doing > it'd be easy enough to use a compatability shim on the site side MooTools has released a patch for this problem. The problem is indeed the sites that have been built and left to their own devices. This is not at all dissimilar to Windows dragging around garbage needed "to permit four programs written in 1994 to continue running" [1]. [1]: https://blogs.msdn.microsoft.com/oldnewthing/20031103-00/?p=41973 https://blogs.msdn.microsoft.com/oldnewthing/20031103-00/?p=...
- geoelectric 9y agoI definitely agree with that last point. I get the desire to keep the top 100 sites going--I used to be on test for Mozilla, and you really don't want to be the browser that can't view a significant chunk of the web. But that sort of fear-based commitment to backwards compatibility didn't do Windows any favors. I'd really hate to see it become endemic to the web.
- lttlrck 9y agoThis is a terrible idea, but if it really is the browser vendors fighting this then perhaps the browser should detect mootools (black list websites?) and disable the newer versions. Perhaps Google crawler already has this list.
- thrownaway954 9y ago"but this was apparently already used by Mootools so they used includes" serious question... does anyone even use mootools at this point in time to even consider this? seems like more and more people are going leaving jquery for vanilla javascript everyday, so i have to conclude that jquery itself will eventually run it's course, like prototype did, and die off, but i would have thought that mootools died long ago.
- jayflux 9y agoThere are various ways of testing this, for instance in the case of ‘flatten’ Firefox released it in their Nightly and it did break a top 100 site, that was enough to end the debate. https://bugzilla.mozilla.org/show_bug.cgi?id=1443630 https://bugzilla.mozilla.org/show_bug.cgi?id=1443630
- stareatgoats 9y agoApprox 460,000 websites [0]. Among them jsfiddle.net, tripadvisor.com. [0] https://www.wappalyzer.com/technologies/mootools https://www.wappalyzer.com/technologies/mootools
- cpeterso 9y agoOld sites using old versions of Mootools might never be updated. Even if Mootools fixed their feature detection of contains() and flatten(), old Mootools versions will still be floating around on real sites forever.
- a_humean 9y agoBasically mootools screwed up, and this is what smooshGate was about as well. They modified the array prototype directly with their own methods. They did feature detection on the prototype by checking if the method of that name existed ("flatten" in the case of smooshGate, "contains" in the case of "includes"), and didn't replace the prototype method if a function of that name already existed on the prototype (whether or not its a compatible implementation or not). Unfortunately, the behavior of these mootools methods differed enough from the official spec that they cannot be used interchangeably. The consequence is if "flatten" or "contains" were to become part of the official spec and implemented by browsers, then all legacy mootool applications would break and mootools is apparently a big enough deal that it ends conversation. This is what happened when Mozilla implemented flatten on firefox nightly: https://bugzilla.mozilla.org/show_bug.cgi?id=1443630 https://bugzilla.mozilla.org/show_bug.cgi?id=1443630
- jasonkester 9y agoThat just proves that "contains" is the correct name for the language feature. Implement it correctly, without regard to any silly things that 3rd parties were doing. 5 years from now, nobody will remember that library. Do it the way they're doing, and 5, 15, 50 years from now people will still be asking why this stupid language used a non-standard method name for Array.contains. Extra points for encouraging all the other poorly implemented javascript libraries to fix their things before they break for similar reasons.
- Klathmon 9y agoI disagree. "contains" might be a nice name, but if it breaks a significant number of websites and forces many to have to update and fix websites that have worked for years, then a simple rename is a fantastic solution in my opinion. This isn't about being "right", it's about finding the best solution to the problem at hand, and a solution that breaks things but is "technically correct" is worse than one that doesn't break things but has a slightly wonky name.
- hungerstrike 9y ago
- masklinn 9y ago> That sounds ... unfortunate, to say the least. Why is the language spec. beholden to one framework written in that language? Doesn't mootools [1] check first for functions it might be overriding? I've looked at it and things are actually worse than I thought: not only do the spec and mootools disagree on behaviour (spec is shallow while mootools is deep) the actual issue — and the one which already broke `contains` is that Mootools adds methods to Array, conditionally for recent-ish version, but it then copies them over to Element. The issue there is that it iterates Array.prototype and copies over what it finds. "Spec" methods are defined as non-enumerable, so it doesn't see them, does not copy them over, and thus using these methods on Element doesn't work anymore. Funnily enough this breaks whether it implements its extensions conditionally or not: even if it re-sets the method, it doesn't reset the enumerable flag, so they're still not enumerable, and still not copied over to Element. This means the method would apparently have to be enumerable (which normally isn't the case) or it would need to be a non-data property with a setter magically setting the enumerable bit. And the committee is apparently unenthused by this prospect.
- ubernostrum 9y agoWhat's the solution? Only use ASCII? Don't use padStart/padEnd? Does anyone know anything about monospace fonts and any guarantees they make wrt. unicode? Well. The description given of "multiple bytes of unicode" is terribly misleading. There are multiple reasons you might run into trouble in a JavaScript string. One is that it uses UTF-16 for its string type; this represents Unicode code points as 16-bit units. For code points which fit in 16 bits, it uses one unit, and for code points that don't it uses two units, so it's a variable-width encoding (all code points of Unicode can be represented with 32 bits, so two units for a code point is the most you'll see in a UTF-16 byte sequence). This is done via a mechanism which derives two "surrogate" code points from the original, and the resulting two code points are called a "surrogate pair". Unfortunately, JavaScript leaks this implementation detail to the programmer, which means many string operations can "cut" a surrogate pair in two and leave you with code points that don't actually represent any character, because they're from the surrogate range. But that's not what's happening in the given example. Emoji are complicated. Some emoji use only a single Unicode code point, while others are composed from multiple code points, potentially with a joiner code point in between. Here's a comment I just posted in another thread with an example: https://news.ycombinator.com/item?id=16757317 https://news.ycombinator.com/item?id=16757317 In the example in the linked article, the "heart" emoji is actually two code points: U+2764 HEAVY BLACK HEART and U+FE0F VARIATION SELECTOR-16. The first is a heart-shaped character that's been around for years; the second is a "variation selector" character which tells whatever's rendering this that it should use a variant emoji-style presentation. But since that's two code points, again, operations on it can "cut" it in half and cause havoc. The "workaround" is not to use string indexing or slicing operations in JavaScript if you think you'll be handed emoji or anything else from outside the Basic Multilingual Plane of Unicode, or to be prepared to manually handle them. As to monospace fonts, this article has a great rundown of how Unicode actually works, and an exploration of how various monospace environments try, and often fail, to handle it: https://eev.ee/blog/2015/09/12/dark-corners-of-unicode/ https://eev.ee/blog/2015/09/12/dark-corners-of-unicode/