New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Weird typeof issue in IE8 ( ie11 ) #1621

Closed
danschumann opened this Issue May 2, 2014 · 24 comments

Comments

Projects
None yet
6 participants
@danschumann

danschumann commented May 2, 2014

See my stackoverflow post here
http://stackoverflow.com/questions/23432494/ie8ie11-typeof-object-function-true-what

Basically,

String(typeof obj) is needed, since (typeof obj === 'object' && typeof obj === 'function') // true

IE8 is weird. I think it does a weird optimization where typeof obj isn't a string unless you save it to a variable.

var t = typeof obj
t === 'function' // false
t === 'object' // true

but ( parenthesis isn't enough to de-optimize)

(typeof obj) === 'function' // true -- this is the currently broke line in underscore _.isFunction
(typeof obj) === 'object' // true

you can also just wrap it in String

String(typeof obj) === 'function' // false
String(typeof obj) === 'object' // true

obj is defined from backbone. It is this.el. It is a dom element

I know its not really broken ( ie8 is what's broken, and maybe only the ie11 version of ie8 at that )

@jdalton

This comment has been minimized.

Contributor

jdalton commented May 2, 2014

The IE8 issue is known for host objects, basically pre-es5 implementations played by their own rules, reporting that they were a function when they weren't or an object when they weren't. For dom elements you should use _.isElement or _.isObject.

On the typeof issue, I'm not familiar with that could you create a small jsbin of where typeof obj === 'object' && typeof obj === 'function' is true

@danschumann

This comment has been minimized.

danschumann commented May 2, 2014

// Optimize `isFunction` if appropriate.
if (typeof (/./) !== 'function') {
  _.isFunction = function(obj) {
    return ('' + typeof obj) === 'function';
  };
}

is what I ended up changing it to, since last i checked ('' + b) is faster than String(b).

I don't know how much slower this makes the method in general or if it is worth putting it into underscore since it might be an isolated bug

@danschumann

This comment has been minimized.

danschumann commented May 2, 2014

@jdalton Well, any old document.createElement('div') doesn't seem to be causing the bug.

The problem is _.result calls _.isFunction, and backbone calls _.result to get this.el. None of this is my doing. I'll see if I can reproduce without a ton of code.

@jdalton

This comment has been minimized.

Contributor

jdalton commented May 2, 2014

I can't reproduce this on my own tests. The amount of this is weird is a red flag and means further investigation is probably needed before we start throwing code at Underscore core.

@danschumann

This comment has been minimized.

danschumann commented May 2, 2014

Yea I agree, it might not even be a problem in real IE8.

@jdalton

This comment has been minimized.

Contributor

jdalton commented May 2, 2014

Btw I work at Microsoft on Chakra (the JavaScript in IE9 and up). I'll ask around. I'm aware of Java applets causing some odd behavior on property access/types but not certain I've seen this.

@danschumann

This comment has been minimized.

danschumann commented May 2, 2014

Nice. Yea, I gave u enough to show what kind of weird JS behavior where a string is not really a string or something... unless it's set to a variable then it behaves.

@jdalton

This comment has been minimized.

Contributor

jdalton commented May 2, 2014

Yea, I gave u enough to show what kind of weird JS behavior

Having a small repro would really help. If it is a JIT bug those can be hard to stumble upon.
What kind of element is it?

@danschumann

This comment has been minimized.

danschumann commented May 2, 2014

its a canvas element for one, I've taken the outerHTML to isolate the problem in a jsfiddle, but it is not reproducing using underscore, jquery and backbone.

There is another issue where the scrollbar, while present, does not work. I can click the middle mouse wheel and scroll via that (not scroll but click), and then after after I'm done with that, I can scroll as normal, so that's definitely a browser bug ( chrome ), but nothing to do with this problem, it could be something related if for some reason some internal features are getting messed with. Why else would typeof anything, which returns a string, simultaneously triple equal any other string? And setting the return of that to a variable fixes it.. so something internal to the browser is getting seriously messed with, perhaps that's why the scrollbar is having some issues, though the code I'm using is not super processor intensive or anything too crazy, just basic form manipulation and some very basic canvas interaction.

It could have something to do with any of these libraries.. it's something I've been putting off, hoping it'll resolve on it's own / I can hack a fix. I've got a lot of application code too, but I can't see putting that all on here and expecting you to dig through it, but maybe including some of these could reproduce or you might see one that looks suspect off the bat. easyXDM would be my first look at.

  <script src="/javascripts/json2.js"></script>
  <script src="/javascripts/underscore-custom.js"></script>
  <script src="/javascripts/jquery-1.11.0.js"></script>
  <script src="/javascripts/jquery-ui-1.9.2.custom.js"></script>
  <script src="/javascripts/jquery.serializeObject.js"></script>
  <script src="/javascripts/jstorage.js"></script>
  <script src="/javascripts/backbone.js"></script>
  <script src="/javascripts/backbone.queryparams.js"></script>
  <script src="/javascripts/coffeecup.js"></script>
  <script src="/javascripts/easyXDM.js"></script>
@danschumann

This comment has been minimized.

danschumann commented May 2, 2014

actually, it still happens with these libraries disabled

#'json2',
'underscore-custom',
'jquery-1.11.0',
'jquery-ui-1.9.2.custom',
#'jquery.serializeObject',
#'jstorage',
'backbone',
'backbone.queryparams',
'coffeecup',
#'easyXDM',
#'launch_mobile',
#'iframe_resizer'
@danschumann

This comment has been minimized.

danschumann commented May 2, 2014

okay so it is happening on line 1105 of backbone 1.0.0

backbone is calling this.setElement(_.result(this, 'el'), false);

the view is being called like so

 new WindView({el: @$('.wind-canvas')[0], model: model});

So.. its really weird..

_.result takes in object, property, then value = object[property]

i can console.log value and it is the dom element, BUT, in the console, when I console.log object, and look at the el property, it is [object Object] {...} with undefined undefined when i expand IT.

So, the el simultaneously exists and doesn't.. it can be pulled out but not seen on the parent. Anyway, I will look into this more on monday

@jdalton

This comment has been minimized.

Contributor

jdalton commented May 21, 2014

I just ran into this running Underscore's unit tests in IE11 under IE8 compat mode.

Here is a small repro test case showing the issue. This looks like a JIT bug in IE11 when dealing with host objects in non-edge document modes.

From the repro test case the console log output should be:

before JIT isFunction(fnc).  Expected: true;  Got: true
before JIT isFunction(obj).  Expected: false; Got: false
before JIT isFunction(num).  Expected: false; Got: false
before JIT isFunction(xml).  Expected: false; Got: false
typeof xml object
after JIT isFunction(fnc).   Expected: true;  Got: true
after JIT isFunction(obj).   Expected: false; Got: false
after JIT isFunction(num).   Expected: false; Got: false
after JIT isFunction(xml).   Expected: false; Got: false

But instead the last log is:

after JIT isFunction(xml).   Expected: false; Got: true

The workaround is to simply add || false to _.isFunction:

_.isFunction = function(obj) {
  return typeof obj === 'function' || false;
};

Related to #605.

@jdalton

This comment has been minimized.

Contributor

jdalton commented May 21, 2014

@danschumann can you confirm if the workaround (manually modify your copy of Underscore) solves your issue too?

mattpodwysocki added a commit to Reactive-Extensions/RxJS that referenced this issue May 21, 2014

jdalton added a commit to lodash/lodash that referenced this issue May 21, 2014

@danschumann

This comment has been minimized.

danschumann commented May 22, 2014

The original issue is no longer occurring. Not sure if IE had a hotfixed or I changed some code elsewhere that was causing it. I didn't update underscore but something else seems to have fixed it.

@jdalton

This comment has been minimized.

Contributor

jdalton commented May 22, 2014

The original issue is no longer occurring.

I confirmed on my own that the || fase does indeed fix the issue.

@akre54

This comment has been minimized.

Collaborator

akre54 commented Jul 10, 2014

Is this still needed?

@jdalton

This comment has been minimized.

Contributor

jdalton commented Jul 10, 2014

Yap.

@akre54

This comment has been minimized.

Collaborator

akre54 commented Jul 10, 2014

So is the || false fix worth adding? Want to open a pull if so?

@akre54

This comment has been minimized.

Collaborator

akre54 commented Jul 10, 2014

What's the aversion to opening pulls yourself? I follow the lodash repo but I really have no interest in constantly comparing implementations.

@ryan-roemer

This comment has been minimized.

ryan-roemer commented Jul 17, 2014

Hi @jdalton , et. al!

Has anyone had a chance to confirm this isn't an issue on "real" IE8?

@jdalton

This comment has been minimized.

Contributor

jdalton commented Jul 17, 2014

Has anyone had a chance to confirm this isn't an issue on "real" IE8?

I've investigated, this only affects IE11 in non-edge compat modes.

@kltan

This comment has been minimized.

kltan commented Jul 17, 2014

@jdalton Thanks for confirming, probably nice to have it in the underscore test suite.

@jdalton

This comment has been minimized.

Contributor

jdalton commented Jul 17, 2014

Related to lodash/lodash@0e88901.

@vorou

This comment has been minimized.

vorou commented Aug 19, 2014

I'm having the issue with IE11 in IE8 mode as well. It looks like it only happens with non-minimized version of scripts. || false did the trick.

@akre54 akre54 closed this in 15a757d Aug 19, 2014

@akre54 akre54 added the bug label Aug 19, 2014

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