Safari Javascript bug

Recently we found that our Lab framework caused the JavascriptCore of Safari 5.1 to crash. Safari 5.1 is the latest version available for OS X 10.6. If you have OS X 10.7 or 10.8, then you have Safari 6 which doesn’t have this problem.

Too long; didn’t read solution: do not name your getters the same as your closure variables.

After at lot of detective work I figured out what the problem was. A block of code like this was causing it:

function testObject(){
  var myProperty = "hello";
  return {
    get myProperty() {
      return myProperty;
    }
  }
}
var myObject = testObject();
console.log(myObject.myProperty);

Here is a fiddle of the same code.

If you run that fiddle in Safari 5.1 You will see an reference error to myProperty. Note: you need to make sure script debugging is disabled. If script debugging is enabled then this problem doesn’t occur. That block of code is using a Javascript getter. If you are not familiar with Javascript getters and setters, this post by John Resig is a great place to start.

If the closure variable name is changed to _myProperty like this:

function testObject(){
  var _myProperty = "hello";
  return {
    get myProperty() {
      return _myProperty;
    }
  }
}
var myObject = testObject();
console.log(myObject.myProperty);

Then it works! So there is an issue with Safari when a getter has the same name as the variable in the outer closure. This didn’t make sense though. We use this pattern of a getter accessing a variable of the same name throughout much of our code. Those parts of the code worked fine. After more exploration I found the following block of code works fine in Safari 5.1:

function testObject(){
  var myProperty = "hello";
  return {
    get myProperty() {
      return myProperty;
    },
    methodUsingMyProperty: function () {
      return myProperty;
    }
  };
}
var myObject = testObject();
console.log(myObject.myProperty);

Here is a fiddle of the same code.

This code is using the closure variable in another method that is part of the return object. Based on this, I believe the problem is that Safari is failing to keep the closure variable available when it has the same name as the getter and is only referenced by that getter. I assume it is common for browsers to try to optimize closures by discarding variables that aren’t used. So it seems the code analysis done by Safari to see if a variable is used, is failing to mark a variable as being used when it is in a getter with the same name.

I have submitted a bug to Apple about this. Their bug tracker is private though, so there is no way for you to see that bug.

So to summarize, you should not name your getters the same as your closure variables.