Fix panic in formelement.rs (#37459)

Use borrowing directly with iterators instead of holding the borrowed
value for a longer scope.

Testing: Covered by existing tests, and manual testing with the test
case from https://github.com/servo/servo/issues/37430
Fixes: https://github.com/servo/servo/issues/37430

Signed-off-by: webbeef <me@webbeef.org>
This commit is contained in:
webbeef 2025-06-16 05:41:37 -07:00 committed by GitHub
parent bcade589e7
commit 910cc0b687
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 24 additions and 10 deletions

View file

@ -537,10 +537,8 @@ impl HTMLFormElementMethods<crate::DomTypeHolder> for HTMLFormElement {
let mut sourced_names_vec: Vec<SourcedName> = Vec::new();
let controls = self.controls.borrow();
// Step 2
for child in controls.iter() {
for child in self.controls.borrow().iter() {
if child
.downcast::<HTMLElement>()
.is_some_and(|c| c.is_listed_element())
@ -565,7 +563,7 @@ impl HTMLFormElementMethods<crate::DomTypeHolder> for HTMLFormElement {
}
// Step 3
for child in controls.iter() {
for child in self.controls.borrow().iter() {
if child.is::<HTMLImageElement>() {
if let Some(id_atom) = child.get_id() {
let entry = SourcedName {
@ -713,8 +711,9 @@ impl HTMLFormElement {
}
pub(crate) fn update_validity(&self, can_gc: CanGc) {
let controls = self.controls.borrow();
let is_any_invalid = controls
let is_any_invalid = self
.controls
.borrow()
.iter()
.any(|control| control.is_invalid(false, can_gc));
@ -1084,9 +1083,10 @@ impl HTMLFormElement {
/// Statitically validate the constraints of form elements
/// <https://html.spec.whatwg.org/multipage/#statically-validate-the-constraints>
fn static_validation(&self, can_gc: CanGc) -> Result<(), Vec<DomRoot<Element>>> {
let controls = self.controls.borrow();
// Step 1-3
let invalid_controls = controls
let invalid_controls = self
.controls
.borrow()
.iter()
.filter_map(|field| {
if let Some(element) = field.downcast::<Element>() {
@ -1131,9 +1131,8 @@ impl HTMLFormElement {
encoding: Option<&'static Encoding>,
can_gc: CanGc,
) -> Vec<FormDatum> {
let controls = self.controls.borrow();
let mut data_set = Vec::new();
for child in controls.iter() {
for child in self.controls.borrow().iter() {
// Step 5.1: The field element is disabled.
if child.disabled_state() {
continue;

View file

@ -8241,6 +8241,13 @@
{}
]
],
"form-check-validity-crash.html": [
"6d3bd0d2e36751c554af42164189d921975ced93",
[
null,
{}
]
],
"form-controls-id-removal-crash.html": [
"2b1ef87774fc1c5393129fca8e65147c379ea7a9",
[

View file

@ -0,0 +1,8 @@
<!DOCTYPE html>
<div id="container">
<form id="formId"></form>
</div>
<input id="inputId" required form="formId" oninvalid="container.remove()">
<script>
formId.checkValidity();
</script>