8 ms·
iOS 8 length bug breaks jQuery and Underscore object iteration
- hahainternet 12y agoThe thing that shocks me most in this article is the subtleness of the bug inducing this behaviour: http://trac.webkit.org/changeset/182058 http://trac.webkit.org/changeset/182058
- gadr90 12y agoYep! Somebody explained quite clearly the bug over at reddit: http://www.reddit.com/r/webdev/comments/3104m3/ios_8_insidious_length_bug_breaks_jquery_and/cpxe2nc http://www.reddit.com/r/webdev/comments/3104m3/ios_8_insidio... I quote: > There is not length property inserted on the object, the jQuery folks had already confirmed that. It is a branch on the form of object that was failing due to a bug in the linkage of a jump. That made that bug very bizarre: you can access a length value by identifier, but now get a length property on the same object.
- joeframbach 12y agoThe workaround in the article was: var thingsGroupedById = _.groupBy(things, function(t){ return 'seller' + t.sellerId }); // { seller1: [...], seller2: [...] } But I actually would have failed this in code review: _.map(thingsGroupedById, function (things) { // ... }); and replaced it with: _.map(_.keys(thingsGroupedById), function (thingKey) { var thing = thingsGroupedById[thingKey]; // ... }); because although mapping over objects is "normal", it has never been 100%.
- gadr90 12y agoThis interests me very much. Are there known problems about mapping over objects? What do you mean it has never been 100%? Thanks!
- ewang1 12y agoThe latest version of underscore has a _.mapObject function.
- wging 12y agoWhy not instead do _.map(_.values(thingsGroupedById), function(thing) { // operate on thing } Then there's no need to do the property access yourself. Chaining makes this even nicer: _(thingsGroupedById).values().map(function(thing) { }
- deleted 12y ago[deleted]
- dandelany 12y agoDepends on what //... is. You might need the key for something, and you can get the value from the key but not vice versa.
- ars 12y agoThe crazy bug aside, I could have done without the animated image macros.
- calciphus 12y agoEveryone vents in their own way. I've used stupid pictures before to get over spending a whole afternoon fixing someone else's screw up.
- wildpeaks 12y agoArray.isArray() would be more reliable than testing if it has a property "length" :/ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- mkozlows 12y agoExcept as MDN says, that works in IE9+, and jQuery 1.x works in IE6+.
- wildpeaks 12y agoMDN has a polyfill for older browsers, right below the examples.
- caperfee 12y agoIt's not quite so simple since JavaScript has the concept of array-like objects - basically objects with a length property and numeric keys (but which aren't arrays). From the Underscore documentation: "Collection functions work on arrays, objects, and array-like objects such as arguments, NodeList and similar". So basically this bug can lead to false positives when checking for array-like objects.
- hayksaakian 12y agoI think the OP likes Emma Stone
- jessegavin 12y agoPeople still use Underscore?
- Dylan16807 12y agoI am aware of underscore as a nice blob of simple utility functions. I'm not aware of what you would replace it with?
- nailer 12y agoWhile the map() should be written in pure JS standard lib, the _.groupBy() is reasonable.
- BinaryIdiot 12y agoI didn't realize anyone used integers as keys. That feels so unnatural to me. I'm also surprised any libraries would check for .length to see if it's an array or not; there are plenty of objects you may want to create with a length property. It seems to me this would be a more accurate check: Object.prototype.toString.call(maybeArray) === "[object Array]" Also sometimes I feel like I'm the only one who doesn't like to use underscore or jQuery for things like this; iterating over properties is so easy it seems weird to me to use a library to create a new object for me to then iterate through.
- cwmma 12y agoIt's easy if your browser has Object.keys or nobody has mucked around with Object.prototype. As for the ease of testing if something is an array, figuring out if something is an array is relatively easy but array like objects like arguments and domlist are where length checking comes from.
- BinaryIdiot 12y ago> It's easy if your browser has Object.keys Most browsers can do a for..in. At least for me there is no browser in existence that I care about that doesn't have that :) > nobody has mucked around with Object.prototype That's just what object.hasOwnProperty(key) is for. An annoying extra check but not a big deal. > As for the ease of testing if something is an array, figuring out if something is an array is relatively easy but array like objects like arguments and domlist are where length checking comes from. There is an incredibly limited list; I'd just check for those few items instead of relying on a property existing that other objects could use but I digress.
- cwmma 12y ago> Most browsers can do a for..in. At least for me there is no browser in existence that I care about that doesn't have that :) then why are you using the underscore/lodash/jquery method, it's main advantage (besides working on array like objects) is compatibility for older browsers.. I'm, btw, on your side here and just use Object.keys and move on for objects and use a while loop for array like objects.
- tambourine_man 12y agoNot to be a jerk, but why not use objects for key value and arrays for int value? Yes, JavaScript object/array system has it's warts, but to me that's clearly the way it was intended to be used.
- myhf 12y agoThe article described the type of situation this arises in: when you want to use arbitrary data as keys of a map, for example when grouping a collection of objects by one of their properties. Any implementation of a hash/map/dictionary should support this process, whether or not it coerces the types of its keys. The problem with the engine in question is that it makes a hash change its behavior when all keys are integers.
- johnthedebs 12y agoI ran into this bug myself, and I spent an afternoon or so debugging it. A simple library upgrade (Underscore 1.7.0 -> 1.8.2) broke a key feature of a site I was working on, but only on my iPhone. It worked just fine on my iPad running the same exact version of iOS. I ended up using git bisect to narrow down the commit, which consisted of several minor updates to various packages. Of those packages, it was my 3rd or 4th guess as to which would have caused that failure (it wasn't clear since I was having trouble connecting the Safari debugger).
- supercoder 12y agoBe great if there was an AdBlock but for animated gifs in blog articles.
- m_eiman 12y agoMaybe there's a ClickToPlay for animated GIFs/PNGs? Edit: There is: https://addons.mozilla.org/en-US/firefox/addon/toggle-animated-gifs/ https://addons.mozilla.org/en-US/firefox/addon/toggle-animat...
- gadr90 12y agoI will add something like that myself soon enough. Thanks for pointing it out! I realize, now, that it bothers some people. https://github.com/firstdoit/firstdoit.com/issues/14 https://github.com/firstdoit/firstdoit.com/issues/14
- jackjeff 12y agoI noticed an instance of _.size(obj) returning "undefined" on a collection using number indices, but in each instance_.keys(obj).length would work fine. This was occurring on iOS 7.1.2 on a single device, from time to time. I realize after reading this, that this might be related to the WebKit bug, since it was the only 64 bit ARM device we had at the time. The bug disappeared when I simply used _.keys(obj).length instead of _.size(obj). It was very hard to reproduce and I could never isolate it in a sample... It's NOT the same bug though. It's kind of the opposite. The "length" property would disappear. Would that be caused by the same WebKit bug? Or that's a new one?
- startswithaj 12y agoI came across an equally strange bug a year or so ago. http://stackoverflow.com/questions/22139746/ios-javascript-engine-parsefloat1-returns-negative-number/22159620#22159620 http://stackoverflow.com/questions/22139746/ios-javascript-e... I found a way to reproduce it, put in a bug report with apple and never got a response.
- booleanbetrayal 12y agoFor an equally crazy bug that's affecting Angular and several other major libraries: https://github.com/angular/angular.js/issues/9128#issuecomment-77524687 https://github.com/angular/angular.js/issues/9128#issuecomme... Basically strict mode blows up webkit in odd ways.