Object killing in IE7

An IE7 bug where a line of code that never runs can still destroy a global object.

One 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?

First published on jpsykes.com.