Webkit & localStorage: obscure bug

 
 
Tags:  | | |
 
 

I have just managed to work out a bug in webkit, or at least Chrome’s implementation of it. It was something that Tony bumped into in Mobile Apps, and he says that it affects all Webkit-based browsers. I claim no credit for working it out. Or maybe I do. I stumbled on the solution this morning because it seemed to be one of the few remaining possibilities. It seemed like this because I had a dim memory of coming across a similar bug in either Lingo or HyperTalk ten or more years ago.

The problem is simple. If you put a user choice into localStorage it does not persist in the way that the documentation suggests it should. You can easily see this by writing a simple page like this:

<html>
  <head>
    <title>Local Storage Test</title>
    <script>
      function storeThis(aName) {
        localStorage['name'] = aName;
        document.getElementById('output1').innerHTML=localStorage['name'];
      }
    </script>
  </head>
  <body>
    <p>The language is: <span id="output1">undecided</span>!</p>
    <p><a href="#" onclick="storeThis('English')">English</a></p>
    <p><a href="#" onclick="storeThis('Swedish')">Swedish</a></p>
    <p><a href="#" onclick="storeThis('Finnish')">Finnish</a></p>
  </body>
</html>

If you open the page and check with the developer tools you will see that the values are inserted correctly into localStorage when you click on the link. However every time that you refresh the page you will see that localStorage is wiped clean.

The answer is simple but far from obvious. It appears that you need to access localStorage at least once before Chrome feels any need to actually save it. Adding one short, and otherwise pointless, line to the script above fixes this:

    <script>
      function storeThis(aName) {
        localStorage['name'] = aName;
        document.getElementById('output1').innerHTML=localStorage['name'];
      }
      localStorage.getItem('name');
    </script>

The storage now persists as it should. Since I could find no documentation claiming that this is a feature of localStorage I am going to assume it is a bug.

A complete page

To demonstrate the persistence in action, I wrote this simple test page that saves the user’s choice to localStorage and then displays it both immediately and whenever the page is reloaded.

<html>
  <head>
    <title>Local Storage Test</title>
    <script>
      function storeThis(aName) {
        localStorage['name'] = aName;
        showLanguage();
      }
      function showLanguage() {
        document.getElementById('output1').innerHTML=localStorage['name'];
      }
      localStorage.getItem('name');
    </script>
  </head>
  <body onload="showLanguage()">
    <p>The language is: <span id="output1">undecided</span>!</p>
    <p><a href="#" onclick="storeThis('English')">English</a></p>
    <p><a href="#" onclick="storeThis('Swedish')">Swedish</a></p>
    <p><a href="#" onclick="storeThis('Finnish')">Finnish</a></p>
  </body>
</html>

 
 
Posted on December 14, 2012