From 2cb7baa5813d713e728684f396a4c5cd295a8f6b Mon Sep 17 00:00:00 2001 From: sideshowbarker Date: Thu, 19 Dec 2024 12:27:18 +0900 Subject: [PATCH] =?UTF-8?q?LibWeb:=20Ignore=20=E2=80=9Corphaned=E2=80=9D?= =?UTF-8?q?=20ARIA=20roles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change causes explicitly-specified role attributes to be ignored in the case where the specified role is “orphaned” — that is, when its element lacks a required ancestor with an appropriate role. --- Libraries/LibWeb/ARIA/ARIAMixin.cpp | 90 ++++++++++++++++++- .../wai-aria/role/grid-roles.tentative.txt | 11 +++ .../wai-aria/role/list-roles.tentative.txt | 7 ++ .../wai-aria/role/listbox-roles.tentative.txt | 6 ++ .../wai-aria/role/menu-roles.tentative.txt | 14 +++ .../wai-aria/role/tab-roles.tentative.txt | 7 ++ .../wai-aria/role/tree-roles.tentative.txt | 7 ++ .../wai-aria/role/grid-roles.tentative.html | 33 +++++++ .../wai-aria/role/list-roles.tentative.html | 29 ++++++ .../role/listbox-roles.tentative.html | 29 ++++++ .../wai-aria/role/menu-roles.tentative.html | 45 ++++++++++ .../wai-aria/role/tab-roles.tentative.html | 29 ++++++ .../wai-aria/role/tree-roles.tentative.html | 28 ++++++ 13 files changed, 334 insertions(+), 1 deletion(-) create mode 100644 Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/grid-roles.tentative.txt create mode 100644 Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/list-roles.tentative.txt create mode 100644 Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/listbox-roles.tentative.txt create mode 100644 Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/menu-roles.tentative.txt create mode 100644 Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/tab-roles.tentative.txt create mode 100644 Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/tree-roles.tentative.txt create mode 100644 Tests/LibWeb/Text/input/wpt-import/wai-aria/role/grid-roles.tentative.html create mode 100644 Tests/LibWeb/Text/input/wpt-import/wai-aria/role/list-roles.tentative.html create mode 100644 Tests/LibWeb/Text/input/wpt-import/wai-aria/role/listbox-roles.tentative.html create mode 100644 Tests/LibWeb/Text/input/wpt-import/wai-aria/role/menu-roles.tentative.html create mode 100644 Tests/LibWeb/Text/input/wpt-import/wai-aria/role/tab-roles.tentative.html create mode 100644 Tests/LibWeb/Text/input/wpt-import/wai-aria/role/tree-roles.tentative.html diff --git a/Libraries/LibWeb/ARIA/ARIAMixin.cpp b/Libraries/LibWeb/ARIA/ARIAMixin.cpp index 2dd47c2dcb5..2e47d36acf8 100644 --- a/Libraries/LibWeb/ARIA/ARIAMixin.cpp +++ b/Libraries/LibWeb/ARIA/ARIAMixin.cpp @@ -25,7 +25,6 @@ Optional ARIAMixin::role_from_role_attribute_value() const // 3. Compare the substrings to all the names of the non-abstract WAI-ARIA roles. Case-sensitivity of the comparison inherits from the case-sensitivity of the host language. for (auto const& role_name : role_list) { - // 4. Use the first such substring in textual order that matches the name of a non-abstract WAI-ARIA role. auto role = role_from_string(role_name); if (!role.has_value()) continue; @@ -43,6 +42,95 @@ Optional ARIAMixin::role_from_role_attribute_value() const // "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 + // 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 + // computedrole as if the ignored role token had not been included. + if (role == ARIA::Role::columnheader) { + for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) { + if (ancestor->role_or_default() == ARIA::Role::row) + return ARIA::Role::columnheader; + } + continue; + } + if (role == ARIA::Role::gridcell) { + for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) { + if (ancestor->role_or_default() == ARIA::Role::row) + return ARIA::Role::gridcell; + } + continue; + } + if (role == ARIA::Role::listitem) { + for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) { + if (first_is_one_of(ancestor->role_or_default(), ARIA::Role::directory, ARIA::Role::list)) + return ARIA::Role::listitem; + } + continue; + } + if (role == ARIA::Role::menuitem) { + for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) { + if (first_is_one_of(ancestor->role_or_default(), ARIA::Role::menu, ARIA::Role::menubar)) + return ARIA::Role::menuitem; + } + continue; + } + if (role == ARIA::Role::menuitemcheckbox) { + for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) { + if (first_is_one_of(ancestor->role_or_default(), ARIA::Role::menu, ARIA::Role::menubar)) + return ARIA::Role::menuitemcheckbox; + } + continue; + } + if (role == ARIA::Role::menuitemradio) { + for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) { + if (first_is_one_of(ancestor->role_or_default(), ARIA::Role::menu, ARIA::Role::menubar)) + return ARIA::Role::menuitemradio; + } + continue; + } + if (role == ARIA::Role::option) { + for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) { + if (ancestor->role_or_default() == ARIA::Role::listbox) + return ARIA::Role::option; + } + continue; + } + if (role == ARIA::Role::row) { + for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) { + if (first_is_one_of(ancestor->role_or_default(), ARIA::Role::table, ARIA::Role::grid, ARIA::Role::treegrid)) + return ARIA::Role::row; + } + continue; + } + if (role == ARIA::Role::rowgroup) { + for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) { + if (first_is_one_of(ancestor->role_or_default(), ARIA::Role::table, ARIA::Role::grid, ARIA::Role::treegrid)) + return ARIA::Role::rowgroup; + } + continue; + } + if (role == ARIA::Role::rowheader) { + for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) { + if (ancestor->role_or_default() == ARIA::Role::row) + return ARIA::Role::rowheader; + } + continue; + } + if (role == ARIA::Role::tab) { + for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) { + if (ancestor->role_or_default() == ARIA::Role::tablist) + return ARIA::Role::tab; + } + continue; + } + if (role == ARIA::Role::treeitem) { + for (auto const* ancestor = to_element()->parent_element(); ancestor; ancestor = ancestor->parent_element()) { + if (ancestor->role_or_default() == ARIA::Role::tree) + return ARIA::Role::treeitem; + } + continue; + } + // 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)) return *role; } diff --git a/Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/grid-roles.tentative.txt b/Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/grid-roles.tentative.txt new file mode 100644 index 00000000000..23c8472b29a --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/grid-roles.tentative.txt @@ -0,0 +1,11 @@ +Harness status: OK + +Found 6 tests + +6 Pass +Pass orphaned button with gridcell role outside the context of row +Pass orphaned row outside the context of table +Pass orphaned rowgroup outside the context of row +Pass orphaned div with gridcell role outside the context of row +Pass orphaned rowheader outside the context of row +Pass orphaned columnheader outside the context of row \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/list-roles.tentative.txt b/Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/list-roles.tentative.txt new file mode 100644 index 00000000000..ea0b48c611f --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/list-roles.tentative.txt @@ -0,0 +1,7 @@ +Harness status: OK + +Found 2 tests + +2 Pass +Pass orphan p with listitem role +Pass orphan div with listitem role \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/listbox-roles.tentative.txt b/Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/listbox-roles.tentative.txt new file mode 100644 index 00000000000..266638a92e8 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/listbox-roles.tentative.txt @@ -0,0 +1,6 @@ +Harness status: OK + +Found 1 tests + +1 Pass +Pass orphaned option outside the context of listbox \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/menu-roles.tentative.txt b/Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/menu-roles.tentative.txt new file mode 100644 index 00000000000..b10a0c42349 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/menu-roles.tentative.txt @@ -0,0 +1,14 @@ +Harness status: OK + +Found 9 tests + +9 Pass +Pass orphaned menuitem outside the context of menu/menubar +Pass orphaned menuitemradio outside the context of menu/menubar +Pass orphaned menuitemcheckbox outside the context of menu/menubar +Pass orphan button with menuitem role +Pass orphan button with menuitemcheckbox role +Pass orphan button with menuitemradio role +Pass orphan div with menuitem role +Pass orphan div with menuitemcheckbox role +Pass orphan div with menuitemradio role \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/tab-roles.tentative.txt b/Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/tab-roles.tentative.txt new file mode 100644 index 00000000000..4265a01ed23 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/tab-roles.tentative.txt @@ -0,0 +1,7 @@ +Harness status: OK + +Found 2 tests + +2 Pass +Pass orphan button with tab role +Pass orphan span with tab role \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/tree-roles.tentative.txt b/Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/tree-roles.tentative.txt new file mode 100644 index 00000000000..8ee6330bf15 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/wai-aria/role/tree-roles.tentative.txt @@ -0,0 +1,7 @@ +Harness status: OK + +Found 2 tests + +2 Pass +Pass orphaned treeitem outside the context of tree +Pass orphaned button with treeitem role outside tree context \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/wai-aria/role/grid-roles.tentative.html b/Tests/LibWeb/Text/input/wpt-import/wai-aria/role/grid-roles.tentative.html new file mode 100644 index 00000000000..e3b0b294a5d --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/wai-aria/role/grid-roles.tentative.html @@ -0,0 +1,33 @@ + + + + Tentative: Grid Role Verification Tests + + + + + + + + + + + x + x +
x
+ +
x
+
x
+ + + + + \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/wai-aria/role/list-roles.tentative.html b/Tests/LibWeb/Text/input/wpt-import/wai-aria/role/list-roles.tentative.html new file mode 100644 index 00000000000..6454dd93bbd --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/wai-aria/role/list-roles.tentative.html @@ -0,0 +1,29 @@ + + + + Tentative: List-related Role Verification Tests + + + + + + + + + + +
x
+

