Skip to content

Commit 67bd7aa

Browse files
committed
refactor(linter): add AriaProperty enum (#10325)
Replaces ARIA strings everywhere with an enum that represents all ARIA properties in a single byte. This should allow us to store this more efficiently in memory and also reduce the executable size.
1 parent dfef8b5 commit 67bd7aa

File tree

3 files changed

+1343
-1134
lines changed

3 files changed

+1343
-1134
lines changed

crates/oxc_linter/src/globals.rs

Lines changed: 176 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -12,58 +12,182 @@ pub const RESERVED_HTML_TAG: [&str; 16] = [
1212
"picture", "script", "source", "style", "title", "track",
1313
];
1414

15-
/// set of valid ARIA properties from the WAI-ARIA 1.1 specifications.
16-
/// Reference: <https://www.w3.org/TR/wai-aria/#state_prop_def>
17-
pub const VALID_ARIA_PROPS: phf::Set<&'static str> = phf_set! {
18-
"aria-activedescendant",
19-
"aria-atomic",
20-
"aria-autocomplete",
21-
"aria-busy",
22-
"aria-checked",
23-
"aria-colcount",
24-
"aria-colindex",
25-
"aria-colspan",
26-
"aria-controls",
27-
"aria-current",
28-
"aria-describedby",
29-
"aria-details",
30-
"aria-disabled",
31-
"aria-dropeffect",
32-
"aria-errormessage",
33-
"aria-expanded",
34-
"aria-flowto",
35-
"aria-grabbed",
36-
"aria-haspopup",
37-
"aria-hidden",
38-
"aria-invalid",
39-
"aria-keyshortcuts",
40-
"aria-label",
41-
"aria-labelledby",
42-
"aria-level",
43-
"aria-live",
44-
"aria-modal",
45-
"aria-multiline",
46-
"aria-multiselectable",
47-
"aria-orientation",
48-
"aria-owns",
49-
"aria-placeholder",
50-
"aria-posinset",
51-
"aria-pressed",
52-
"aria-readonly",
53-
"aria-relevant",
54-
"aria-required",
55-
"aria-roledescription",
56-
"aria-rowcount",
57-
"aria-rowindex",
58-
"aria-rowspan",
59-
"aria-selected",
60-
"aria-setsize",
61-
"aria-sort",
62-
"aria-valuemax",
63-
"aria-valuemin",
64-
"aria-valuenow",
65-
"aria-valuetext"
66-
};
15+
const ARIA_ACTIVEDESCENDANT: &str = "aria-activedescendant";
16+
const ARIA_ATOMIC: &str = "aria-atomic";
17+
const ARIA_AUTOCOMPLETE: &str = "aria-autocomplete";
18+
const ARIA_BUSY: &str = "aria-busy";
19+
const ARIA_BRAILLELABEL: &str = "aria-braillelabel";
20+
const ARIA_BRAILLEROLEDESCRIPTION: &str = "aria-brailleroledescription";
21+
const ARIA_CHECKED: &str = "aria-checked";
22+
const ARIA_COLCOUNT: &str = "aria-colcount";
23+
const ARIA_COLINDEX: &str = "aria-colindex";
24+
const ARIA_COLSPAN: &str = "aria-colspan";
25+
const ARIA_CONTROLS: &str = "aria-controls";
26+
const ARIA_CURRENT: &str = "aria-current";
27+
const ARIA_DESCRIBEDBY: &str = "aria-describedby";
28+
const ARIA_DESCRIPTION: &str = "aria-description";
29+
const ARIA_DETAILS: &str = "aria-details";
30+
const ARIA_DISABLED: &str = "aria-disabled";
31+
const ARIA_DROPEFFECT: &str = "aria-dropeffect";
32+
const ARIA_ERRORMESSAGE: &str = "aria-errormessage";
33+
const ARIA_EXPANDED: &str = "aria-expanded";
34+
const ARIA_FLOWTO: &str = "aria-flowto";
35+
const ARIA_GRABBED: &str = "aria-grabbed";
36+
const ARIA_HASPOPUP: &str = "aria-haspopup";
37+
const ARIA_HIDDEN: &str = "aria-hidden";
38+
const ARIA_INVALID: &str = "aria-invalid";
39+
const ARIA_KEYSHORTCUTS: &str = "aria-keyshortcuts";
40+
const ARIA_LABEL: &str = "aria-label";
41+
const ARIA_LABELLEDBY: &str = "aria-labelledby";
42+
const ARIA_LEVEL: &str = "aria-level";
43+
const ARIA_LIVE: &str = "aria-live";
44+
const ARIA_MODAL: &str = "aria-modal";
45+
const ARIA_MULTILINE: &str = "aria-multiline";
46+
const ARIA_MULTISELECTABLE: &str = "aria-multiselectable";
47+
const ARIA_ORIENTATION: &str = "aria-orientation";
48+
const ARIA_OWNS: &str = "aria-owns";
49+
const ARIA_PLACEHOLDER: &str = "aria-placeholder";
50+
const ARIA_POSINSET: &str = "aria-posinset";
51+
const ARIA_PRESSED: &str = "aria-pressed";
52+
const ARIA_READONLY: &str = "aria-readonly";
53+
const ARIA_RELEVANT: &str = "aria-relevant";
54+
const ARIA_REQUIRED: &str = "aria-required";
55+
const ARIA_ROLEDESCRIPTION: &str = "aria-roledescription";
56+
const ARIA_ROWCOUNT: &str = "aria-rowcount";
57+
const ARIA_ROWINDEX: &str = "aria-rowindex";
58+
const ARIA_ROWSPAN: &str = "aria-rowspan";
59+
const ARIA_SELECTED: &str = "aria-selected";
60+
const ARIA_SETSIZE: &str = "aria-setsize";
61+
const ARIA_SORT: &str = "aria-sort";
62+
const ARIA_VALUEMAX: &str = "aria-valuemax";
63+
const ARIA_VALUEMIN: &str = "aria-valuemin";
64+
const ARIA_VALUENOW: &str = "aria-valuenow";
65+
const ARIA_VALUETEXT: &str = "aria-valuetext";
66+
67+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68+
pub enum AriaProperty {
69+
ActiveDescendant,
70+
Atomic,
71+
AutoComplete,
72+
Busy,
73+
BrailleLabel,
74+
BrailleRoleDescription,
75+
Checked,
76+
ColCount,
77+
ColIndex,
78+
ColSpan,
79+
Controls,
80+
Current,
81+
DescribedBy,
82+
Description,
83+
Details,
84+
Disabled,
85+
DropEffect,
86+
ErrorMessage,
87+
Expanded,
88+
FlowTo,
89+
Grabbed,
90+
HasPopup,
91+
Hidden,
92+
Invalid,
93+
KeyShortcuts,
94+
Label,
95+
LabelledBy,
96+
Level,
97+
Live,
98+
Modal,
99+
Multiline,
100+
Multiselectable,
101+
Orientation,
102+
Owns,
103+
Placeholder,
104+
PosInSet,
105+
Pressed,
106+
Readonly,
107+
Relevant,
108+
Required,
109+
RoleDescription,
110+
RowCount,
111+
RowIndex,
112+
RowSpan,
113+
Selected,
114+
SetSize,
115+
Sort,
116+
ValueMax,
117+
ValueMin,
118+
ValueNow,
119+
ValueText,
120+
}
121+
122+
impl TryFrom<&str> for AriaProperty {
123+
type Error = ();
124+
125+
fn try_from(value: &str) -> Result<Self, Self::Error> {
126+
match value {
127+
ARIA_ACTIVEDESCENDANT => Ok(AriaProperty::ActiveDescendant),
128+
ARIA_ATOMIC => Ok(AriaProperty::Atomic),
129+
ARIA_AUTOCOMPLETE => Ok(AriaProperty::AutoComplete),
130+
ARIA_BUSY => Ok(AriaProperty::Busy),
131+
ARIA_BRAILLELABEL => Ok(AriaProperty::BrailleLabel),
132+
ARIA_BRAILLEROLEDESCRIPTION => Ok(AriaProperty::BrailleRoleDescription),
133+
ARIA_CHECKED => Ok(AriaProperty::Checked),
134+
ARIA_COLCOUNT => Ok(AriaProperty::ColCount),
135+
ARIA_COLINDEX => Ok(AriaProperty::ColIndex),
136+
ARIA_COLSPAN => Ok(AriaProperty::ColSpan),
137+
ARIA_CONTROLS => Ok(AriaProperty::Controls),
138+
ARIA_CURRENT => Ok(AriaProperty::Current),
139+
ARIA_DESCRIBEDBY => Ok(AriaProperty::DescribedBy),
140+
ARIA_DESCRIPTION => Ok(AriaProperty::Description),
141+
ARIA_DETAILS => Ok(AriaProperty::Details),
142+
ARIA_DISABLED => Ok(AriaProperty::Disabled),
143+
ARIA_DROPEFFECT => Ok(AriaProperty::DropEffect),
144+
ARIA_ERRORMESSAGE => Ok(AriaProperty::ErrorMessage),
145+
ARIA_EXPANDED => Ok(AriaProperty::Expanded),
146+
ARIA_FLOWTO => Ok(AriaProperty::FlowTo),
147+
ARIA_GRABBED => Ok(AriaProperty::Grabbed),
148+
ARIA_HASPOPUP => Ok(AriaProperty::HasPopup),
149+
ARIA_HIDDEN => Ok(AriaProperty::Hidden),
150+
ARIA_INVALID => Ok(AriaProperty::Invalid),
151+
ARIA_KEYSHORTCUTS => Ok(AriaProperty::KeyShortcuts),
152+
ARIA_LABEL => Ok(AriaProperty::Label),
153+
ARIA_LABELLEDBY => Ok(AriaProperty::LabelledBy),
154+
ARIA_LEVEL => Ok(AriaProperty::Level),
155+
ARIA_LIVE => Ok(AriaProperty::Live),
156+
ARIA_MODAL => Ok(AriaProperty::Modal),
157+
ARIA_MULTILINE => Ok(AriaProperty::Multiline),
158+
ARIA_MULTISELECTABLE => Ok(AriaProperty::Multiselectable),
159+
ARIA_ORIENTATION => Ok(AriaProperty::Orientation),
160+
ARIA_OWNS => Ok(AriaProperty::Owns),
161+
ARIA_PLACEHOLDER => Ok(AriaProperty::Placeholder),
162+
ARIA_POSINSET => Ok(AriaProperty::PosInSet),
163+
ARIA_PRESSED => Ok(AriaProperty::Pressed),
164+
ARIA_READONLY => Ok(AriaProperty::Readonly),
165+
ARIA_RELEVANT => Ok(AriaProperty::Relevant),
166+
ARIA_REQUIRED => Ok(AriaProperty::Required),
167+
ARIA_ROLEDESCRIPTION => Ok(AriaProperty::RoleDescription),
168+
ARIA_ROWCOUNT => Ok(AriaProperty::RowCount),
169+
ARIA_ROWINDEX => Ok(AriaProperty::RowIndex),
170+
ARIA_ROWSPAN => Ok(AriaProperty::RowSpan),
171+
ARIA_SELECTED => Ok(AriaProperty::Selected),
172+
ARIA_SETSIZE => Ok(AriaProperty::SetSize),
173+
ARIA_SORT => Ok(AriaProperty::Sort),
174+
ARIA_VALUEMAX => Ok(AriaProperty::ValueMax),
175+
ARIA_VALUEMIN => Ok(AriaProperty::ValueMin),
176+
ARIA_VALUENOW => Ok(AriaProperty::ValueNow),
177+
ARIA_VALUETEXT => Ok(AriaProperty::ValueText),
178+
_ => Err(()),
179+
}
180+
}
181+
}
182+
183+
/// Returns whether this string is a valid ARIA property.
184+
///
185+
/// # Example
186+
/// - `is_valid_aria_property("aria-label")` => `true`
187+
/// - `is_valid_aria_property("aria-labelby")` => `false`
188+
pub fn is_valid_aria_property(name: &str) -> bool {
189+
AriaProperty::try_from(name).is_ok()
190+
}
67191

68192
/// set of valid ARIA role definitions
69193
/// Reference: <https://www.w3.org/TR/wai-aria/#role_definitions>

crates/oxc_linter/src/rules/jsx_a11y/aria_props.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use oxc_macros::declare_oxc_lint;
55
use oxc_span::{GetSpan, Span};
66

77
use crate::{
8-
AstNode, context::LintContext, globals::VALID_ARIA_PROPS, rule::Rule,
8+
AstNode, context::LintContext, globals::is_valid_aria_property, rule::Rule,
99
utils::get_jsx_attribute_name,
1010
};
1111

@@ -56,7 +56,7 @@ impl Rule for AriaProps {
5656
if let AstKind::JSXAttributeItem(JSXAttributeItem::Attribute(attr)) = node.kind() {
5757
let name = get_jsx_attribute_name(&attr.name);
5858
let name = name.cow_to_ascii_lowercase();
59-
if name.starts_with("aria-") && !VALID_ARIA_PROPS.contains(&name) {
59+
if name.starts_with("aria-") && !is_valid_aria_property(&name) {
6060
let suggestion = COMMON_TYPOS.get(&name).copied();
6161
let diagnostic = aria_props_diagnostic(attr.span, &name, suggestion);
6262

0 commit comments

Comments
 (0)