ソースを参照

LibWeb: Ignore role=none for focusable & has-global-ARIA-attribute cases

This change causes explicit role=none and role=presentation attribute
values to be ignored in cases where the elements for which those values
are specified are either focusable, or have global ARIA attributes —
per https://w3c.github.io/aria/#conflict_resolution_presentation_none.
sideshowbarker 6 ヶ月 前
コミット
c8f4f7fe33

+ 16 - 5
Libraries/LibWeb/ARIA/ARIAMixin.cpp

@@ -38,11 +38,6 @@ Optional<Role> ARIAMixin::role_from_role_attribute_value() const
         // computedrole image" test in https://wpt.fyi/results/wai-aria/role/synonym-roles.html expects "image", not "img".
         // computedrole image" test in https://wpt.fyi/results/wai-aria/role/synonym-roles.html expects "image", not "img".
         if (role == Role::img)
         if (role == Role::img)
             return Role::image;
             return Role::image;
-        // NOTE: Per https://w3c.github.io/aria/#presentation, "the working group introduced none as the preferred
-        // synonym to the presentation role"; further, https://wpt.fyi/results/wai-aria/role/synonym-roles.html has a
-        // "synonym presentation role == computedrole none" test that expects "none", not "presentation".
-        if (role == Role::presentation)
-            return Role::none;
         // https://w3c.github.io/core-aam/#roleMappingComputedRole
         // https://w3c.github.io/core-aam/#roleMappingComputedRole
         // When an element has a role but is not contained in the required context (for example, an orphaned listitem
         // When an element has a role but is not contained in the required context (for example, an orphaned listitem
         // without the required accessible parent of role list), User Agents MUST ignore the role token, and return the
         // without the required accessible parent of role list), User Agents MUST ignore the role token, and return the
@@ -139,6 +134,22 @@ Optional<Role> ARIAMixin::role_from_role_attribute_value() const
         if ((role == ARIA::Role::form || role == ARIA::Role::region)
         if ((role == ARIA::Role::form || role == ARIA::Role::region)
             && to_element()->accessible_name(to_element()->document(), DOM::ShouldComputeRole::No).value().is_empty())
             && to_element()->accessible_name(to_element()->document(), DOM::ShouldComputeRole::No).value().is_empty())
             continue;
             continue;
+        if (role == ARIA::Role::none || role == ARIA::Role::presentation) {
+            // https://w3c.github.io/aria/#conflict_resolution_presentation_none
+            // If an element is focusable, user agents MUST ignore the none/presentation
+            // role and expose the element with its implicit role.
+            if (to_element()->is_focusable())
+                continue;
+            // If an element has global WAI-ARIA states or properties, user agents MUST
+            // ignore the none/presentation role and instead expose the element's implicit role.
+            if (has_global_aria_attribute())
+                continue;
+            // NOTE: Per https://w3c.github.io/aria/#presentation, "the working group introduced 'none' as the preferred
+            // synonym to the presentation role"; further, https://wpt.fyi/results/wai-aria/role/synonym-roles.html has
+            // a "synonym presentation role == computedrole none" test that expects "none", not "presentation".
+            if (role == Role::presentation)
+                return Role::none;
+        }
         // 4. Use the first such substring in textual order that matches the name of a non-abstract WAI-ARIA role.
         // 4. Use the first such substring in textual order that matches the name of a non-abstract WAI-ARIA role.
         if (!is_abstract_role(*role))
         if (!is_abstract_role(*role))
             return *role;
             return *role;

+ 12 - 0
Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/role_none_conflict_resolution.txt

@@ -0,0 +1,12 @@
+Harness status: OK
+
+Found 7 tests
+
+7 Pass
+Pass	heading role none with global attr aria-label
+Pass	p role none with global attr aria-label (prohibited role)
+Pass	focusable heading role none with tabindex=0
+Pass	focusable heading role none with tabindex=-1
+Pass	p role none without global attr aria-label (prohibited role)
+Pass	non-focusable heading role none
+Pass	none with non-global

+ 38 - 0
Tests/LibWeb/Text/input/wpt-import/wai-aria/role/role_none_conflict_resolution.html

@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+<head>
+  <title>Role None Conflict Resolution Verification Tests</title>
+    <script src="../../resources/testharness.js"></script>
+    <script src="../../resources/testharnessreport.js"></script>
+    <script src="../../resources/testdriver.js"></script>
+    <script src="../../resources/testdriver-vendor.js"></script>
+    <script src="../../resources/testdriver-actions.js"></script>
+    <script src="../../wai-aria/scripts/aria-utils.js"></script>
+</head>
+<body>
+
+<p>Verifies <a href="https://w3c.github.io/aria/#conflict_resolution_presentation_none"></a>conflict resolution</a> requirements for the ARIA <a href="https://w3c.github.io/aria/#none">none</a> and <a href="https://w3c.github.io/aria/#presentation">presentation</a> roles.</p>
+
+<!-- none with label(global) on header -->
+<h1 role="none" data-testname="heading role none with global attr aria-label" data-expectedrole="heading" aria-label="x" class="ex">x</h1>
+
+<!-- none with label(global) on paragraph -->
+<p role="none" data-testname="p role none with global attr aria-label (prohibited role)" data-expectedrole="paragraph" aria-label="x" class="ex">x</p>
+<p role="none" data-testname="p role none without global attr aria-label (prohibited role)" class="ex-generic">x</p>
+
+<!-- none with focusable header -->
+<h1 role="none" data-testname="focusable heading role none with tabindex=0" data-expectedrole="heading" tabindex="0" class="ex">x</h1>
+<h1 role="none" data-testname="focusable heading role none with tabindex=-1" data-expectedrole="heading" tabindex="-1" class="ex">x</h1>
+<h1 role="none" data-testname="non-focusable heading role none" class="ex-generic">x</h1>
+
+<!-- none with non-global-->
+<h1 role="none" data-testname="none with non-global" class="ex-generic" aria-level="2"> Sample Content </h1>
+
+
+<script>
+AriaUtils.verifyRolesBySelector(".ex");
+AriaUtils.verifyGenericRolesBySelector(".ex-generic");
+</script>
+
+</body>
+</html>