Skip to content

$.each fails intermittently on iOS due to Safari bug #2145

Closed
@osolo

Description

@osolo

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:

http://stackoverflow.com/questions/28155841/misterious-failure-of-jquery-each-and-underscore-each-on-ios

Activity

mgol

mgol commented on Mar 14, 2015

@mgol
Member

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.

added this to the 3.0.0 milestone on Mar 14, 2015
osolo

osolo commented on Mar 14, 2015

@osolo
Author

@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

mgol commented on Mar 14, 2015

@mgol
Member

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

osolo commented on Mar 18, 2015

@osolo
Author
dmethvin

dmethvin commented on Mar 18, 2015

@dmethvin
Member

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

mgol commented on Mar 18, 2015

@mgol
Member

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

BenjaminPoulain commented on Mar 18, 2015

@BenjaminPoulain

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

mgol commented on Mar 20, 2015

@mgol
Member

Is it worth doing another minor-point release for this?

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

osolo commented on Mar 20, 2015

@osolo
Author

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

mgol commented on Mar 20, 2015

@mgol
Member

8.x will have a lot of market share for a while to come

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

mgol commented on Mar 20, 2015

@mgol
Member

BTW: according to jashkenas/underscore#2094 (comment):

I don't think the bug is reproable in the iOS simulator which is what Sauce uses.

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

BenjaminPoulain commented on Mar 20, 2015

@BenjaminPoulain

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions

    $.each fails intermittently on iOS due to Safari bug · Issue #2145 · jquery/jquery