Updated below

For reasons that I don't want to talk about right now I've read the JavaScript specification (ECMA-262, 3rd edition) when I stumbled upon a small mystery. It'd be more of a challenge than a mystery if the major Web browsers and their JavaScript engines didn't totally disagree on what is the correct answer.

Here's the problem. If you want to compile JavaScript to native code (see one of my earlier blog posts on why you would want to do this) you need at one point to decide where to put all the data, especially the local variables, so the CPU can find the stuff when it's executing the code. It's like the table of content in a book (no, it isn't but for the sake of argument let's pretend it is). If value can't be found in the local scope of a function it must be in either an intermediary scope (because function definitions can be nested) or in the global top-most scope. Where the values are at run-time can be determined at compile time, i.e. the compiler can (and will) generate code (the "table of content", if you will) to locate the value.

The problem is that there's a JavaScript feature called eval that evaluates a JavaScript text piece handed to it as argument. What happens if the text piece contains a variable declaration? Note that by the time the processor executes the code and calls the eval function all variables and values are set in stone (or code, rather). Or are they?

Variable instantiation is performed using the calling context's variable object and using empty property attributes. [ECMA-262 3rd ed. p 39]

This cryptic language means that variables declared in an eval call are to be added to the calling context's table of content. Ouch! How do you change at run-time what is supposedly fixed at compile time? Let's take some JavaScript code, execute that within all major browsers and see what they do.

var a=3;
function w(e,r)
{
  var c=2;
  e(r);
  return c+a;
}

I print the result of the following calls, followed by the value of a:

w(eval,"var a=5;")
w(eval,"c=1")
a

Note that w is just a intricate way of calling eval without the compiler or interpreter knowing. Here's the fun bit: All major Web browsers and their respective JavaScript engines produce different results.

Browser Result Comment
IE 8.0.6001.18702 7 4 3 The variable declaration in eval is performed within the context of w, hence hiding the global variable a. This is the correct reading of above specification.
Firefox 3.5.3 7 6 5 The variable declaration in eval overwrites the global variable (hence a equals 5 at the end). Bug!
Chrome 3.0.195.27 7 7 5 This is totally weird. What happened to the second call with c being set to 1? There appears to be a serious mixup of scopes. Or worse! Weird Bug!!

This explains everything. Apparently, even the demigods at Mozilla or Google don't know how to implement eval correctly. On the other hand, IE rocks! Albeit very slowly ...

Update

Well, it appears that the Firefox people do the right thing after all, albeit by taking the easy way out, that is to say, by implementing the ECMAScript standard's fifth edition. According to ECMA-262 5th ed.

indirect calls to the eval function use the global environment as both the variable environment and lexical environment for the eval code. In Edition 3, the variable and lexical environments of the caller of an indirect eval was used as the environments for the eval code.

That sounds much more reasonable, and is far easier to implement. Kudos to ECMA. Firefox now rocks, too, admittedly.