htmlinputelement: Update radio group validity logic for disconnected trees (#36431)

This PR updates the validity state revalidation behavior for radio input
elements, ensuring consistent logic regardless of tree connectivity.

---

**What’s changed:**  
- we now always update the validity state.
- Handled more edge cases for disconnected trees, shadow roots, and
cross-tree movement.
- Ensured that radio group updates still trigger when a parent is moved
into a different root.
- Updated test expectations in
`radio-disconnected-group-owner.html.ini`.

---

**Why this matters:**  
The updated logic aligns better with the [HTML
specification](https://html.spec.whatwg.org/multipage/input.html#radio-button-group),
especially regarding radio group behavior in disconnected trees or
shadow DOM.

These changes improve validity propagation in scenarios like:
- Appending inputs into a disconnected form
- Shadow roots acting as radio group containers
- Cross-tree movement of radio buttons

---

**Tests:**  
- Modified `radio-disconnected-group-owner.html.ini`
  - Removed a test that now passes
- Added a failing test expectation caused by a spec bug: the fragment
parsing algorithm uses the connected tree for HTML set via `innerHTML`,
affecting radio group computation

---

**Spec reference:**  
https://html.spec.whatwg.org/multipage/input.html#radio-button-group

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by
`[X]` when the step is complete, and replace `___` with appropriate
data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report an errors
- [ ] These changes fix #

<!-- Either: -->
- [X] There are tests for these changes

Signed-off-by: Emmanuel Paul Elom <elomemmanuel007@gmail.com>
This commit is contained in:
elomscansio 2025-04-28 02:24:43 +01:00 committed by GitHub
parent 2892e7924d
commit b1d0b6a37b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 6 additions and 8 deletions

View file

@ -1257,6 +1257,7 @@ impl HTMLInputElementMethods<crate::DomTypeHolder> for HTMLInputElement {
// https://html.spec.whatwg.org/multipage/#dom-input-checked
fn SetChecked(&self, checked: bool) {
self.update_checked_state(checked, true);
update_related_validity_states(self, CanGc::note())
}
// https://html.spec.whatwg.org/multipage/#dom-input-readonly
@ -1697,7 +1698,7 @@ fn radio_group_iter<'a>(
) -> impl Iterator<Item = DomRoot<HTMLInputElement>> + 'a {
root.traverse_preorder(ShadowIncluding::No)
.filter_map(DomRoot::downcast::<HTMLInputElement>)
.filter(move |r| &**r == elem || in_same_group(r, form, group, None))
.filter(move |r| &**r == elem || in_same_group(r, form, group, Some(root)))
}
fn broadcast_radio_checked(broadcaster: &HTMLInputElement, group: Option<&Atom>) {
@ -2580,6 +2581,9 @@ impl VirtualMethods for HTMLInputElement {
self.upcast::<Element>()
.check_ancestors_disabled_state_for_form_control();
if self.input_type() == InputType::Radio {
self.radio_group_updated(self.radio_group_name().as_ref());
}
update_related_validity_states(self, can_gc);
}