Skip to content

Commit

Permalink
LibWeb: Fix accessible-name computation for “encapsulation” cases
Browse files Browse the repository at this point in the history
This change makes Ladybird correctly handle all “encapsulation” tests in
the https://wpt.fyi/results/accname/name/comp_host_language_label.html
set of tests in WPT.

Those all test the requirement that when computing the accessible name
for a <label>-ed form control, then any content (text content or
attribute values) from the control itself that would otherwise be
included in the accessible-name computation for it ancestor <label> must
instead be skipped and not included.

The HTML-AAM spec seems to try to achieve that result by expressing
specific steps for each particular type of form control. But what all
that reduces/optimizes/simplifies down to is just, “skip over self”.

Otherwise, without this change, Ladybird includes that “self” content
from those “encapsulated” elements when doing accessible-name
computation for the elements — which results in AT users hearing
unexpected extra content in the accessible names for those elements.
  • Loading branch information
sideshowbarker committed Nov 25, 2024
1 parent 1bc23f1 commit b9897f1
Show file tree
Hide file tree
Showing 3 changed files with 263 additions and 0 deletions.
9 changes: 9 additions & 0 deletions Libraries/LibWeb/DOM/Node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2290,6 +2290,15 @@ ErrorOr<String> Node::name_or_description(NameOrDescription target, Document con
for (u32 i = 0; i < labels->length(); i++) {
auto nodes = labels->item(i)->children_as_vector();
for (auto const& node : nodes) {
// AD-HOC: https://wpt.fyi/results/accname/name/comp_host_language_label.html has “encapsulation”
// tests, from which can be induced a requirement that when computing the accessible name for a
// <label>-ed form control (“embedded control”), then any content (text content or attribute values)
// from the control itself that would otherwise be included in the accessible-name computation for
// it ancestor <label> must instead be skipped and not included. The HTML-AAM spec seems to maybe
// be trying to achieve that result by expressing specific steps for each particular type of form
// control. But what all that reduces/optimizes/simplifies down to is just, “skip over self”.
if (node == this)
continue;
if (node->is_element()) {
auto const& element = static_cast<DOM::Element const&>(*node);
auto role = element.role_or_default();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
Summary

Harness status: OK

Rerun

Found 78 tests

78 Pass
Details
Result Test Name MessagePass html: input[type=button]
Pass html: input[type=image]
Pass html: input[type=reset]
Pass html: input[type=submit]
Pass html: label[for] input[type=checkbox]
Pass html: label[for] input[type=checkbox][value='test']
Pass html: label[for] input[type=checkbox][checked]
Pass html: label[for] input[type=checkbox][checked][value='test']
Pass html: label[for] input[type=color]
Pass html: label[for] input[type=color][value='#999999']
Pass html: label[for] input[type=date]
Pass html: label[for] input[type=date][value='2025-01-01']
Pass html: label[for] input[type=datetime-local]
Pass html: label[for] input[type=datetime-local][value='2025-01-01T00:01']
Pass html: label[for] input[type=email]
Pass html: label[for] input[type=email][value='test@test.com']
Pass html: label[for] input[type=month]
Pass html: label[for] input[type=month][value='2025-01']
Pass html: label[for] input[type=number]
Pass html: label[for] input[type=number][value=2025]
Pass html: label[for] input[type=password]
Pass html: label[for] input[type=password][value='test']
Pass html: label[for] input[type=radio]
Pass html: label[for] input[type=radio][value='test']
Pass html: label[for] input[type=range]
Pass html: label[for] input[type=range][min=0][max=10][value=5]
Pass html: label[for] input[type=search]
Pass html: label[for] input[type=search][value='test']
Pass html: label[for] input[type=tel]
Pass html: label[for] input[type=tel][value='123-45-678']
Pass html: label[for] input[type=text]
Pass html: label[for] input[type=text][value='test']
Pass html: label[for] input[type=time]
Pass html: label[for] input[type=time][value='00:01']
Pass html: label[for] input[type=url]
Pass html: label[for] input[type=url][value='https://www.w3.org']
Pass html: label[for] input[type=week]
Pass html: label[for] input[type=week][value='2025-W01']
Pass html: label input[type=checkbox] encapsulation
Pass html: label input[type=checkbox][value='test'] encapsulation
Pass html: label input[type=checkbox][checked] encapsulation
Pass html: label input[type=checkbox][value='test'][checked] encapsulation
Pass html: label input[type=color] encapsulation
Pass html: label input[type=color][value='#999999'] encapsulation
Pass html: label input[type=date] encapsulation
Pass html: label input[type=date][value='2025-01-01'] encapsulation
Pass html: label input[type=datetime-local] encapsulation
Pass html: label input[type=datetime-local][value='2025-01-01T00:01'] encapsulation
Pass html: label input[type=email] encapsulation
Pass html: label input[type=email][value='test@test.com'] encapsulation
Pass html: label input[type=month] encapsulation
Pass html: label input[type=month][value='2025-01'] encapsulation
Pass html: label input[type=number] encapsulation
Pass html: label input[type=number][value=1] encapsulation
Pass html: label input[type=password] encapsulation
Pass html: label input[type=password][value='test'] encapsulation
Pass html: label input[type=radio] encapsulation
Pass html: label input[type=radio][value='test'] encapsulation
Pass html: label input[type=range] encapsulation
Pass html: label input[type=range][value='5'][min='0'][max='10'] encapsulation
Pass html: label input[type=search] encapsulation
Pass html: label input[type=search][value='test'] encapsulation
Pass html: label input[type=tel] encapsulation
Pass html: label input[type=tel][value='123-45-678'] encapsulation
Pass html: label[for] input[type=text] encapsulation
Pass html: label[for] input[type=text][value='test'] encapsulation
Pass html: label input[type=time] encapsulation
Pass html: label input[type=time][value='00:01'] encapsulation
Pass html: label input[type=url] encapsulation
Pass html: label input[type=url][value='https://www.w3.org'] encapsulation
Pass html: label input[type=week] encapsulation
Pass html: label input[type=week][value='2025-W01'] encapsulation
Pass html: select for/id
Pass html: select encapsulation
Pass html: img[alt] (non-empty)
Pass html: picture > img[alt] (non-empty)
Pass html: fieldset > legend
Pass html: table > caption
Loading

0 comments on commit b9897f1

Please sign in to comment.