New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement form-associated custom elements and their ElementInternals #31980
Conversation
…use the code in Validatable trait. 3. The form associated custom element is not a customized built-in element.
🤖 Opened new upstream WPT pull request (web-platform-tests/wpt#45471) with upstreamable changes. |
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#45471). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a lot going on here, so I wasn't able to check the logic of everything. I have some comments, but I don't see any glaring issues with this change.
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#45471). |
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#45471). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To make "readonly" effective to element with internals.
// or the element has a datalist element ancestor. | ||
!self.as_element().read_write_state() && | ||
!self.as_element().disabled_state() && | ||
!is_barred_by_datalist_ancestor(self.target_element.upcast::<Node>()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The readonly attribute affects "barred from constraint validation"
}, | ||
} | ||
} | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update the read_write_state
when "readonly" changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes to fix the WPT failures.
if definition.form_associated { | ||
element.upcast::<Element>().set_enabled_state(true); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this change to AttachInternals
which also check the invalid state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice cleanup.
components/script/dom/create.rs
Outdated
// of enabled/disabled/not-form-control and | ||
// becoming a form control is a change. | ||
element.upcast::<Element>().set_enabled_state(true); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this change to AttachInternals
which also check the invalid state.
@@ -867,6 +867,7 @@ pub fn upgrade_element(definition: Rc<CustomElementDefinition>, element: &Elemen | |||
// so it doesn't describe this check as an action.) | |||
element.check_disabled_attribute(); | |||
element.check_ancestors_disabled_state_for_form_control(); | |||
element.check_readonly_attribute(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should also check the readonly attribute after upgrade, so that the value of is_instance_validatable
will be correct.
components/script/dom/element.rs
Outdated
@@ -3137,6 +3138,9 @@ impl VirtualMethods for Element { | |||
self.super_type().unwrap().unbind_from_tree(context); | |||
|
|||
if let Some(f) = self.as_maybe_form_control() { | |||
// TODO: The valid state of ancestors might be wrong if the form control element | |||
// is with a fieldset ancestor, for instance: `<form><fieldset><input>`, | |||
// if `<input>` is unbinded, `<form><fieldset>` should `update_validity()`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This affects the test case "[Custom control affects :valid :invalid for FORM and FIELDSET]" in ElementInternals-validation.html
return internals.is_invalid(); | ||
} | ||
true | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because validatable
including the form control elements and elements with internals, it is not easy to check both outside element.rs, so we create functions here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function checks if the form control elements or elements with internals are invalid or not.
components/script/dom/htmlelement.rs
Outdated
} | ||
element.check_readonly_attribute(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems unbind_from_tree
won't affect the "readonly" attribute, so maybe we could remove this change.
false | ||
} | ||
}); | ||
.any(|element| element.is_invalid(false)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use is_invalid
instead, and consider of element with internals.
validatable.is_instance_validatable() && | ||
!validatable.validity_state().invalid_flags().is_empty() | ||
}); | ||
let is_any_invalid = controls.iter().any(|control| control.is_invalid(false)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use is_invalid
, and consider element with internals case.
None | ||
if let Some(element) = field.downcast::<Element>() { | ||
if element.is_invalid(true) { | ||
Some(DomRoot::from_ref(element)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same, use is_invalid
instead.
self.element.set_state(ElementState::INVALID, false); | ||
} | ||
pub fn update_pseudo_classes(&self) { | ||
if self.element.is_instance_validatable() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use is_instance_validatable
instead, and handle with the element with internals case.
if definition.form_associated { | ||
element.upcast::<Element>().set_enabled_state(true); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice cleanup.
if !bits.is_empty() && !message.iter().any(|m| m.len() > 0) { | ||
// Step 3: If flags contains one or more true values and message is not given or is the empty | ||
// string, then throw a TypeError. | ||
let bits = ValidationFlags::from(flags); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this can be an into()
call. I can try to make this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, thanks:) Then I'll leave it as it is for now.
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#45471). |
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#45471). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that many tests are failing now unfortunately: https://github.com/servo/servo/runs/23680344451
I'm not sure if this was due to changes made during this final review round or before.
components/script/dom/htmlelement.rs
Outdated
} | ||
element.check_readonly_attribute(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I notice that this was removed, perhaps it was inadvertent?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did it intentional, let me take a loot at the failures:)
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#45471). |
Looks like this just needs some expectations updates: https://github.com/servo/servo/runs/23705832258 |
Yeah, true, will do:) |
Done! |
📝 Transplanted new upstreamable changes to existing upstream WPT pull request (web-platform-tests/wpt#45471). |
✍ Updated existing upstream WPT pull request (web-platform-tests/wpt#45471) title and body. |
Form-associated elements are now working.
Remaining test failures in custom-elements/form-associated/ are:
This patch is originally from #25705
./mach build -d
does not report any errors./mach test-tidy
does not report any errors