- commit
- 50c2d3fcb29dc090987b6307c2708a86fb288a37
- parent
- f2d0aeb3c33b18dd77b9d66160154997687a7180
- Author
- Tobias Bengfort <tobias.bengfort@posteo.de>
- Date
- 2026-02-18 21:33
shadow-dom: use getRootNode() instead of document This also means we can longer globally query for owners. From my testing the performance impact is not too bad.
Diffstat
| M | lib/atree.js | 43 | +++++++++++++++++-------------------------- |
| M | lib/name.js | 4 | ++-- |
2 files changed, 19 insertions, 28 deletions
diff --git a/lib/atree.js b/lib/atree.js
@@ -1,27 +1,19 @@ 1 1 import * as attrs from './attrs'; 2 23 -1 const _getOwner = function(node, owners) {-1 3 const _getOwner = function(node) { 4 4 if (node.nodeType === node.ELEMENT_NODE && node.id) {5 -1 const selector = '[aria-owns~="' + CSS.escape(node.id) + '"]';6 -1 if (owners) {7 -1 for (const owner of owners) {8 -1 if (owner.matches(selector)) {9 -1 return owner;10 -1 }11 -1 }12 -1 } else {13 -1 return document.querySelector(selector);14 -1 }-1 5 const selector = `[aria-owns~="${CSS.escape(node.id)}"]`; -1 6 return node.getRootNode().querySelector(selector); 15 7 } 16 8 }; 17 918 -1 const _getParentNode = function(node, owners) {19 -1 return _getOwner(node, owners) || node.parentNode;-1 10 const _getParentNode = function(node) { -1 11 return _getOwner(node) || node.parentNode; 20 12 }; 21 1322 -1 const detectLoop = function(node, owners) {-1 14 const detectLoop = function(node) { 23 15 const seen = [node];24 -1 while ((node = _getParentNode(node, owners))) {-1 16 while ((node = _getParentNode(node))) { 25 17 if (seen.includes(node)) { 26 18 return true; 27 19 } @@ -29,27 +21,27 @@ const detectLoop = function(node, owners) { 29 21 } 30 22 }; 31 2332 -1 const getOwner = function(node, owners) {33 -1 const owner = _getOwner(node, owners);34 -1 if (owner && !detectLoop(node, owners)) {-1 24 const getOwner = function(node) { -1 25 const owner = _getOwner(node); -1 26 if (owner && !detectLoop(node)) { 35 27 return owner; 36 28 } 37 29 }; 38 3039 -1 export const getParentNode = function(node, owners) {40 -1 return getOwner(node, owners) || node.parentNode;-1 31 export const getParentNode = function(node) { -1 32 return getOwner(node) || node.parentNode; 41 33 }; 42 34 43 35 const isHidden = function(node) { 44 36 return node.nodeType === node.ELEMENT_NODE && attrs.getAttribute(node, 'hidden'); 45 37 }; 46 3847 -1 export const getChildNodes = function(node, owners) {-1 39 export const getChildNodes = function(node) { 48 40 const childNodes = []; 49 41 50 42 for (let i = 0; i < node.childNodes.length; i++) { 51 43 const child = node.childNodes[i];52 -1 if (!getOwner(child, owners) && !isHidden(child)) {-1 44 if (!getOwner(child) && !isHidden(child)) { 53 45 childNodes.push(child); 54 46 } 55 47 } @@ -57,9 +49,9 @@ export const getChildNodes = function(node, owners) { 57 49 if (node.nodeType === node.ELEMENT_NODE) { 58 50 const owns = attrs.getAttribute(node, 'owns') || []; 59 51 for (let i = 0; i < owns.length; i++) {60 -1 const child = document.getElementById(owns[i]);-1 52 const child = node.getRootNode().getElementById(owns[i]); 61 53 // double check with getOwner for consistency62 -1 if (child && getOwner(child, owners) === node && !isHidden(child)) {-1 54 if (child && getOwner(child) === node && !isHidden(child)) { 63 55 childNodes.push(child); 64 56 } 65 57 } @@ -69,12 +61,11 @@ export const getChildNodes = function(node, owners) { 69 61 }; 70 62 71 63 export const walk = function(root, fn) {72 -1 const owners = document.querySelectorAll('[aria-owns]');73 64 let queue = [root]; 74 65 while (queue.length) { 75 66 const item = queue.shift(); 76 67 fn(item);77 -1 queue = getChildNodes(item, owners).concat(queue);-1 68 queue = getChildNodes(item).concat(queue); 78 69 } 79 70 }; 80 71
diff --git a/lib/name.js b/lib/name.js
@@ -94,7 +94,7 @@ const getNameRaw = function(el, recursive, ongoingLabelledBy, visited, directRef 94 94 if (!ongoingLabelledBy && el.matches('[aria-labelledby]')) { 95 95 const ids = el.getAttribute('aria-labelledby').split(/\s+/); 96 96 const strings = ids.map(id => {97 -1 const label = document.getElementById(id);-1 97 const label = el.getRootNode().getElementById(id); 98 98 return label ? getNameRaw(label, true, true, visited, true) : ''; 99 99 }); 100 100 ret = strings.join(' '); @@ -205,7 +205,7 @@ export const getDescription = function(el) { 205 205 if (el.matches('[aria-describedby]')) { 206 206 const ids = el.getAttribute('aria-describedby').split(/\s+/); 207 207 const strings = ids.map(id => {208 -1 const label = document.getElementById(id);-1 208 const label = el.getRootNode().getElementById(id); 209 209 return label ? getNameRaw(label, true, true) : ''; 210 210 }); 211 211 ret = strings.join(' ');