DOMParser vs innerHTML vs createHTMLDocument (v5)

Revision 5 of this benchmark created on


Description

Tests

  • body + innerHTML
  • template + innerHTML
  • createHTMLDocument + innerHTML
  • DOMParser with text/html - https://developer.mozilla.org/en-US/docs/DOM/DOMParser

Using a string with a size of 100k <div>x</div>s, wrapped in a <body> element.

The last two methods involve creating an offline document (contrary to the firsy method, external resources such as <img> are not loaded).

No error checking is added. When this test case was created, Firefox (12+) was the only browser which supported all of the three methods. The first and second test should pass on all modern browsers though (the first on ancient browsers as well!).

Setup

/* 
         * DOMParser HTML extension 
         * 2012-02-02 
         * 
         * By Eli Grey, http://eligrey.com 
         * Public domain. 
         * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. 
         */  
    
        /*! @source https://gist.github.com/1129031 */  
        /*global document, DOMParser*/  
    
        (function(DOMParser) {  
            "use strict";  
            var DOMParser_proto = DOMParser.prototype  
              , real_parseFromString = DOMParser_proto.parseFromString;
    
            // Firefox/Opera/IE throw errors on unsupported types  
            try {  
                // WebKit returns null on unsupported types  
                if ((new DOMParser).parseFromString("", "text/html")) {  
                    // text/html parsing is natively supported  
                    return;  
                }  
            } catch (ex) {}  
    
            DOMParser_proto.parseFromString = function(markup, type) {  
                if (/^\s*text\/html\s*(?:;|$)/i.test(type)) {  
                    var doc = document.implementation.createHTMLDocument("")
                      , doc_elt = doc.documentElement
                      , first_elt;
    
                    doc_elt.innerHTML = markup;
                    first_elt = doc_elt.firstElementChild;
    
                    if (doc_elt.childElementCount === 1
                        && first_elt.localName.toLowerCase() === "html") {  
                        doc.replaceChild(first_elt, doc_elt);  
                    }  
    
                    return doc;  
                } else {  
                    return real_parseFromString.apply(this, arguments);  
                }  
            };  
        }(DOMParser));
    
    var testString = '<body>' + Array(50).join('<div>x</div>') + '</body>';
    
    function test_innerHTML() {
        var b = document.createElement('body');
        b.innerHTML = testString;
        return b;
    }
    function test_template() {
        var b = document.createElement('template');
        b.innerHTML = testString;
        return b.content;
    }
    function test_createHTMLDocument() {
        var d = document.implementation.createHTMLDocument('');
        d.body.innerHTML = testString;
        return d.body;
    }
    function test_DOMParser() {
        return (new DOMParser).parseFromString(testString, 'text/html').body;
    }

Test runner

Ready to run.

Testing in
TestOps/sec
body+innerHTML
test_innerHTML();
ready
createHTMLDocument
test_createHTMLDocument();
ready
DOMParser+text/html
test_DOMParser();
ready
template+innerHTML
test_template();
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.