This commit is contained in:
sideshowbarker 2025-04-19 11:18:51 +00:00 committed by GitHub
commit 79a9535268
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 90 additions and 22 deletions

View file

@ -2470,16 +2470,14 @@ ErrorOr<String> Node::name_or_description(NameOrDescription target, Document con
// then try to retrieve a role for such elements here, thatd then end up calling right back into this
// name_or_description code — which would cause the calls to loop infinitely. So to avoid that, the caller
// in the ARIAMixin code can pass the shouldComputeRole parameter to indicate we must skip the role lookup.
// https://github.com/w3c/aria/issues/2404
if (should_compute_role == ShouldComputeRole::Yes)
role = element->role_from_role_attribute_value();
// Per https://w3c.github.io/html-aam/#el-aside and https://w3c.github.io/html-aam/#el-section, computing a
// default role for an aside element or section element requires first computing its accessible name — that is,
// calling into this name_or_description code. But if we then try to determine a default role for the aside
// element or section element here, thatd then end up calling right back into this name_or_description code —
// which would cause the calls to loop infinitely. So to avoid that, we only compute a default role here if this
// isnt an aside element or section element.
// Per-spec, at https://w3c.github.io/html-aam/#el-aside and elsewhere, computing a default role for certain
// elements (img, aside, and section) requires first computing its accessible name. So to avoid getting into an
// infinite loop here, the callers in our code for those cases pass in ShouldComputeRole::Yes.
// https://github.com/w3c/aria/issues/2391
if (!role.has_value() && element->local_name() != HTML::TagNames::aside && element->local_name() != HTML::TagNames::section)
if (should_compute_role == ShouldComputeRole::Yes && !role.has_value())
role = element->default_role();
// 2. Compute the text alternative for the current node:
@ -2550,7 +2548,7 @@ ErrorOr<String> Node::name_or_description(NameOrDescription target, Document con
total_accumulated_text.append(result);
}
// iii. Return the accumulated text.
// iii. Return the accumulated text if it is not the empty string ("").
// AD-HOC: This substep in the spec doesnt seem to explicitly require the following check for an aria-label
// value; but the “button's hidden referenced name (visibility:hidden) with hidden aria-labelledby traversal
// falls back to aria-label” subtest at https://wpt.fyi/results/accname/name/comp_labelledby.html wont pass
@ -2675,7 +2673,9 @@ ErrorOr<String> Node::name_or_description(NameOrDescription target, Document con
//
// https://w3c.github.io/html-aam/#img-element-accessible-name-computation
// use alt attribute, even if its value is the empty string.
// See also https://wpt.fyi/results/accname/name/comp_tooltip.tentative.html.
// See also https://wpt.fyi/results/accname/name/comp_tooltip.tentative.html — but also see
// https://github.com/w3c/aria/issues/2491 and the el-img-empty-alt-title subtest in the test at
// https://wpt.fyi/results/html-aam/roles-contextual.html.
if (is<HTML::HTMLImageElement>(*element) && element->has_attribute(HTML::AttributeNames::alt))
return element->get_attribute(HTML::AttributeNames::alt).value();

View file

@ -845,7 +845,7 @@ Optional<ARIA::Role> HTMLElement::default_role() const
// https://w3c.github.io/html-aam/#el-aside
for (auto ancestor = parent_element(); ancestor; ancestor = ancestor->parent_element()) {
if (ancestor->local_name().is_one_of(TagNames::article, TagNames::aside, TagNames::nav, TagNames::section)
&& accessible_name(document()).value().is_empty())
&& accessible_name(document(), DOM::ShouldComputeRole::No).value().trim_whitespace(TrimMode::Both).value().is_empty())
return ARIA::Role::generic;
}
// https://w3c.github.io/html-aam/#el-aside-ancestorbodymain
@ -932,7 +932,7 @@ Optional<ARIA::Role> HTMLElement::default_role() const
// https://www.w3.org/TR/html-aria/#el-section
if (local_name() == TagNames::section) {
// role=region if the section element has an accessible name
if (!accessible_name(document()).value().is_empty())
if (!accessible_name(document(), DOM::ShouldComputeRole::No).value().trim_whitespace(TrimMode::Both).value().is_empty())
return ARIA::Role::region;
// Otherwise, role=generic
return ARIA::Role::generic;

View file

@ -419,17 +419,18 @@ WebIDL::ExceptionOr<GC::Ref<WebIDL::Promise>> HTMLImageElement::decode() const
Optional<ARIA::Role> HTMLImageElement::default_role() const
{
// https://www.w3.org/TR/html-aria/#el-img-empty-alt
// NOTE: The "none" role value is a synonym for the older "presentation" role value; however, the el-img-alt-no-value
// test in https://wpt.fyi/results/html-aam/roles.html expects the value to be "none" (not "presentation").
if (has_attribute(HTML::AttributeNames::alt) && alt().is_empty()
&& accessible_name(document(), DOM::ShouldComputeRole::No).value().trim_whitespace(TrimMode::Both).value().is_empty())
return ARIA::Role::none;
// https://www.w3.org/TR/html-aria/#el-img
// https://www.w3.org/TR/html-aria/#el-img-no-alt
// https://w3c.github.io/aria/#image
// NOTE: The "image" role value is a synonym for the older "img" role value; however, the el-img test in
// https://wpt.fyi/results/html-aam/roles.html expects the value to be "image" (not "img").
if (!alt().is_empty())
return ARIA::Role::image;
// https://www.w3.org/TR/html-aria/#el-img-empty-alt
// NOTE: The "none" role value is a synonym for the older "presentation" role value; however, the el-img-alt-no-value
// test in https://wpt.fyi/results/html-aam/roles.html expects the value to be "none" (not "presentation").
return ARIA::Role::none;
return ARIA::Role::image;
}
// https://html.spec.whatwg.org/multipage/images.html#use-srcset-or-picture

View file

@ -1,8 +1,9 @@
Harness status: OK
Found 19 tests
Found 48 tests
19 Pass
47 Pass
1 Fail
Pass el-a
Pass el-aside
Pass el-aside-in-main
@ -12,13 +13,42 @@ Pass el-aside-in-aside-with-name
Pass el-aside-in-nav-with-name
Pass el-aside-in-nav-with-role
Pass el-aside-in-section-with-name
Pass el-aside-in-section-aria-labelledby
Pass el-aside-in-section-title
Pass el-footer-ancestorbody
Pass el-header-ancestorbody
Pass el-img-no-name
Pass el-img-empty-alt-aria-label
Pass el-img-empty-alt-aria-labelledby
Fail el-img-empty-alt-title
Pass el-section
Pass el-section-aria-labelledby
Pass el-section-title
Pass el-a-no-href
Pass el-aside-in-article-in-main
Pass el-aside-in-article
Pass el-aside-in-aside
Pass el-aside-in-nav
Pass el-aside-in-section
Pass el-section-no-name
Pass el-aside-in-section-aria-label-empty
Pass el-aside-in-section-aria-label-whitespace
Pass el-aside-in-section-aria-labelledby-non-existing
Pass el-aside-in-section-aria-labelledby-empty
Pass el-aside-in-section-aria-labelledby-whitespace
Pass el-aside-in-section-title-empty
Pass el-aside-in-section-title-whitespace
Pass el-img-empty-alt-aria-label-empty
Pass el-img-empty-alt-aria-label-whitespace
Pass el-img-empty-alt-aria-labelledby-non-existing
Pass el-img-empty-alt-aria-labelledby-empty
Pass el-img-empty-alt-aria-labelledby-whitespace
Pass el-img-empty-alt-title-empty
Pass el-img-empty-alt-title-whitespace
Pass el-section-no-name
Pass el-section-aria-label-empty
Pass el-section-aria-label-whitespace
Pass el-section-aria-labelledby-non-existing
Pass el-section-aria-labelledby-empty
Pass el-section-aria-labelledby-whitespace
Pass el-section-title-empty
Pass el-section-title-whitespace

View file

@ -12,7 +12,7 @@
<body>
<p>Tests contextual computedrole mappings defined in <a href="https://w3c.github.io/html-aam/">HTML-AAM</a>, where the returned computed role is expected to change based on the context. Most test names correspond to a unique ID defined in the spec.<p>
<p>Tests contextual computed role mappings defined in <a href="https://w3c.github.io/html-aam/">HTML-AAM</a>, where the returned computed role is expected to change based on the context. Most test names correspond to a unique ID defined in the spec.<p>
<p>These should remain in alphabetical order.</code></p>
@ -50,6 +50,15 @@
<section aria-label="x">
<aside data-testname="el-aside-in-section" class="ex-generic">x</aside>
<aside data-testname="el-aside-in-section-with-name" data-expectedrole="complementary" aria-label="x" class="ex">x</aside>
<aside data-testname="el-aside-in-section-aria-label-empty" class="ex-generic" aria-label="">x</aside>
<aside data-testname="el-aside-in-section-aria-label-whitespace" class="ex-generic" aria-label=" ">x</aside>
<aside data-testname="el-aside-in-section-aria-labelledby" data-expectedrole="complementary" class="ex" aria-labelledby="labelledby">x</aside>
<aside data-testname="el-aside-in-section-aria-labelledby-non-existing" class="ex-generic" aria-labelledby="non-existing">x</aside>
<aside data-testname="el-aside-in-section-aria-labelledby-empty" class="ex-generic" aria-labelledby="empty">x</aside>
<aside data-testname="el-aside-in-section-aria-labelledby-whitespace" class="ex-generic" aria-labelledby="space">x</aside>
<aside data-testname="el-aside-in-section-title" data-expectedrole="complementary" title="x" class="ex">x</aside>
<aside data-testname="el-aside-in-section-title-empty" class="ex-generic" title="">x</aside>
<aside data-testname="el-aside-in-section-title-whitespace" class="ex-generic" title=" ">x</aside>
</section>
<!-- el-footer -->
@ -62,10 +71,38 @@
<header data-testname="el-header-ancestorbody" data-expectedrole="banner" class="ex">x</header>
<!-- main>header -> ./roles-contextual.tentative.html -->
<!-- el-img-empty-alt -->
<img data-testname="el-img-no-name" data-expectedrole="image" class="ex" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==">
<!-- img empty alt -> ./roles.html -->
<img data-testname="el-img-empty-alt-aria-label" data-expectedrole="image" class="ex" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt aria-label="x">
<img data-testname="el-img-empty-alt-aria-label-empty" class="ex-generic" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt aria-label="">
<img data-testname="el-img-empty-alt-aria-label-whitespace" class="ex-generic" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt aria-label=" ">
<img data-testname="el-img-empty-alt-aria-labelledby" data-expectedrole="image" class="ex" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt aria-labelledby="labelledby">
<img data-testname="el-img-empty-alt-aria-labelledby-non-existing" class="ex-generic" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt aria-labelledby="non-existing">
<img data-testname="el-img-empty-alt-aria-labelledby-empty" class="ex-generic" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt aria-labelledby="empty">
<img data-testname="el-img-empty-alt-aria-labelledby-whitespace" class="ex-generic" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt aria-labelledby="space">
<img data-testname="el-img-empty-alt-title" data-expectedrole="image" class="ex" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt title="x">
<img data-testname="el-img-empty-alt-title-empty" class="ex-generic" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt title="">
<img data-testname="el-img-empty-alt-title-whitespace" class="ex-generic" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt title=" ">
<!-- el-section -->
<section data-testname="el-section" aria-label="x" data-expectedrole="region" class="ex">x</section>
<section data-testname="el-section-no-name" class="ex-generic">x</section>
<section data-testname="el-section-aria-label-empty" class="ex-generic" aria-label="">x</section>
<section data-testname="el-section-aria-label-whitespace" class="ex-generic" aria-label=" ">x</section>
<section data-testname="el-section-aria-labelledby" data-expectedrole="region" class="ex" aria-labelledby="labelledby">x</section>
<section data-testname="el-section-aria-labelledby-non-existing" class="ex-generic" aria-labelledby="non-existing">x</section>
<section data-testname="el-section-aria-labelledby-empty" class="ex-generic" aria-labelledby="empty">x</section>
<section data-testname="el-section-aria-labelledby-whitespace" class="ex-generic" aria-labelledby="space">x</section>
<section data-testname="el-section-title" data-expectedrole="region" title="x" class="ex">x</section>
<section data-testname="el-section-title-empty" class="ex-generic" title="">x</section>
<section data-testname="el-section-title-whitespace" class="ex-generic" title=" ">x</section>
<!-- element to reference for aria-labelledby tests -->
<div id="labelledby">labelledby</div>
<div id="empty"></div>
<div id="space"> </div>
<script>
AriaUtils.verifyRolesBySelector(".ex");
@ -73,4 +110,4 @@ AriaUtils.verifyGenericRolesBySelector(".ex-generic");
</script>
</body>
</html>
</html>