Skip to content

Commit 3e372e9

Browse files
botandrose-machinebotandrose
authored andcommitted
it turns out that Element.contains is really slow, so big perf win by precomputing the active element parent path and doing an array inclusion check instead.
1 parent 87b84db commit 3e372e9

File tree

1 file changed

+19
-1
lines changed

1 file changed

+19
-1
lines changed

src/idiomorph.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ var Idiomorph = (function () {
112112
* @property {ConfigInternal['callbacks']} callbacks
113113
* @property {ConfigInternal['head']} head
114114
* @property {HTMLDivElement} pantry
115+
* @property {Element[]} activeElementAndParents
115116
*/
116117

117118
//=============================================================================
@@ -433,7 +434,8 @@ var Idiomorph = (function () {
433434

434435
// if the current node contains active element, stop looking for better future matches,
435436
// because if one is found, this node will be moved to the pantry, reparenting it and thus losing focus
436-
if (cursor.contains(document.activeElement)) break;
437+
// @ts-ignore pretend cursor is Element rather than Node, we're just testing for array inclusion
438+
if (ctx.activeElementAndParents.includes(cursor)) break;
437439

438440
cursor = cursor.nextSibling;
439441
}
@@ -1010,6 +1012,7 @@ var Idiomorph = (function () {
10101012
idMap: idMap,
10111013
persistentIds: persistentIds,
10121014
pantry: createPantry(),
1015+
activeElementAndParents: createActiveElementAndParents(oldNode),
10131016
callbacks: mergedConfig.callbacks,
10141017
head: mergedConfig.head,
10151018
};
@@ -1050,6 +1053,21 @@ var Idiomorph = (function () {
10501053
return pantry;
10511054
}
10521055

1056+
/**
1057+
* @param {Element} oldNode
1058+
* @returns {Element[]}
1059+
*/
1060+
function createActiveElementAndParents(oldNode) {
1061+
/** @type {Element[]} */
1062+
let activeElementAndParents = [];
1063+
let elt = document.activeElement;
1064+
while (elt && elt !== oldNode) {
1065+
activeElementAndParents.push(elt);
1066+
elt = elt.parentElement;
1067+
}
1068+
return activeElementAndParents;
1069+
}
1070+
10531071
/**
10541072
* Returns all elements with an ID contained within the root element and its descendants
10551073
*

0 commit comments

Comments
 (0)