Bug 1850293 - Make CHECKED/DEFAULT states not intrinsic. r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D186933
This commit is contained in:
Emilio Cobos Álvarez 2023-08-30 09:18:31 +00:00
Родитель 33968f7c4e
Коммит b1ad2fb6f3
12 изменённых файлов: 118 добавлений и 209 удалений

Просмотреть файл

@ -126,6 +126,7 @@ struct ScrollOptions;
class Attr;
class BooleanOrScrollIntoViewOptions;
class Document;
class HTMLFormElement;
class DOMIntersectionObserver;
class DOMMatrixReadOnly;
class Element;
@ -656,11 +657,7 @@ class Element : public FragmentOrElement {
const AttrArray& GetAttrs() const { return mAttrs; }
void SetDefined(bool aSet) {
if (aSet) {
AddStates(ElementState::DEFINED);
} else {
RemoveStates(ElementState::DEFINED);
}
SetStates(ElementState::DEFINED, aSet);
}
// AccessibilityRole
@ -749,6 +746,7 @@ class Element : public FragmentOrElement {
friend class ::nsGlobalWindowInner;
friend class ::nsGlobalWindowOuter;
friend class ::nsFocusManager;
friend class mozilla::dom::HTMLFormElement;
// Allow CusomtElementRegistry to call AddStates.
friend class CustomElementRegistry;
@ -768,19 +766,30 @@ class Element : public FragmentOrElement {
// These will handle setting up script blockers when they notify, so no need
// to do it in the callers unless desired. States passed here must only be
// those in EXTERNALLY_MANAGED_STATES.
void AddStates(ElementState aStates) {
void AddStates(ElementState aStates, bool aNotify = true) {
MOZ_ASSERT(!aStates.HasAtLeastOneOfStates(ElementState::INTRINSIC_STATES),
"Should only be adding externally-managed states here");
ElementState old = mState;
AddStatesSilently(aStates);
NotifyStateChange(old ^ mState);
if (aNotify) {
NotifyStateChange(old ^ mState);
}
}
void RemoveStates(ElementState aStates) {
void RemoveStates(ElementState aStates, bool aNotify = true) {
MOZ_ASSERT(!aStates.HasAtLeastOneOfStates(ElementState::INTRINSIC_STATES),
"Should only be removing externally-managed states here");
ElementState old = mState;
RemoveStatesSilently(aStates);
NotifyStateChange(old ^ mState);
if (aNotify) {
NotifyStateChange(old ^ mState);
}
}
void SetStates(ElementState aStates, bool aSet, bool aNotify = true) {
if (aSet) {
AddStates(aStates, aNotify);
} else {
RemoveStates(aStates, aNotify);
}
}
void ToggleStates(ElementState aStates, bool aNotify) {
MOZ_ASSERT(!aStates.HasAtLeastOneOfStates(ElementState::INTRINSIC_STATES),

Просмотреть файл

@ -181,7 +181,9 @@ bitflags! {
Self::INCREMENT_SCRIPT_LEVEL.bits |
Self::PLACEHOLDER_SHOWN.bits |
Self::READONLY.bits |
Self::READWRITE.bits;
Self::READWRITE.bits |
Self::CHECKED.bits |
Self::DEFAULT.bits;
const INTRINSIC_STATES = !Self::EXTERNALLY_MANAGED_STATES.bits;
}

Просмотреть файл

@ -1227,7 +1227,7 @@ nsresult HTMLFormElement::AddElement(nsGenericHTMLFormElement* aChild,
(*firstSubmitSlot == mDefaultSubmitElement ||
nsContentUtils::CompareTreePosition(aChild, mDefaultSubmitElement,
this) < 0)) {
mDefaultSubmitElement = aChild;
SetDefaultSubmitElement(aChild);
}
*firstSubmitSlot = aChild;
}
@ -1271,6 +1271,19 @@ nsresult HTMLFormElement::AddElementToTable(nsGenericHTMLFormElement* aChild,
return mControls->AddElementToTable(aChild, aName);
}
void HTMLFormElement::SetDefaultSubmitElement(
nsGenericHTMLFormElement* aElement) {
if (mDefaultSubmitElement) {
// It just so happens that a radio button or an <option> can't be our
// default submit element, so we can just blindly remove the bit.
mDefaultSubmitElement->RemoveStates(ElementState::DEFAULT);
}
mDefaultSubmitElement = aElement;
if (mDefaultSubmitElement) {
mDefaultSubmitElement->AddStates(ElementState::DEFAULT);
}
}
nsresult HTMLFormElement::RemoveElement(nsGenericHTMLFormElement* aChild,
bool aUpdateValidity) {
RemoveElementFromPastNamesMap(aChild);
@ -1320,7 +1333,7 @@ nsresult HTMLFormElement::RemoveElement(nsGenericHTMLFormElement* aChild,
if (aChild == mDefaultSubmitElement) {
// Need to reset mDefaultSubmitElement. Do this asynchronously so
// that we're not doing it while the DOM is in flux.
mDefaultSubmitElement = nullptr;
SetDefaultSubmitElement(nullptr);
nsContentUtils::AddScriptRunner(new RemoveElementRunnable(this));
// Note that we don't need to notify on the old default submit (which is
@ -1348,29 +1361,26 @@ void HTMLFormElement::HandleDefaultSubmitRemoval() {
return;
}
nsGenericHTMLFormElement* newDefaultSubmit;
if (!mFirstSubmitNotInElements) {
mDefaultSubmitElement = mFirstSubmitInElements;
newDefaultSubmit = mFirstSubmitInElements;
} else if (!mFirstSubmitInElements) {
mDefaultSubmitElement = mFirstSubmitNotInElements;
newDefaultSubmit = mFirstSubmitNotInElements;
} else {
NS_ASSERTION(mFirstSubmitInElements != mFirstSubmitNotInElements,
"How did that happen?");
// Have both; use the earlier one
mDefaultSubmitElement =
newDefaultSubmit =
nsContentUtils::CompareTreePosition(mFirstSubmitInElements,
mFirstSubmitNotInElements, this) < 0
? mFirstSubmitInElements
: mFirstSubmitNotInElements;
}
SetDefaultSubmitElement(newDefaultSubmit);
MOZ_ASSERT(mDefaultSubmitElement == mFirstSubmitInElements ||
mDefaultSubmitElement == mFirstSubmitNotInElements,
"What happened here?");
// Notify about change if needed.
if (mDefaultSubmitElement) {
mDefaultSubmitElement->UpdateState(true);
}
}
nsresult HTMLFormElement::RemoveElementFromTableInternal(
@ -1679,40 +1689,6 @@ nsGenericHTMLFormElement* HTMLFormElement::GetDefaultSubmitElement() const {
return mDefaultSubmitElement;
}
bool HTMLFormElement::IsDefaultSubmitElement(
const nsGenericHTMLFormElement* aElement) const {
MOZ_ASSERT(aElement, "Unexpected call");
if (aElement == mDefaultSubmitElement) {
// Yes, it is
return true;
}
if (mDefaultSubmitElement || (aElement != mFirstSubmitInElements &&
aElement != mFirstSubmitNotInElements)) {
// It isn't
return false;
}
// mDefaultSubmitElement is null, but we have a non-null submit around
// (aElement, in fact). figure out whether it's in fact the default submit
// and just hasn't been set that way yet. Note that we can't just call
// HandleDefaultSubmitRemoval because we might need to notify to handle that
// correctly and we don't know whether that's safe right here.
if (!mFirstSubmitInElements || !mFirstSubmitNotInElements) {
// We only have one first submit; aElement has to be it
return true;
}
// We have both kinds of submits. Check which comes first.
nsGenericHTMLFormElement* defaultSubmit =
nsContentUtils::CompareTreePosition(mFirstSubmitInElements,
mFirstSubmitNotInElements, this) < 0
? mFirstSubmitInElements
: mFirstSubmitNotInElements;
return aElement == defaultSubmit;
}
bool HTMLFormElement::ImplicitSubmissionIsDisabled() const {
// Input text controls are always in the elements list.
uint32_t numDisablingControlsFound = 0;

Просмотреть файл

@ -57,6 +57,9 @@ class HTMLFormElement final : public nsGenericHTMLElement,
int32_t IndexOfContent(nsIContent* aContent);
nsGenericHTMLFormElement* GetDefaultSubmitElement() const;
bool IsDefaultSubmitElement(nsGenericHTMLFormElement* aElement) const {
return aElement == mDefaultSubmitElement;
}
// nsIRadioGroupContainer
void SetCurrentRadioButton(const nsAString& aName,
@ -206,15 +209,6 @@ class HTMLFormElement final : public nsGenericHTMLElement,
*/
bool IsLastActiveElement(const nsGenericHTMLFormElement* aElement) const;
/**
* Check whether a given nsGenericHTMLFormElement is the default submit
* element. This is different from just comparing to
* GetDefaultSubmitElement() in certain situations inside an update
* when GetDefaultSubmitElement() might not be up to date. aElement
* is expected to not be null.
*/
bool IsDefaultSubmitElement(const nsGenericHTMLFormElement* aElement) const;
/**
* Flag the form to know that a button or image triggered scripted form
* submission. In that case the form will defer the submission until the
@ -618,6 +612,8 @@ class HTMLFormElement final : public nsGenericHTMLElement,
private:
bool IsSubmitting() const;
void SetDefaultSubmitElement(nsGenericHTMLFormElement*);
NotNull<const Encoding*> GetSubmitEncoding();
/**

Просмотреть файл

@ -1246,16 +1246,20 @@ void HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
UpdateStepMismatchValidityState();
}
//
// Checked must be set no matter what type of control it is, since
// mChecked must reflect the new value
if (aName == nsGkAtoms::checked && !mCheckedChanged) {
// Delay setting checked if we are creating this element (wait
// until everything is set)
if (!mDoneCreating) {
mShouldInitChecked = true;
} else {
DoSetChecked(DefaultChecked(), true, false);
if (aName == nsGkAtoms::checked) {
if (IsRadioOrCheckbox()) {
SetStates(ElementState::DEFAULT, !!aValue, aNotify);
}
if (!mCheckedChanged) {
// Delay setting checked if we are creating this element (wait
// until everything is set)
if (!mDoneCreating) {
mShouldInitChecked = true;
} else {
DoSetChecked(!!aValue, aNotify, false);
}
}
}
@ -2231,13 +2235,7 @@ void HTMLInputElement::SetFocusState(bool aIsFocused) {
if (NS_WARN_IF(!IsDateTimeInputType(mType))) {
return;
}
ElementState focusStates = ElementState::FOCUS | ElementState::FOCUSRING;
if (aIsFocused) {
AddStates(focusStates);
} else {
RemoveStates(focusStates);
}
SetStates(ElementState::FOCUS | ElementState::FOCUSRING, aIsFocused);
}
void HTMLInputElement::UpdateValidityState() {
@ -2952,25 +2950,26 @@ void HTMLInputElement::MaybeSubmitForm(nsPresContext* aPresContext) {
}
}
void HTMLInputElement::UpdateCheckedState(bool aNotify) {
SetStates(ElementState::CHECKED, IsRadioOrCheckbox() && mChecked, aNotify);
}
void HTMLInputElement::SetCheckedInternal(bool aChecked, bool aNotify) {
// Set the value
mChecked = aChecked;
// Notify the frame
if (mType == FormControlType::InputCheckbox ||
mType == FormControlType::InputRadio) {
nsIFrame* frame = GetPrimaryFrame();
if (frame) {
if (IsRadioOrCheckbox()) {
if (nsIFrame* frame = GetPrimaryFrame()) {
frame->InvalidateFrameSubtree();
}
SetStates(ElementState::CHECKED, aChecked, aNotify);
}
// No need to update element state, since we're about to call
// UpdateState anyway.
UpdateAllValidityStatesButNotElementState();
// Notify the document that the CSS :checked pseudoclass for this element
// has changed state.
// :indeterminate and validity state still require UpdateState to be called.
UpdateState(aNotify);
// Notify all radios in the group that value has changed, this is to let
@ -3350,8 +3349,7 @@ void HTMLInputElement::CancelRangeThumbDrag(bool aIsForUserEvent) {
// is small, so we should be fine here.)
SetValueInternal(val, {ValueSetterOption::BySetUserInputAPI,
ValueSetterOption::SetValueChanged});
nsRangeFrame* frame = do_QueryFrame(GetPrimaryFrame());
if (frame) {
if (nsRangeFrame* frame = do_QueryFrame(GetPrimaryFrame())) {
frame->UpdateForValueChange();
}
DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchInputEvent(this);
@ -3375,8 +3373,7 @@ void HTMLInputElement::SetValueOfRangeForUserEvent(
// is small, so we should be fine here.)
SetValueInternal(val, {ValueSetterOption::BySetUserInputAPI,
ValueSetterOption::SetValueChanged});
nsRangeFrame* frame = do_QueryFrame(GetPrimaryFrame());
if (frame) {
if (nsRangeFrame* frame = do_QueryFrame(GetPrimaryFrame())) {
frame->UpdateForValueChange();
}
@ -4396,6 +4393,11 @@ void HTMLInputElement::HandleTypeChange(FormControlType aNewType,
UpdatePlaceholderShownState();
// Whether readonly applies might have changed.
UpdateReadOnlyState(aNotify);
UpdateCheckedState(aNotify);
const bool isDefault = IsRadioOrCheckbox()
? DefaultChecked()
: (mForm && mForm->IsDefaultSubmitElement(this));
SetStates(ElementState::DEFAULT, isDefault, aNotify);
// https://html.spec.whatwg.org/#input-type-change
switch (GetValueMode()) {
@ -4473,12 +4475,10 @@ void HTMLInputElement::HandleTypeChange(FormControlType aNewType,
// Update or clear our required states since we may have changed from a
// required input type to a non-required input type or viceversa.
if (DoesRequiredApply()) {
bool isRequired = HasAttr(nsGkAtoms::required);
const bool isRequired = HasAttr(nsGkAtoms::required);
UpdateRequiredState(isRequired, aNotify);
} else if (aNotify) {
RemoveStates(ElementState::REQUIRED_STATES);
} else {
RemoveStatesSilently(ElementState::REQUIRED_STATES);
RemoveStates(ElementState::REQUIRED_STATES, aNotify);
}
UpdateHasRange();
@ -6037,36 +6037,19 @@ void HTMLInputElement::DestroyContent() {
}
ElementState HTMLInputElement::IntrinsicState() const {
// If you add states here, and they're type-dependent, you need to add them
// to the type case in AfterSetAttr.
// If you add states here, and they're type-dependent, you need to add them to
// HandleTypeChange.
ElementState state =
nsGenericHTMLFormControlElementWithState::IntrinsicState();
if (mType == FormControlType::InputCheckbox ||
mType == FormControlType::InputRadio) {
// Check current checked state (:checked)
if (mChecked) {
state |= ElementState::CHECKED;
}
// Check current indeterminate state (:indeterminate)
if (mType == FormControlType::InputCheckbox && mIndeterminate) {
// Check current indeterminate state (:indeterminate)
if (mType == FormControlType::InputCheckbox && mIndeterminate) {
state |= ElementState::INDETERMINATE;
} else if (mType == FormControlType::InputRadio) {
HTMLInputElement* selected = GetSelectedRadioButton();
const bool indeterminate = !selected && !mChecked;
if (indeterminate) {
state |= ElementState::INDETERMINATE;
}
if (mType == FormControlType::InputRadio) {
HTMLInputElement* selected = GetSelectedRadioButton();
bool indeterminate = !selected && !mChecked;
if (indeterminate) {
state |= ElementState::INDETERMINATE;
}
}
// Check whether we are the default checked element (:default)
if (DefaultChecked()) {
state |= ElementState::DEFAULT;
}
} else if (mType == FormControlType::InputImage) {
state |= nsImageLoadingContent::ImageState();
}
@ -6267,7 +6250,6 @@ void HTMLInputElement::WillRemoveFromRadioGroup() {
// longer a selected radio button
if (mChecked) {
container->SetCurrentRadioButton(name, nullptr);
nsCOMPtr<nsIRadioVisitor> visitor = new nsRadioUpdateStateVisitor(this);
VisitGroup(visitor);
}
@ -6815,13 +6797,9 @@ void HTMLInputElement::InitializeKeyboardEventListeners() {
}
void HTMLInputElement::UpdatePlaceholderShownState() {
const bool shown =
IsValueEmpty() && PlaceholderApplies() && HasAttr(nsGkAtoms::placeholder);
if (shown) {
AddStates(ElementState::PLACEHOLDER_SHOWN);
} else {
RemoveStates(ElementState::PLACEHOLDER_SHOWN);
}
SetStates(ElementState::PLACEHOLDER_SHOWN,
IsValueEmpty() && PlaceholderApplies() &&
HasAttr(nsGkAtoms::placeholder));
}
void HTMLInputElement::OnValueChanged(ValueChangeKind aKind,
@ -6833,11 +6811,7 @@ void HTMLInputElement::OnValueChanged(ValueChangeKind aKind,
}
if (aNewValueEmpty != IsValueEmpty()) {
if (aNewValueEmpty) {
AddStates(ElementState::VALUE_EMPTY);
} else {
RemoveStates(ElementState::VALUE_EMPTY);
}
SetStates(ElementState::VALUE_EMPTY, aNewValueEmpty);
UpdatePlaceholderShownState();
}
@ -6876,11 +6850,7 @@ void HTMLInputElement::SetRevealPassword(bool aValue) {
if (NS_WARN_IF(!defaultAction)) {
return;
}
if (aValue) {
AddStates(ElementState::REVEALED);
} else {
RemoveStates(ElementState::REVEALED);
}
SetStates(ElementState::REVEALED, aValue);
}
bool HTMLInputElement::RevealPassword() const {

Просмотреть файл

@ -325,6 +325,7 @@ class HTMLInputElement final : public TextControlElement,
void UpdateStepMismatchValidityState();
void UpdateBadInputValidityState();
void UpdatePlaceholderShownState();
void UpdateCheckedState(bool aNotify);
// Update all our validity states and then update our element state
// as needed. aNotify controls whether the element state update
// needs to notify.
@ -464,6 +465,11 @@ class HTMLInputElement final : public TextControlElement,
bool Checked() const { return mChecked; }
void SetChecked(bool aChecked);
bool IsRadioOrCheckbox() const {
return mType == FormControlType::InputCheckbox ||
mType == FormControlType::InputRadio;
}
bool Disabled() const { return GetBoolAttr(nsGkAtoms::disabled); }
void SetDisabled(bool aValue, ErrorResult& aRv) {

Просмотреть файл

@ -33,10 +33,7 @@ namespace mozilla::dom {
HTMLOptionElement::HTMLOptionElement(
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
: nsGenericHTMLElement(std::move(aNodeInfo)),
mSelectedChanged(false),
mIsSelected(false),
mIsInSetDefaultSelected(false) {
: nsGenericHTMLElement(std::move(aNodeInfo)) {
// We start off enabled
AddStatesSilently(ElementState::ENABLED);
}
@ -52,13 +49,7 @@ mozilla::dom::HTMLFormElement* HTMLOptionElement::GetForm() {
void HTMLOptionElement::SetSelectedInternal(bool aValue, bool aNotify) {
mSelectedChanged = true;
mIsSelected = aValue;
// When mIsInSetDefaultSelected is true, the state change will be handled by
// SetAttr/UnsetAttr.
if (!mIsInSetDefaultSelected) {
UpdateState(aNotify);
}
SetStates(ElementState::CHECKED, aValue, aNotify);
}
void HTMLOptionElement::OptGroupDisabledChanged(bool aNotify) {
@ -156,9 +147,9 @@ void HTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
// it.
HTMLSelectElement* selectInt = GetSelect();
if (!selectInt) {
// If option is a child of select, SetOptionsSelectedByIndex will set
// mIsSelected if needed.
mIsSelected = aValue;
// If option is a child of select, SetOptionsSelectedByIndex will set the
// selected state if needed.
SetStates(ElementState::CHECKED, !!aValue, aNotify);
return;
}
@ -187,8 +178,9 @@ void HTMLOptionElement::BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
// Now reset our members; when we finish the attr set we'll end up with the
// rigt selected state.
mIsInSetDefaultSelected = inSetDefaultSelected;
// mIsSelected might have been changed by SetOptionsSelectedByIndex. Possibly
// more than once; make sure our mSelectedChanged state is set back correctly.
// the selected state might have been changed by SetOptionsSelectedByIndex,
// possibly more than once; make sure our mSelectedChanged state is set back
// correctly.
mSelectedChanged = false;
}
@ -203,14 +195,16 @@ void HTMLOptionElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
}
if (aName == nsGkAtoms::value && Selected()) {
// Since this option is selected, changing value
// may have changed missing validity state of the
// Select element
HTMLSelectElement* select = GetSelect();
if (select) {
// Since this option is selected, changing value may have changed missing
// validity state of the select element
if (HTMLSelectElement* select = GetSelect()) {
select->UpdateValueMissingValidityState();
}
}
if (aName == nsGkAtoms::selected) {
SetStates(ElementState::DEFAULT, !!aValue, aNotify);
}
}
return nsGenericHTMLElement::AfterSetAttr(
@ -260,18 +254,6 @@ void HTMLOptionElement::UnbindFromTree(bool aNullParent) {
UpdateDisabledState(false);
}
ElementState HTMLOptionElement::IntrinsicState() const {
ElementState state = nsGenericHTMLElement::IntrinsicState();
if (Selected()) {
state |= ElementState::CHECKED;
}
if (DefaultSelected()) {
state |= ElementState::DEFAULT;
}
return state;
}
// Get the select content element that contains this option
HTMLSelectElement* HTMLOptionElement::GetSelect() {
nsIContent* parent = GetParent();

Просмотреть файл

@ -32,7 +32,7 @@ class HTMLOptionElement final : public nsGenericHTMLElement {
using mozilla::dom::Element::GetText;
bool Selected() const { return mIsSelected; }
bool Selected() const { return State().HasState(ElementState::CHECKED); }
void SetSelected(bool aValue);
void SetSelectedChanged(bool aValue) { mSelectedChanged = aValue; }
@ -64,9 +64,6 @@ class HTMLOptionElement final : public nsGenericHTMLElement {
nsresult BindToTree(BindContext&, nsINode& aParent) override;
void UnbindFromTree(bool aNullParent = true) override;
// nsIContent
ElementState IntrinsicState() const override;
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
nsresult CopyInnerTo(mozilla::dom::Element* aDest);
@ -125,12 +122,11 @@ class HTMLOptionElement final : public nsGenericHTMLElement {
*/
HTMLSelectElement* GetSelect();
bool mSelectedChanged;
bool mIsSelected;
bool mSelectedChanged = false;
// True only while we're under the SetOptionsSelectedByIndex call when our
// "selected" attribute is changing and mSelectedChanged is false.
bool mIsInSetDefaultSelected;
bool mIsInSetDefaultSelected = false;
};
} // namespace mozilla::dom

Просмотреть файл

@ -1120,12 +1120,8 @@ void HTMLTextAreaElement::InitializeKeyboardEventListeners() {
}
void HTMLTextAreaElement::UpdatePlaceholderShownState() {
const bool shown = IsValueEmpty() && HasAttr(nsGkAtoms::placeholder);
if (shown) {
AddStates(ElementState::PLACEHOLDER_SHOWN);
} else {
RemoveStates(ElementState::PLACEHOLDER_SHOWN);
}
SetStates(ElementState::PLACEHOLDER_SHOWN,
IsValueEmpty() && HasAttr(nsGkAtoms::placeholder));
}
void HTMLTextAreaElement::OnValueChanged(ValueChangeKind aKind,
@ -1136,11 +1132,7 @@ void HTMLTextAreaElement::OnValueChanged(ValueChangeKind aKind,
}
if (aNewValueEmpty != IsValueEmpty()) {
if (aNewValueEmpty) {
AddStates(ElementState::VALUE_EMPTY);
} else {
RemoveStates(ElementState::VALUE_EMPTY);
}
SetStates(ElementState::VALUE_EMPTY, aNewValueEmpty);
UpdatePlaceholderShownState();
}

Просмотреть файл

@ -2035,10 +2035,8 @@ void nsGenericHTMLFormElement::UpdateFormOwner(bool aBindToTree,
MOZ_ASSERT(!aBindToTree || !aFormIdElement,
"aFormIdElement shouldn't be set if aBindToTree is true!");
bool needStateUpdate = false;
HTMLFormElement* form = GetFormInternal();
if (!aBindToTree) {
needStateUpdate = form && form->IsDefaultSubmitElement(this);
ClearForm(true, false);
form = nullptr;
}
@ -2101,7 +2099,7 @@ void nsGenericHTMLFormElement::UpdateFormOwner(bool aBindToTree,
}
}
if (form != oldForm || needStateUpdate) {
if (form != oldForm) {
UpdateState(true);
}
}
@ -2625,22 +2623,6 @@ void nsGenericHTMLFormControlElement::ClearForm(bool aRemoveFromForm,
nsGenericHTMLFormElement::ClearForm(aRemoveFromForm, aUnbindOrDelete);
}
ElementState nsGenericHTMLFormControlElement::IntrinsicState() const {
// If you add attribute-dependent states here, you need to add them to
// AfterSetAttr too. And add them to AfterSetAttr for all subclasses that
// implement IntrinsicState() and are affected by that attribute.
ElementState state = nsGenericHTMLFormElement::IntrinsicState();
if (mForm && mForm->IsDefaultSubmitElement(this)) {
NS_ASSERTION(IsSubmitControl(),
"Default submit element that isn't a submit control.");
// We are the default submit element (:default)
state |= ElementState::DEFAULT;
}
return state;
}
bool nsGenericHTMLFormControlElement::IsLabelable() const {
auto type = ControlType();
return (IsInputElement(type) && type != FormControlType::InputHidden) ||

Просмотреть файл

@ -1156,7 +1156,6 @@ class nsGenericHTMLFormControlElement : public nsGenericHTMLFormElement,
virtual ~nsGenericHTMLFormControlElement();
// Element
mozilla::dom::ElementState IntrinsicState() const override;
bool IsLabelable() const override;
// nsGenericHTMLFormElement

Просмотреть файл

@ -43,7 +43,6 @@ bool nsRadioUpdateStateVisitor::Visit(HTMLInputElement* aRadio) {
if (aRadio == mExcludeElement) {
return true;
}
aRadio->UpdateState(true);
return true;
}