Bug 1897194 - Form-associated custom elements shouldn't have special handling for :read-write, r=edgar

Differential Revision: https://phabricator.services.mozilla.com/D210868
This commit is contained in:
Olli Pettay 2024-05-21 12:53:14 +00:00
parent 9b4a7fecb7
commit c10f141eb1
6 changed files with 33 additions and 13 deletions

View file

@ -381,10 +381,6 @@ HTMLFieldSetElement* HTMLElement::GetFieldSetInternal() const {
bool HTMLElement::CanBeDisabled() const { return IsFormAssociatedElement(); } bool HTMLElement::CanBeDisabled() const { return IsFormAssociatedElement(); }
bool HTMLElement::DoesReadOnlyApply() const {
return IsFormAssociatedElement();
}
void HTMLElement::UpdateDisabledState(bool aNotify) { void HTMLElement::UpdateDisabledState(bool aNotify) {
bool oldState = IsDisabled(); bool oldState = IsDisabled();
nsGenericHTMLFormElement::UpdateDisabledState(aNotify); nsGenericHTMLFormElement::UpdateDisabledState(aNotify);

View file

@ -75,7 +75,6 @@ class HTMLElement final : public nsGenericHTMLFormElement {
void SetFieldSetInternal(HTMLFieldSetElement* aFieldset) override; void SetFieldSetInternal(HTMLFieldSetElement* aFieldset) override;
HTMLFieldSetElement* GetFieldSetInternal() const override; HTMLFieldSetElement* GetFieldSetInternal() const override;
bool CanBeDisabled() const override; bool CanBeDisabled() const override;
bool DoesReadOnlyApply() const override;
void UpdateDisabledState(bool aNotify) override; void UpdateDisabledState(bool aNotify) override;
void UpdateFormOwner(bool aBindToTree, Element* aFormIdElement) override; void UpdateFormOwner(bool aBindToTree, Element* aFormIdElement) override;

View file

@ -6553,7 +6553,7 @@ HTMLInputElement::ValueModeType HTMLInputElement::GetValueMode() const {
bool HTMLInputElement::IsMutable() const { bool HTMLInputElement::IsMutable() const {
return !IsDisabled() && return !IsDisabled() &&
!(DoesReadOnlyApply() && State().HasState(ElementState::READONLY)); !(DoesReadWriteApply() && State().HasState(ElementState::READONLY));
} }
bool HTMLInputElement::DoesRequiredApply() const { bool HTMLInputElement::DoesRequiredApply() const {

View file

@ -2233,7 +2233,7 @@ void nsGenericHTMLFormElement::UpdateDisabledState(bool aNotify) {
if (!changedStates.IsEmpty()) { if (!changedStates.IsEmpty()) {
ToggleStates(changedStates, aNotify); ToggleStates(changedStates, aNotify);
if (DoesReadOnlyApply()) { if (DoesReadWriteApply()) {
// :disabled influences :read-only / :read-write. // :disabled influences :read-only / :read-write.
UpdateReadOnlyState(aNotify); UpdateReadOnlyState(aNotify);
} }
@ -2241,7 +2241,7 @@ void nsGenericHTMLFormElement::UpdateDisabledState(bool aNotify) {
} }
bool nsGenericHTMLFormElement::IsReadOnlyInternal() const { bool nsGenericHTMLFormElement::IsReadOnlyInternal() const {
if (DoesReadOnlyApply()) { if (DoesReadWriteApply()) {
return IsDisabled() || GetBoolAttr(nsGkAtoms::readonly); return IsDisabled() || GetBoolAttr(nsGkAtoms::readonly);
} }
return nsGenericHTMLElement::IsReadOnlyInternal(); return nsGenericHTMLElement::IsReadOnlyInternal();
@ -2682,7 +2682,7 @@ bool nsGenericHTMLFormControlElement::CanBeDisabled() const {
return type != FormControlType::Object && type != FormControlType::Output; return type != FormControlType::Object && type != FormControlType::Output;
} }
bool nsGenericHTMLFormControlElement::DoesReadOnlyApply() const { bool nsGenericHTMLFormControlElement::DoesReadWriteApply() const {
auto type = ControlType(); auto type = ControlType();
if (!IsInputElement(type) && type != FormControlType::Textarea) { if (!IsInputElement(type) && type != FormControlType::Textarea) {
return false; return false;
@ -2716,7 +2716,7 @@ bool nsGenericHTMLFormControlElement::DoesReadOnlyApply() const {
case FormControlType::InputDatetimeLocal: case FormControlType::InputDatetimeLocal:
return true; return true;
default: default:
MOZ_ASSERT_UNREACHABLE("Unexpected input type in DoesReadOnlyApply()"); MOZ_ASSERT_UNREACHABLE("Unexpected input type in DoesReadWriteApply()");
return true; return true;
#else // DEBUG #else // DEBUG
default: default:

View file

@ -1140,9 +1140,10 @@ class nsGenericHTMLFormElement : public nsGenericHTMLElement {
virtual bool CanBeDisabled() const { return false; } virtual bool CanBeDisabled() const { return false; }
/** /**
* Returns if the readonly attribute applies. * Returns true if :read-write pseudo class may match the element even if the
* element isn't part of designMode or contenteditable.
*/ */
virtual bool DoesReadOnlyApply() const { return false; } virtual bool DoesReadWriteApply() const { return false; }
/** /**
* Returns true if the element is a form associated element. * Returns true if the element is a form associated element.
@ -1200,7 +1201,7 @@ class nsGenericHTMLFormControlElement : public nsGenericHTMLFormElement,
// nsGenericHTMLFormElement // nsGenericHTMLFormElement
bool CanBeDisabled() const override; bool CanBeDisabled() const override;
bool DoesReadOnlyApply() const override; bool DoesReadWriteApply() const override;
void SetFormInternal(mozilla::dom::HTMLFormElement* aForm, void SetFormInternal(mozilla::dom::HTMLFormElement* aForm,
bool aBindToTree) override; bool aBindToTree) override;
mozilla::dom::HTMLFormElement* GetFormInternal() const override; mozilla::dom::HTMLFormElement* GetFormInternal() const override;

View file

@ -5,6 +5,17 @@
<script src="/resources/testharness.js"></script> <script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script> <script src="/resources/testharnessreport.js"></script>
<script src="utils.js"></script> <script src="utils.js"></script>
<script>
class CustomElement extends HTMLElement {
static formAssociated = true;
constructor() {
super();
}
}
window.customElements.define("custom-element", CustomElement);
</script>
<div id="log"></div> <div id="log"></div>
<div id=set0> <div id=set0>
@ -58,6 +69,14 @@
</div> </div>
</div> </div>
<div id=set6>
<custom-element id=ce1>content</custom-element>
<custom-element id=ce2 contenteditable>content</custom-element>
<custom-element id=ce3 contenteditable readonly>content</custom-element>
<custom-element id=ce4 contenteditable disabled>content</custom-element>
<custom-element id=ce5 contenteditable readonly disabled>content</custom-element>
</div>
<script> <script>
testSelectorIdsMatch("#set0 :read-write", [], "The :read-write pseudo-class must not match input elements to which the readonly attribute does not apply"); testSelectorIdsMatch("#set0 :read-write", [], "The :read-write pseudo-class must not match input elements to which the readonly attribute does not apply");
@ -115,4 +134,9 @@
testSelectorIdsMatch("#set5 :read-write", ["cd1", "p3", "ci3", "ci4", "ct3", "ct4"], "The :read-write pseudo-class must match elements that are inside editing hosts, but not match inputs and textareas inside that aren't"); testSelectorIdsMatch("#set5 :read-write", ["cd1", "p3", "ci3", "ci4", "ct3", "ct4"], "The :read-write pseudo-class must match elements that are inside editing hosts, but not match inputs and textareas inside that aren't");
testSelectorIdsMatch("#set6 :read-only", ["ce1"], "The :read-only pseudo-class must match form-associated custom elements");
testSelectorIdsMatch("#set6 :read-write", ["ce2", "ce3", "ce4", "ce5"], "The :read-write pseudo-class must match form-associated contenteditable custom elements");
</script> </script>