-
Notifications
You must be signed in to change notification settings - Fork 776
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(performance): significantly improve the performance of the dom.fi… #699
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,54 @@ | ||
/* global dom, axe */ | ||
/** | ||
* recusively walk up the DOM, checking for a node which matches a selector | ||
* Find the virtual node and call dom.fundUpVirtual | ||
* | ||
* **WARNING:** this should be used sparingly, as it's not even close to being performant | ||
* @method findUp | ||
* @memberof axe.commons.dom | ||
* @instance | ||
* @param {HTMLElement|String} element The starting HTMLElement | ||
* @param {HTMLElement} element The starting HTMLElement | ||
* @param {String} target The selector for the HTMLElement | ||
* @return {HTMLElement|null} Either the matching HTMLElement or `null` if there was no match | ||
*/ | ||
dom.findUp = function (element, target) { | ||
let doc, matches, | ||
parent = element; | ||
return dom.findUpVirtual(axe.utils.getNodeFromTree(axe._tree[0], element), target); | ||
}; | ||
|
||
/** | ||
* recusively walk up the DOM, checking for a node which matches a selector | ||
* | ||
* **WARNING:** this should be used sparingly, as it's not even close to being performant | ||
* @method findUpVirtual | ||
* @memberof axe.commons.dom | ||
* @instance | ||
* @param {VirtualNode} element The starting virtualNode | ||
* @param {String} target The selector for the HTMLElement | ||
* @return {HTMLElement|null} Either the matching HTMLElement or `null` if there was no match | ||
*/ | ||
dom.findUpVirtual = function (element, target) { | ||
let parent; | ||
|
||
parent = element.actualNode; | ||
// virtualNode will have a shadowId if the element lives inside a shadow DOM or is | ||
// slotted into a shadow DOM | ||
if (!element.shadowId && typeof element.actualNode.closest === 'function') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Am I correct in assuming that any virtual node with a truthy shadowId is somewhere inside a shadow tree, either because it is a shadow element or because it's slotted somewhere? Please add a comment to clear that up. |
||
// non-shadow DOM elements | ||
let match = element.actualNode.closest(target); | ||
if (match) { | ||
return match; | ||
} | ||
return null; | ||
} | ||
// handle shadow DOM elements and older browsers | ||
do {// recursively walk up the DOM, checking each parent node | ||
parent = (parent.assignedSlot ? parent.assignedSlot : parent.parentNode); | ||
if (parent && parent.nodeType === 11) { | ||
matches = null; | ||
parent = parent.host; | ||
} | ||
if (!matches) { | ||
doc = axe.commons.dom.getRootNode(parent); | ||
matches = doc.querySelectorAll(target); | ||
matches = axe.utils.toArray(matches); | ||
if (doc === document && !matches.length) { | ||
return null; | ||
} | ||
} | ||
} while (parent && !matches.includes(parent)); | ||
} while (parent && !axe.utils.matchesSelector(parent, target) && parent !== document.documentElement); | ||
|
||
if (!axe.utils.matchesSelector(parent, target)) { | ||
return null; | ||
} | ||
return parent; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,14 +19,14 @@ var phrasingElements = ['A', 'EM', 'STRONG', 'SMALL', 'MARK', 'ABBR', 'DFN', 'I' | |
* @param {HTMLElement} element The HTMLElement | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These docs look out-of-date. |
||
* @return {HTMLElement} The label element, or null if none is found | ||
*/ | ||
function findLabel({ actualNode }) { | ||
function findLabel(virtualNode) { | ||
let label; | ||
if (actualNode.id) { | ||
if (virtualNode.actualNode.id) { | ||
label = dom.findElmsInContext({ | ||
elm: 'label', attr: 'for', value: actualNode.id, context: actualNode | ||
elm: 'label', attr: 'for', value: virtualNode.actualNode.id, context: virtualNode.actualNode | ||
})[0]; | ||
} else { | ||
label = dom.findUp(actualNode, 'label'); | ||
label = dom.findUpVirtual(virtualNode, 'label'); | ||
} | ||
return axe.utils.getNodeFromTree(axe._tree[0], label); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may also add a note here on turning up the iframe timeout option with very large iframes.