Skip to content
This repository

isObject returning unexpected values in Chrome v19 MAC #605

Closed
subimage opened this Issue May 17, 2012 · 27 comments

8 participants

Seth brad dunbar Michael Ficarra Jakob Borg Donald Tetto Jeremy Ashkenas Jay Phelps Paul Irish
Seth

So I started getting bug reports from my customers this morning that certain things were breaking in my app.

After a little digging, it seems to be caused by the isObject feature of underscore. For some reason the default implementation is returning "true" for simple boolean variables - which it shouldn't be. For instance doing something like the following is returning true...

  var x = true;
  _.isObject(x); // true

Changing this...

  _.isObject = function(obj) {
    return obj === Object(obj);
  };

...to this

  _.isObject = function(obj) {
    return typeof obj == 'object';
  };

...fixes the problem. Unsure why you're doing the first check, as it seems overkill - when using 'typeof == "object"' has been the way to detect objects in JS since day 1.

brad dunbar
Collaborator

I'm also running Chrome 19 on OSX, but the code below returns false.

> var x = true;
> _.isObject(x);
  false

Would you mind reproducing your result and posting it as a fiddle?

Seth

How do i "post it as a fiddle?" I can reproduce this reliably in the console when my app is loaded.

brad dunbar
Collaborator

I just mean post it somewhere on the web so that I can take a look at it. jsfiddle.net, jsbin.com or gist.github.com are great places to post code to share through a url.

Seth

Can't reproduce it on Fiddle with about 5 minutes playing with it unfortunately, but here's output of my console after changing the _.isObject function to the following...

  // Is a given variable an object?
  _.isObject = function(obj) {
    var isObj = (obj === Object(obj));
    console.log("\n")
    console.log(obj);
    console.log(typeof obj);
    console.log(isObj);
    return isObj;
  };

http://dl.dropbox.com/u/156966/underscore_mac_console.png

...ideas on the above trace?

brad dunbar
Collaborator

Those results look correct to me. I'm going to close this as not reproducible for now, but please post a reproducible test case if you find it again.

brad dunbar braddunbar closed this May 18, 2012
Seth

A string returning true after returning false looks "correct"? o_O (See the end of the console output...)

Will try to reproduce, but for now I just hacked my underscore copy with my suggested fix and it solves my issue.

Michael Ficarra
Collaborator

I smell a troll...

Seth

@michaelficarra yeah i've got nothing better to do than file useless bug reports. STFU idiot.

Jakob Borg
calmh commented May 19, 2012

@subimage can you reproduce it on the console with "true === Object(true)"? Only when your app is loaded, or always? If only with your app, perhaps it or a library it uses messes with Object?

Seth
Donald Tetto
dtetto commented May 24, 2012

I have run into it here. I can't quite figure out why, as it's only occasional. "_.isObject('marker')" returns true under certain conditions. Bug filters down into Backbone.js Model#set(string,value).

Have a coworker who can duplicate it right now in his console:
_.isObject("marker")
true
Same code for me, same Chrome version, returns false.

Donald Tetto
dtetto commented May 24, 2012

(We're both on Chrome 19.0.1084.46, Underscore version is 1.3.2)

Jeremy Ashkenas
Owner

Unless edge chrome is changing the semantics of immutable JS strings, or the semantics of ==, that's pretty damn crazy. The implementation of isObject is just:

obj === Object(obj)
Jeremy Ashkenas
Owner

Do y'all have any changes made to either Object.prototype, or String.prototype?

Donald Tetto
dtetto commented May 24, 2012

No changes to either. Third-party scripts running on the page are Backbone, jQuery, Google Maps API. JS is compiled with Coffeescript.

As I said, the problem is only occasional; haven't been able to reproduce it reliably yet. Not sure why. Sessions in the webapp tend to last 20 minutes or more, so possible that something breaks along the way. Only seen it so far in Chrome 19.

@subimage Are you seeing it more predictably?

Donald Tetto
dtetto commented May 24, 2012

(When it comes up again, I'll be sure to play around plenty in console, since the problem does persist in the console session. But as soon as you reload the page it's fixed.)

Seth
Seth

@dtetto and yes - I can get it to happen reliably one one of my pages here - but only after my app initialization. I have so much JS on that particular page (prototype, underscore 1.3.2, a modified version of backbone to work with prototype, etc) that I don't want to post it all for a "test case".

Could not get it to happen with just prototype.js & underscore on jsfiddle.

Another oddity - it does not happen in Safari, or Firefox. Only Chrome...and only the newest version. I know they swapped out the v8 javascript engine in the latest version, so I'm sure that has something to do with it.

Jay Phelps

Just chiming in that we over at SignNow ran into this as well. I even gathered the team to confirm I wasn't on crack. For us, it was only happening in Chrome 20.0.1132.47 and very very sporadically. When it did happen, using the same implementation just by itself; that is, 'asdf' === Object('asdf') returns false, but _.isObject('asdf') returned true. Also confirmed that the implementation of _.isObject wasn't overriden as well.

All other primitives were returning true as well (booleans and numbers)

We thought what everyone else suggested, extending native prototypes, over-shadowing Object constructor, etc and we're still looking into these as they seem the most likely but the strange part is how random it is. When it happens, it is every time you use that helper, but hit refresh or try it again from a fresh load and nada.

No extensions installed. Flash was used on the page as well.

We have no solution yet, but hope this helps other people who stumble on this confirm they aren't crazy. For anyone who changes isObject to native typeof, keep in mind typeof null === 'object'! That'll bite you.

brad dunbar
Collaborator

Just for posterity, I believe that this bug, jashkenas/backbone#1543, and joyent/node#3867 are likely one and the same. If not, it seems that they are at least related and perhaps can point you in the right direction, though I'm sure you've come up with a workaround of some sort since posting here.

Donald Tetto

Crazy V8 bug! Thanks for the update. We have patched our underscore for it over here, but hopefully we'll be able to roll back that patch after a Chrome update with the fix goes out.

Jeremy Ashkenas
Owner

It's not a real bug in production Chrome, right? Just Canary?

brad dunbar
Collaborator

Running this gist in chrome stable I get the following, which I believe is a repro of the bug.

isObjectA(str): true
isObjectB(str): false
inline check:   false
Jay Phelps

This was in production Chrome for us. It was brought to our attention when a user couldn't load our web app because it was returning an incorrect value. We could only internally reproduce it in 20.0.1132.47. Haven't tested since my initial report. We moved away from using that function.

Jeremy Ashkenas
Owner

Eek.

Paul Irish

The source ticket: http://code.google.com/p/v8/issues/detail?id=2291

Looks to be from an optimization that triggers the bug only sporadically in special situations.

Ticket filed and fixed both today. It'll ship to stable/beta/dev/canary Chrome asap, from what I can tell. cc @erikcorry

Jay Phelps

@erikcorry @paulirish Did this make it into stable? Still listed as assigned.

We've been actively avoiding Object() and isObject() in our app, hoping to close this internal ticket.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.