x

+ + + + + \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/wai-aria/role/listbox-roles.tentative.html b/Tests/LibWeb/Text/input/wpt-import/wai-aria/role/listbox-roles.tentative.html new file mode 100644 index 00000000000..99479e0513f --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/wai-aria/role/listbox-roles.tentative.html @@ -0,0 +1,29 @@ + + + + Tentative: Listbox-related Role Verification Tests + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/wai-aria/role/menu-roles.tentative.html b/Tests/LibWeb/Text/input/wpt-import/wai-aria/role/menu-roles.tentative.html new file mode 100644 index 00000000000..08219f2be7a --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/wai-aria/role/menu-roles.tentative.html @@ -0,0 +1,45 @@ + + + + Tentative: Menu-related Role Verification Tests + + + + + + + + + + + + + + + + + + +
x
+ + +
x
+ + + + + \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/wai-aria/role/tab-roles.tentative.html b/Tests/LibWeb/Text/input/wpt-import/wai-aria/role/tab-roles.tentative.html new file mode 100644 index 00000000000..4b43dc775a0 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/wai-aria/role/tab-roles.tentative.html @@ -0,0 +1,29 @@ + + + + Tentative: Tab-related Role Verification Tests + + + + + + + + + + + +x + + + + + \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/wai-aria/role/tree-roles.tentative.html b/Tests/LibWeb/Text/input/wpt-import/wai-aria/role/tree-roles.tentative.html new file mode 100644 index 00000000000..28e800e0229 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/wai-aria/role/tree-roles.tentative.html @@ -0,0 +1,28 @@ + + + + Tentative: Tree related Role Verification Tests + + + + + + + + + + + + + + + + + \ No newline at end of file