Fix radio group validity update when removing or selecting an input (#36252)

This PR fixes an issue where radio inputs in the same group failed to
correctly update their `validity.valueMissing` state when:

- A **checked radio button was removed** from the DOM.
- A **different radio button was selected** by user interaction.

This behavior caused mismatches with how browsers like Firefox handle
radio group validation.

---

### Changes in This PR

#### Radio group revalidation on DOM removal
- Updated `unbind_from_tree()` to revalidate other radio buttons in the
same group when a checked input is removed.
- Uses `UnbindContext::parent` as the DOM root to ensure the correct
context is used during traversal.

#### New helper: `find_related_radios()`
- Encapsulates logic for finding other inputs in the same group.
- Used during both removal and attribute changes for consistency.

#### Validation on `checked`/`value` updates
- Introduced `update_related_validity_states()` to revalidate all group
members when a radio's `checked` or `value` is changed.

#### Web Platform Test (WPT) coverage
- Created a new WPT file: `radio-group-valueMissing.html`.
- Tests follow recommended `test()` pattern:
  - **Precondition**: Assert initial `valueMissing`.
  - **Action**: Remove or select a radio.
  - **Postcondition**: Assert expected `valueMissing`.

#### Manifest updated
- The WPT manifest now includes the new test.

---
<!-- 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 any errors
- [X] These changes fix #36110

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

Signed-off-by: Emmanuel Elom <elomemmanuel007@gmail.com>
This commit is contained in:
elomscansio 2025-04-07 00:26:15 +01:00 committed by GitHub
parent 0caa271176
commit 1f558a0d49
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 157 additions and 38 deletions

View file

@ -728363,6 +728363,13 @@
{}
]
],
"radio-group-valueMissing.html": [
"5f14c0b82e15c2e1ad259d47b970e4b19e7b3f0e",
[
null,
{}
]
],
"radio-valueMissing.html": [
"a02b6b96454f28c7ebd6ebfbedd604b67e8b1d77",
[

View file

@ -0,0 +1,46 @@
<!DOCTYPE html>
<meta charset="utf-8" />
<title>
The constraint validation API Test: element.validity.valueMissing for radio
group
</title>
<link rel="author" title="Emmanuel Elom" href="mailto:elomemmanuel007@gmail.com">
<link
rel="help"
href="https://html.spec.whatwg.org/multipage/#dom-validitystate-valuemissing"
/>
<link
rel="help"
href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api"
/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support/validator.js"></script>
<div id="log"></div>
<input type="radio" id="first" required name="group" />
<input type="radio" id="second" checked name="group" />
<input type="radio" id="third" required name="group1" />
<input type="radio" id="fourth" name="group1" />
<script>
const first = document.getElementById("first");
const second = document.getElementById("second");
const third = document.getElementById("third");
const fourth = document.getElementById("fourth");
test(() => {
assert_equals(first.validity.valueMissing, false);
assert_equals(second.validity.valueMissing, false);
second.remove();
assert_equals(first.validity.valueMissing, true);
}, "valueMissing is true for all group members when checked group member is removed");
test(() => {
assert_equals(third.validity.valueMissing, true);
assert_equals(fourth.validity.valueMissing, true);
fourth.click();
assert_equals(third.validity.valueMissing, false);
assert_equals(fourth.validity.valueMissing, false);
}, "valueMissing is false for all group members when any group member is checked");
</script>