Posts Tagged ‘DOM’

One Bug to Rule Them All

Friday, July 17th, 2009

Just read an interesting article about a buffer overflow bug dealing with the select method. Interestingly, the proof of concept choose the max signed 32-bit integer of 2147483647 to cause the bug. This does indeed crash IE8, but does not crash FF3.5. I didn’t personally test any other browser. What’s even more interesting about this though is that this shouldn’t overflow in JS, as all numbers in JS are internally represented as 64-bit floats. Moreover, even if JS had a 32-bit integer number that number shouldn’t overflow at all. Given that the bug deals with the select element, my suspicion is that it is a DOM related issue that is being misrepresented as an ECMA script related issue.

Internet Explorer, Tables, the DOM, and what not to do…

Saturday, March 14th, 2009

A post on reddit a few weeks ago finally inticed me enough to sign up for an account on the popular social link sharing site. The post was at a blog by Eric Vasilik (who supposedly had something to do with making IE a horrible platform to develop for) that dealt with having to insert the new rows into an existing table. Intuitively, most coders would just use the .innerHTML property and go about their day until they later test their code in IE and then everything explodes because IE doesn’t play nice when it comes to tables and .innerHTML. Especially when inserting new rows. What really irked me about the whole thing though was the way Mr. Vasilik was going about solving his problem.

For reasons beyond me Mr. Vasilik decided that it would be best to not just use the DOM methods and insert rows in that manner. Instead Eric wrapped his newly created HTML for table rows inside of <table> and <tbody> tags, put them into a hidden element on the page, and then looped over rows in the currently visible table calling the replaceChild method on the table in order to swap out the rows. This solution does, in fact swap out all of the rows. Unfortunately it is painfully slow.  Having to use the DOM alone for this is already significantly slower than using innerHTML (but IE makes this impossible, at least for versions 7 and lower) but using both innerHTML and the DOM is even slower than that. Instead of creating the table rows as strings Mr. Vasilik should have JSON encoded the tables so that he would’ve had them as objects after a quick eval or if he had to create them in the code then he should’ve used the DOM to create the objects and used insertRow, insertCell, etc. on the table object instead of using the least efficient approach he could think of.

I ended up writing a few speed tests to test innerHTML, DOM, DOM/appendChild, and DOM/innerHTML/replaceChild which can be found here (needs Firebug to run).  Not surprisingly, using innerHTML to create a new table, then calling replaceChild to swap table rows was the slowest of the tests. Full code below:

(function()

{

var table = document.getElementById(‘test’);

var tr, td;
<pre id="line1">  console.time("DOM Manipulation");
  for(var i = 0; i &lt; 1000; i++)
  {
      tr = table.insertRow(-1);
      td = tr.insertCell(-1);
      td.innerHTML = "Test";
  }
  console.timeEnd("DOM Manipulation");
  table.innerHTML = "";
  console.time("innerHTML");
  var rows = "";
  for(var i = 0; i &lt; 1000; i++)
  {
     rows += "&lt;tr&gt;&lt;td&gt;test&lt;/td&gt;&lt;/tr&gt;";
  }
  table.innerHTML = rows;
  console.timeEnd("innerHTML");
  table.innerHTML = "";
  console.time("DOM, appendChild");
  for(var i = 0; i &lt; 1000; i++)
  {
    tr = document.createElement("TR");
    td = document.createElement("TD");
    td.innerHTML = "Test";
    tr.appendChild(td);
    table.appendChild(tr);
  }

  console.timeEnd("DOM, appendChild");
  rows = "&lt;table id=’test2′&gt;";
  console.time("DOM, span, replaceChild");
  for(var i = 0; i &lt; 1000; i++)
  {
    rows += "&lt;tr&gt;&lt;td&gt;test DOM, span, replaceChild&lt;/td&gt;&lt;/tr&gt;";
  }
  rows += "&lt;/table&gt;";

  var spanTemp = document.getElementById("temp");
  spanTemp.innerHTML = rows;
  var varTempTableRows = spanTemp.getElementsByTagName("table")[0].getElementsByTagName("TR");
  for(var i = 0; i &lt; varTempTableRows.length; i++)
  {
     table.replaceChild(varTempTableRows[i], table.childNodes[i]);
  }
  console.timeEnd("DOM, span, replaceChild");
})();

UPDATE: Seems like this completely changed in FF3.5 and using innerHTML is significantly faster than any of the previous methods.