Description
There is a timing bug in iOS8 that causes mobile Safari to incorrectly report a 'length' on objects that don't have one.
To the best of my knowledge, this happens on iOS8+, possibly only on 64-bit systems. The bug is triggered for objects that have only numeric properties. For example:
foo = { 1: 'a', 2: 'b', 3: 'c' }
In this case, if you query foo.length
then mobile Safari will sometimes return 4 (the highest property + 1).
This causes functions like $.each()
to treat objects such as foo above as arrays instead of objects, and when it tries to iterate them as such it fails since there is no foo[0].
The problem can be fixed in the function isArrayLike()
. Instead of just checking for
typeof length === "number"
you also need to check for
obj.hasOwnProperty('length')
The latter check is immune to the iOS bug.
I realize this is a fix just for one browser, but it's a browser with a very large user base.
You can see more background and some repro steps at the following Stack Overflow discussion:
Activity
mgol commentedon Mar 14, 2015
Thanks for the report! This is really weird and due to being a timing issue it seems impossible to write a test for it. :( Did you report it to Apple? And/or to https://bugs.webkit.org/? We'd like an issue we'd be able to link to.
I agree we should work around it.
osolo commentedon Mar 14, 2015
@mzgol I agree that writing a test case would be impossible. I didn't report the issue to Apple. I think it would carry more weight coming from the jQuery team, but if you point me to the right direction I'd be happy to file with them myself.
mgol commentedon Mar 14, 2015
The description you provided seems detailed enough. You could report a bug at https://bugs.webkit.org/, mention it affects jQuery & link to this issue.
osolo commentedon Mar 18, 2015
Link to WebKit bug: https://bugs.webkit.org/show_bug.cgi?id=142792
dmethvin commentedon Mar 18, 2015
Wow. I guess this must be rare enough that it doesn't occur that often? Plain object, only numeric indices, etc. There's a patch in jashkenas/underscore#2094 that says it tries to work around this. We could do something similar but it seems like we're in the same situation as we were with the December release. Is it worth doing another minor-point release for this?
mgol commentedon Mar 18, 2015
I'd like to get a response to this WebKit bug first to know what we're dealing with. @BenjaminPoulain, could you have a look?
BenjaminPoulain commentedon Mar 18, 2015
Yep.
This looks like a bug in one of the two optimizers. The problem likely only occurs after the code has been executed a few thousand times.
First, I'll try to make a test case to reproduce.
mgol commentedon Mar 20, 2015
It might be... We could ask people affected to comment here. This seems like a bug that manifests mainly in large apps where it will be hard to debug.
If Apple is going to fix it & backport a fix to the 8.x line we could punt on this but we won't know before the release (judging by past events) so IMO we should proceed assuming there won't be any backport here.
osolo commentedon Mar 20, 2015
I suggest this go out in the next point release regardless of what Apple does. 8.x will have a lot of market share for a while to come and this bug is VERY nasty to diagnose. It took me weeks to unearth the core problem. jQuery is in a great position to spare people the anguish.
mgol commentedon Mar 20, 2015
Yes, I meant that if Apple backported this fix to iOS 8.3 & Safari 8.0.5 then we shouldn't release a patch; before most people would have noticed the bug would be fixed.
If the fix will get only to iOS 9/Safari 9 then we still need a patch since we'll be supporting iOS 8/Safari 8 for a while.
I'd still want to hear from more affected people but I tend to agree this is something that will need a patch release. :/
mgol commentedon Mar 20, 2015
BTW: according to jashkenas/underscore#2094 (comment):
we won't be able to write a meaningful test for it since we run the test in simulators as well. :/ Unless someone is going to run the suite manually on iOS 8 from time to time (the number of people being able to do it will drastically decrease with the release of iOS 9).
BenjaminPoulain commentedon Mar 20, 2015
I have had a hell of a time reproducing this. I cannot even tell if the bug exists in WebKit trunk or not. Any attempt at instrumenting the JIT makes the bug disappear due to the changes of timing.
Has anyone found a reliable way to reproduce this bug? I have been using the test case of http://stackoverflow.com/questions/28155841/misterious-failure-of-jquery-each-and-underscore-each-on-ios but it is very fragile.
55 remaining items