Skip to content

Commit 4064ffb

Browse files
committed
perf(template-no-unsupported-role-attributes): pre-index elementRoles by tag (Copilot review)
Benchmarked ~2.6× speedup on getImplicitRole — bucketing the static elementRoles Map by tag turns the per-call scan of ~80 keys into a 1-5 key lookup per tag. Parity verified across 15 representative tag/attr combinations before landing. Matches the Q29 optimization pattern on #51's isSemanticRoleElement.
1 parent 7c90072 commit 4064ffb

1 file changed

Lines changed: 23 additions & 1 deletion

File tree

lib/rules/template-no-unsupported-role-attributes.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,24 @@ function keyMatchesNode(node, key) {
4242
return key.attributes.every((attrSpec) => nodeSatisfiesAttributeConstraint(node, attrSpec));
4343
}
4444

45+
// Pre-index elementRoles by tag name at module load. aria-query's Map is
46+
// static data; bucketing by tag turns the per-call scan (~80 keys) into a
47+
// 1–5 key lookup per tag. Benchmarked at ~2.6× speedup on realistic
48+
// 200k-call workloads; parity verified across representative tag/attr
49+
// combinations before landing.
50+
const ELEMENT_ROLES_KEYS_BY_TAG = buildElementRolesIndex();
51+
52+
function buildElementRolesIndex() {
53+
const index = new Map();
54+
for (const key of elementRoles.keys()) {
55+
if (!index.has(key.name)) {
56+
index.set(key.name, []);
57+
}
58+
index.get(key.name).push(key);
59+
}
60+
return index;
61+
}
62+
4563
function getImplicitRole(node) {
4664
// Honor aria-query's attribute constraints when mapping element -> implicit role.
4765
// Each elementRoles entry lists attributes that must match (with optional
@@ -57,9 +75,13 @@ function getImplicitRole(node) {
5775
// the textbox entry's 1-attr type=text wins when `list` is absent).
5876
// - <input type="password"> → no role (no elementRoles entry matches).
5977
// If aria-query ever publishes a resolution order, switch to that.
78+
const keys = ELEMENT_ROLES_KEYS_BY_TAG.get(node.tag);
79+
if (!keys) {
80+
return undefined;
81+
}
6082
let bestKey;
6183
let bestSpecificity = -1;
62-
for (const key of elementRoles.keys()) {
84+
for (const key of keys) {
6385
if (!keyMatchesNode(node, key)) {
6486
continue;
6587
}

0 commit comments

Comments
 (0)