jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/386009 )

Change subject: Remove unnecessary calls to Node#childNodes
......................................................................


Remove unnecessary calls to Node#childNodes

These calls force us to allocate a backing array for childNodes,
deoptimizing a linked list DOM representation.  Iterate over the
children using Node#firstChild / Node#nextSibling instead, which
can be efficiently done w/o allocating a backing array.

Change-Id: Ibed52d3d82a7fc54796d7ef6f1cf771a6f48b974
---
M lib/utils/DOMUtils.js
M lib/wt2html/XMLSerializer.js
M lib/wt2html/pp/processors/computeDSR.js
M lib/wt2html/pp/processors/handlePres.js
4 files changed, 20 insertions(+), 30 deletions(-)

Approvals:
  Subramanya Sastry: Looks good to me, approved
  Legoktm: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/lib/utils/DOMUtils.js b/lib/utils/DOMUtils.js
index c9cd9fb..dc221ce 100644
--- a/lib/utils/DOMUtils.js
+++ b/lib/utils/DOMUtils.js
@@ -815,9 +815,8 @@
         * Check whether a node has any children that are elements.
         */
        hasElementChild: function(node) {
-               var children = node.childNodes;
-               for (var i = 0, n = children.length; i < n; i++) {
-                       if (DU.isElt(children[i])) {
+               for (var child = node.firstChild; child; child = 
child.nextSibling) {
+                       if (DU.isElt(child)) {
                                return true;
                        }
                }
@@ -829,9 +828,7 @@
         * Check if a node has a block-level element descendant.
         */
        hasBlockElementDescendant: function(node) {
-               var children = node.childNodes;
-               for (var i = 0, n = children.length; i < n; i++) {
-                       var child = children[i];
+               for (var child = node.firstChild; child; child = 
child.nextSibling) {
                        if (DU.isElt(child) &&
                                        // Is a block-level node
                                        (this.isBlockNode(child) ||
@@ -997,15 +994,14 @@
                switch (node.nodeType) {
                        case node.ELEMENT_NODE:
                                var nodeName = node.nodeName.toLowerCase();
-                               var children = node.childNodes;
                                var attrInfo = 
domAttrsToTagAttrs(node.attributes);
 
                                if (Util.isVoidElement(nodeName)) {
                                        tokBuf.push(new 
pd.SelfclosingTagTk(nodeName, attrInfo.attrs, attrInfo.dataAttrs));
                                } else {
                                        tokBuf.push(new pd.TagTk(nodeName, 
attrInfo.attrs, attrInfo.dataAttrs));
-                                       for (var i = 0, n = children.length; i 
< n; i++) {
-                                               tokBuf = 
this.convertDOMtoTokens(tokBuf, children[i]);
+                                       for (var child = node.firstChild; 
child; child = child.nextSibling) {
+                                               tokBuf = 
this.convertDOMtoTokens(tokBuf, child);
                                        }
                                        var endTag = new pd.EndTagTk(nodeName);
                                        // Keep stx parity
@@ -1966,15 +1962,16 @@
         *    See encapsulateExpansionHTML's doc. for more info about these 
options.
         */
        buildDOMFragmentTokens: function(env, token, docOrHTML, addAttrsCB, 
opts) {
-               var body;
+               var body, nodes;
                if (docOrHTML.constructor === String) {
                        body = DU.ppToDOM(docOrHTML);
                } else {
                        body = docOrHTML.body;
                }
 
-               var nodes = body.childNodes;
-               if (nodes.length === 0) {
+               if (body.hasChildNodes()) {
+                       nodes = body.childNodes;
+               } else {
                        // RT extensions expanding to nothing.
                        nodes = [body.ownerDocument.createElement('link')];
                }
diff --git a/lib/wt2html/XMLSerializer.js b/lib/wt2html/XMLSerializer.js
index a1b1864..2c2a993 100644
--- a/lib/wt2html/XMLSerializer.js
+++ b/lib/wt2html/XMLSerializer.js
@@ -238,9 +238,8 @@
        var accum = options.captureOffsets ?
                accumOffsets.bind(null, out) : function(bit) { out.str += bit; 
};
        if (options.innerXML) {
-               var children = node.childNodes;
-               for (var i = 0; i < children.length; i++) {
-                       serializeToString(children[i], options, accum);
+               for (var child = node.firstChild; child; child = 
child.nextSibling) {
+                       serializeToString(child, options, accum);
                }
        } else {
                serializeToString(node, options, accum);
diff --git a/lib/wt2html/pp/processors/computeDSR.js 
b/lib/wt2html/pp/processors/computeDSR.js
index bbb4af2..716909f 100644
--- a/lib/wt2html/pp/processors/computeDSR.js
+++ b/lib/wt2html/pp/processors/computeDSR.js
@@ -173,9 +173,6 @@
                });
        }
 
-       var children = node.childNodes;
-       var numChildren = children.length;
-
        // No undefined values here onwards.
        // NOTE: Never use !s, !e, !cs, !ce for testing for non-null
        // because any of them could be zero.
@@ -187,7 +184,7 @@
                e = null;
        }
 
-       if (e === null && numChildren === 0) {
+       if (e === null && !node.hasChildNodes()) {
                e = s;
        }
 
@@ -204,7 +201,6 @@
        var rtTestMode = env.conf.parsoid.rtTestMode;
 
        var child = node.lastChild;
-       var i = numChildren - 1;
        while (child !== null) {
                var prevChild = child.previousSibling;
                var isMarkerTag = false;
@@ -244,6 +240,7 @@
                }
 
                env.log("trace/dsr", function() {
+                       var i = child.parentNode.childNodes.indexOf(child); // 
slow, for debugging only
                        return "     CHILD: <" + child.parentNode.nodeName + 
":" + i +
                                ">=" +
                                (DU.isElt(child) ? '' : (DU.isText(child) ? '#' 
: '!')) +
@@ -608,12 +605,10 @@
                                node.replaceChild(newNode, prevChild);
                                node.removeChild(nextChild);
                                prevChild = newNode.previousSibling;
-                               i--;
                        }
                        node.removeChild(child);
                }
 
-               i--;
                child = prevChild;
        }
 
diff --git a/lib/wt2html/pp/processors/handlePres.js 
b/lib/wt2html/pp/processors/handlePres.js
index 64f67b1..d5668d5 100644
--- a/lib/wt2html/pp/processors/handlePres.js
+++ b/lib/wt2html/pp/processors/handlePres.js
@@ -12,14 +12,13 @@
 }
 
 function reinsertLeadingSpace(elt, isLastChild) {
-       var children = elt.childNodes;
-       for (var i = 0, n = children.length; i < n; i++) {
-               var c = children[i];
+       for (var c = elt.firstChild; c; c = c.nextSibling) {
+               var last = (c.nextSibling === null);
                if (DU.isText(c)) {
-                       c.data = fixedIndentPreText(c.data, isLastChild && i 
=== n - 1);
+                       c.data = fixedIndentPreText(c.data, isLastChild && 
last);
                } else {
                        // recurse
-                       reinsertLeadingSpace(c, isLastChild && i === n - 1);
+                       reinsertLeadingSpace(c, isLastChild && last);
                }
        }
 }
@@ -85,11 +84,11 @@
        }
 
        function findAndHandlePres(elt, indentPresHandled) {
-               var children = elt.childNodes;
+               var nextChild;
                var blocklevel = false;
-               for (var i = 0; i < children.length; i++) {
+               for (var n = elt.firstChild; n; n = nextChild) {
                        var processed = false;
-                       var n = children[i];
+                       nextChild = n.nextSibling; // store this before n is 
possibly deleted
                        if (!indentPresHandled && DU.isElt(n) &&
                                        Util.tagOpensBlockScope(n.nodeName) &&
                                        
(DU.isTplMetaType(n.getAttribute("typeof")) ||

-- 
To view, visit https://gerrit.wikimedia.org/r/386009
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ibed52d3d82a7fc54796d7ef6f1cf771a6f48b974
Gerrit-PatchSet: 5
Gerrit-Project: mediawiki/services/parsoid
Gerrit-Branch: master
Gerrit-Owner: C. Scott Ananian <canan...@wikimedia.org>
Gerrit-Reviewer: Arlolra <abrea...@wikimedia.org>
Gerrit-Reviewer: C. Scott Ananian <canan...@wikimedia.org>
Gerrit-Reviewer: Legoktm <lego...@member.fsf.org>
Gerrit-Reviewer: Sbailey <sbai...@wikimedia.org>
Gerrit-Reviewer: Subramanya Sastry <ssas...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to