

iOS 8 length bug breaks jQuery and Underscore object iteration - gadr90
http://firstdoit.com/ios-8-insidious-length-bug-on-jquery-and-underscore-each-map/

======
hahainternet
The 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
Yep! Somebody explained quite clearly the bug over at reddit:
[http://www.reddit.com/r/webdev/comments/3104m3/ios_8_insidio...](http://www.reddit.com/r/webdev/comments/3104m3/ios_8_insidious_length_bug_breaks_jquery_and/cpxe2nc)

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.

------
BinaryIdiot
I 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
It'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
> 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
> 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.

~~~
BinaryIdiot
> 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..

Oh I'm not my point was it's not really necessary anymore. It's been so long
since browsers didn't have support for these kinds of things I can't imagine
the compatibility is that important anymore except in say corporate
environments.

------
startswithaj
I came across an equally strange bug a year or so ago.

[http://stackoverflow.com/questions/22139746/ios-
javascript-e...](http://stackoverflow.com/questions/22139746/ios-javascript-
engine-parsefloat1-returns-negative-number/22159620#22159620)

I found a way to reproduce it, put in a bug report with apple and never got a
response.

------
joeframbach
The 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%.

~~~
wging
Why 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) {
    
        }

~~~
dandelany
Depends on what //... is. You might need the key for something, and you can
get the value from the key but not vice versa.

------
johnthedebs
I 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).

------
ars
The crazy bug aside, I could have done without the animated image macros.

~~~
calciphus
Everyone 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
Array.isArray() would be more reliable than testing if it has a property
"length" :/

[https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Refe...](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray)

~~~
mkozlows
Except as MDN says, that works in IE9+, and jQuery 1.x works in IE6+.

~~~
wildpeaks
MDN has a polyfill for older browsers, right below the examples.

------
booleanbetrayal
For an equally crazy bug that's affecting Angular and several other major
libraries:

[https://github.com/angular/angular.js/issues/9128#issuecomme...](https://github.com/angular/angular.js/issues/9128#issuecomment-77524687)

Basically strict mode blows up webkit in odd ways.

------
jackjeff
I 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?

------
tambourine_man
Not 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
The 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.

------
supercoder
Be great if there was an AdBlock but for animated gifs in blog articles.

~~~
m_eiman
Maybe there's a ClickToPlay for animated GIFs/PNGs?

Edit: There is: [https://addons.mozilla.org/en-US/firefox/addon/toggle-
animat...](https://addons.mozilla.org/en-US/firefox/addon/toggle-animated-
gifs/)

~~~
gadr90
I 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)

------
hayksaakian
I think the OP likes Emma Stone

------
jessegavin
People still use Underscore?

~~~
Dylan16807
I am aware of underscore as a nice blob of simple utility functions. I'm not
aware of what you would replace it with?

~~~
147
lodash is basically an underscore replacement.
[https://lodash.com/](https://lodash.com/)

~~~
untog
For a second there I thought we might get a thread that mentions Underscore
without Lodash being plugged.

Oh well, maybe next time.

