Skip to content

Commit

Permalink
perf: simplify DOM.compareDocumentPosition (xmldom#805)
Browse files Browse the repository at this point in the history
PR contributes a more efficient coding for the `compareDocumentPosition`
method contributed in PR xmldom#488
. In detail:

* Removes the `parentChain` method and replaces it with a parent chain
computation that immediately compares target nodes, thus avoiding
unnecessary computations.
* Uses `push` and `reverse` instead of `unshift` to assemble chains as
this is considerably faster.
  • Loading branch information
zorkow authored Dec 16, 2024
1 parent 83b01fc commit 8a371a5
Showing 1 changed file with 26 additions and 22 deletions.
48 changes: 26 additions & 22 deletions lib/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -257,23 +257,6 @@ var DocumentPosition = conventions.freeze({
});

//helper functions for compareDocumentPosition
/**
* Constructs a parent chain for a node.
*
* @param {Node} node
* The start node from which the parent chain will be constructed.
* @returns {Node[]}
* The array of nodes representing the parent chain from the root to the specified node.
*/
function parentChain(node) {
var chain = [];
while (node.parentNode || node.ownerElement) {
node = node.parentNode || node.ownerElement;
chain.unshift(node);
}
return chain;
}

/**
* Finds the common ancestor in two parent chains.
*
Expand Down Expand Up @@ -1476,15 +1459,36 @@ Node.prototype = {
: DocumentPosition.DOCUMENT_POSITION_PRECEDING)
);
}
var chain1 = parentChain(node1);
var chain2 = parentChain(node2);
if ((!attr1 && chain2.indexOf(node1) >= 0) || (attr2 && node1 === node2)) {
if (attr2 && node1 === node2) {
return DocumentPosition.DOCUMENT_POSITION_CONTAINS + DocumentPosition.DOCUMENT_POSITION_PRECEDING;
}
if ((!attr2 && chain1.indexOf(node2) >= 0) || (attr1 && node1 === node2)) {
if (attr1 && node1 === node2) {
return DocumentPosition.DOCUMENT_POSITION_CONTAINED_BY + DocumentPosition.DOCUMENT_POSITION_FOLLOWING;
}
var ca = commonAncestor(chain2, chain1);

var chain1 = [];
var ancestor1 = node1.parentNode;
while (ancestor1) {
if (!attr2 && ancestor1 === node2) {
return DocumentPosition.DOCUMENT_POSITION_CONTAINED_BY + DocumentPosition.DOCUMENT_POSITION_FOLLOWING;
}
chain1.push(ancestor1);
ancestor1 = ancestor1.parentNode;
}
chain1.reverse();

var chain2 = [];
var ancestor2 = node2.parentNode;
while (ancestor2) {
if (!attr1 && ancestor2 === node1) {
return DocumentPosition.DOCUMENT_POSITION_CONTAINS + DocumentPosition.DOCUMENT_POSITION_PRECEDING;
}
chain2.push(ancestor2);
ancestor2 = ancestor2.parentNode;
}
chain2.reverse();

var ca = commonAncestor(chain1, chain2);
for (var n in ca.childNodes) {
var child = ca.childNodes[n];
if (child === node2) return DocumentPosition.DOCUMENT_POSITION_FOLLOWING;
Expand Down

0 comments on commit 8a371a5

Please sign in to comment.