Object Killing in IE7 (bug)
November 30th, 2007One of my client colleagues, John Viszmeg, just found an interesting bug in IE7. It was manifesting in dojo.provide, but it’s not really a Dojo bug, it’s at the browser level and dojo.provide just does a great job in demo’ing it.
It’s a weird one, so I’ll keep the intro brief. Basically you can instantiate a global level object, and then have that object destroyed in IE7 by a line of code inside a conditional statement that never returns true (and thus should have no play in what it going on).
Yes, it sounds crazy. Putting code inside of a if(true === false) conditional can actually trash an object. What’s even better is it trashes the object if you try to access it BEFORE the conditional statement block but within the same script tag (so it’s not even doing things in order any more).
I’ve put together a test page that shows this is, remember it’s IE7 only.
The code on that page looks like this:
-
-
<script type="text/javascript">
-
this[‘test’] = {};
-
alert(this[‘test’]);
-
// will spit out [Object object]
-
</script>
-
<script type="text/javascript">
-
alert(this[‘test’]);
-
// will spit out Undefined in IE7
-
-
// this next chunk of code should never run.
-
if (true == false){
-
alert("This never fires");
-
// THIS SHOULD NOT IMPACT ON ANYTHING !!!!
-
var test;
-
alert("This never fires");
-
}
-
</script>
-
Commenting out the line “var test;” makes the issue go away.
Another fix to the issue is to not declare your objects that way, but to instead do:
-
-
<script type="text/javascript">
-
var test = {};
-
alert(this[‘test’]);
-
// will spit out [Object object]
-
</script>
-
<script type="text/javascript">
-
alert(this[‘test’]);
-
// will now spit out [Object object]
-
-
// this next chunk of code should never run.
-
if (true == false){
-
alert("This never fires");
-
var test;
-
alert("This never fires");
-
}
-
</script>
-
I put this fix page up as a contrast.
Another weird quirk is that the bug only occurs in the conditional and the second alert is situationed inside a different script tag from where the object is initially declared, so code like this does not show the bug:
-
-
<script type="text/javascript">
-
var test = {};
-
alert(this[‘test’]);
-
// will spit out [Object object]
-
-
-
alert(this[‘test’]);
-
// will now spit out [Object object]
-
-
// this next chunk of code should never run.
-
if (true == false){
-
alert("This never fires");
-
var test;
-
alert("This never fires");
-
}
-
</script>
-
I’ve done a huge amount of searching and I can’t find any reference to anything like this. It has to be some sort of namespacing issue that IE has, but the fact that code in a conditional that doesn’t run causes this is just beyond me.
It probably wouldn’t have come up, expect that dojo.provide uses the above x[’y']={} style of object declaration.
-
-
//Bootstrap1.js in Dojo 0.4.3
-
-
dojo.evalProp = function(name, object, create){
-
if((!object)||(!name)) return undefined;
-
if(!dj_undef(name, object)) return object[name];
-
return (create ? (object[name]={}) : undefined);
-
}
-
-
//Bootstrap.js in Dojo 1.0
-
-
dojo._getProp = function(parts, create, context){
-
var obj=context||d.global;
-
for(var i=0, p; obj&&(p=parts[i]); i++){
-
obj = (p in obj ? obj[p] : (create ? obj[p]={} : undefined));
-
}
-
return obj;
-
}
-
So any objects created using dojo.provide are susceptible to being wipped out by the example situation.
-
-
<script type="text/javascript" src="http://test.jpsykes.com/junk/dojo/dojo-0.4.3/dojo.js"></script>
-
<script type="text/javascript">
-
dojo.provide(‘test’);
-
alert(this[‘test’]);
-
// will spit out [Object object]
-
</script>
-
<script type="text/javascript">
-
alert(this[‘test’]);
-
// will spit out Undefined
-
-
// this next chunk of code should never run.
-
if (true == false){
-
alert("This never fires");
-
var test;
-
alert("This never fires");
-
}
-
</script>
-
As can be seen in this demo page, I set up.
Anyone have any ideas on this?

November 30th, 2007 at 3:16 am
[…] Sykes thinks he has found a bizarre bug in IE7. Since Microsoft has 34 QA people per developer, surely not! […]
November 30th, 2007 at 3:37 am
Looks like IE tries to declare the variable anyway, in a first pass over the script block. Because originally you declared `test` as a property of the window object, `test` is not marked as a declared variable and therefore overwritten.
What happens if instead of simply declaring the variable, you assign declare it and assign a value?
November 30th, 2007 at 5:21 am
[…] Sykes thinks he has found a bizarre bug in IE7. Since Microsoft has 34 QA people per developer, surely […]
November 30th, 2007 at 5:57 am
i get the feeling this is the new IE garbage collector related - ive seen a similar thing where a global (window) variable gets deleted randomly because of parser problems. Ive found that it only happens when ‘this’ -> the window
November 30th, 2007 at 6:46 am
Hi jpSykes,
This is not a bug. JavaScript does not have block scope. Variables introduced with a block are scoped to the containing function or script, and the effects of setting them persist beyond the block itself. In other words, block statements do not introduce a scope. Although “standalone” blocks are valid syntax, you do not want to use standalone blocks in JavaScript, because they don’t do what you think they do.
So, in your example the ‘test’ variable in the if condition is escalated to the script block level.
This can be proved by alert(this[’test’] === test);
Please refer to http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Statements:block
November 30th, 2007 at 8:53 am
[…] Sykes has discovered a bizarre bug in Internet Explorer 7 (and presumably IE6 as there is next to no difference in the JScript engines). You probably […]
November 30th, 2007 at 9:16 am
@Raja, but if test is already defined, doing var test; should not result in the first object being crushed.
November 30th, 2007 at 11:45 am
[…] Sykes thinks he has found a bizarre bug in IE7. Since Microsoft has 34 QA people per developer, surely […]
November 30th, 2007 at 6:39 pm
“but if test is already defined, doing var test; should not result in the first object being crushed.”
Please note that the scope of ‘test’ variable in the if condition is ascalated to the script scope which in turn is === global as you have not enclosed the logic in a function but instead is in a script block. So your this[’test’] has just been overriden.
Please refer to page 55 in the book Javascript : The Definitive Guide by Gavid Flanagan.
So the final verdict is that the first variable is actually not crushed but set to ‘undefined’ because you just declared the var test; which === ‘undefined’.
This is clearly justified by testing using alert(this[’test’] === test); notice the ‘===’ which says that both the variables refer to the same object.
November 30th, 2007 at 10:38 pm
Now, the question is, do other browsers behave like this? I can understand Raja’s explanation that this[’test] === test because this === window, but that still doesn’t justify Internet Explorer executing a variable declaration in a conditional block that never runs.
December 1st, 2007 at 3:08 pm
Raja, sorry but although I see where you’re coming from, the argument that this is expected and correct I just don’t agree with:
A: It doesn’t occur in any other browser.
B: It seems to fly in the face of other specs that say if a var exists and you do “var foo;” it should NOT kill that var and set it to undefined. See New Test Case I just added.
C: if it was correct then it should also occur in IE7 if you just do it with regular variables, which it does not, it onlt occurs with objects, that are set in the fashion outlined in the first test case.
Personally, I believe it’s a bug, one around how IE7 sets up window objects if they are defined using the this[’foo’] syntax. As far as I can see there isn’t any easy “fixes”, yet it’s a bug that if you’re aware of you can easy avoid. It’s that knowledge that I’m hoping I might be passing on with this post, as it’s a debug nightmare of a bug.
The fix we’re using at work is to just define all global object namespaces using var foo = {}; at the head of the page.
December 1st, 2007 at 10:14 pm
[…] Sykes has found an interesting bug in IE7. In his post found a bizarre bug in IE7, he demonstrated the bug with some simple test scripts. Quite frankly, it should be a rare case to […]
December 3rd, 2007 at 6:51 am
That’s a common behave of the IE scripting engine and can be reproduced in all versions of that browser and it can become a problem for libraries, if you e.g. create two scripts, the first one containing ‘function Test(){};Test.S=”Hello World”;’ and the second script containing ‘if( !window[”Test”] ) { function Test(){}; }; alert(Test.S);’, then you would expect an alter box with “Hello World” in it if you include both in this order, but you get a box with “undefined”. If you change the second script in “if( !window[”Test”] ) { window[”Test”] = function(){}; }; alert(Test.S);’, then it works as intended. It seems that IE is parsing a script at load time and directly declares all variables beeing defined using keywords like “var” or “function”, ignoring conditions. Even if this behave isn’t against the standard (I don’t know), it’s a weird implementation.