forked from dequelabs/axe-core
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathget-element-internals.js
More file actions
73 lines (65 loc) · 2.17 KB
/
Copy pathget-element-internals.js
File metadata and controls
73 lines (65 loc) · 2.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import isValidCustomElementName from './is-valid-custom-element-name';
/**
* community protocols that axe-core supports to find element internals:
* - globalThis._elementInternals.get(node)
* - node._internals (recommended)
* - node.internals
* - node.internals_
* - node[Symbol('internals')]
* - node[Symbol('privateInternals')]
**/
const propNames = ['_internals', 'internals', 'internals_'];
const symbolNames = ['internals', 'privateInternals'];
/**
* Get the ElementInternals object for a custom element using a community protocol.
* @example
* // use the global map
* const internals = node.attachInternals()
* globalThis._elementInternals ??= new WeakMap();
* globalThis._elementInternals.set(node, internals);
* @example
* // set property
* const internals = node.attachInternals()
* node._internals = internals;
* @param {HTMLElement} node
* @return {ElementInternals|undefined}
*/
export default function getElementInternals(node) {
// internals can only be attached to custom-elements
// trying to do otherwise results in an error "Cannot attach ElementInternals to a customized built-in or non-custom element"
if (!isValidCustomElementName(node.nodeName.toLowerCase())) {
return;
}
// support finding internals from an optional global map. we assume that if a node is set here the value will be an ElementInternals object
const mapInternals = globalThis._elementInternals?.get(node);
if (mapInternals) {
return mapInternals;
}
// ie11 guard
if (!('ElementInternals' in window)) {
return;
}
for (const propName of propNames) {
if (Object.getOwnPropertyDescriptor(node, propName)?.get) {
continue;
}
if (node[propName] instanceof window.ElementInternals) {
return node[propName];
}
}
const ownSymbols = Object.getOwnPropertySymbols(node);
if (!ownSymbols.length) {
return;
}
for (const symbolName of symbolNames) {
const symbol = ownSymbols.find(s => s.description === symbolName);
if (symbol) {
if (Object.getOwnPropertyDescriptor(node, symbol)?.get) {
continue;
}
if (node[symbol] instanceof window.ElementInternals) {
return node[symbol];
}
}
}
}