https://bugs.webkit.org/show_bug.cgi?id=129084
Reviewed by Benjamin Poulain.
Source/WebCore:
In order to resolve the bug 129035, a text form control elements needs to synchronously change
its inner text element's editability by setting or unsetting contenteditable content attribute.
Before this patch, we could not do this because editability of a text form control dependent on
its disabled-ness which was only computed lazily via updateAncestorDisabledState().
This patch makes HTMLFieldSetElement and HTMLFormControlElement update this state synchronously.
To avoid O(k) DOM traversal, where k is the depth of the tree, in insertedInto and removedFrom of
HTMLFormControlElement on most pages, a new document-level flag, m_disabledFieldsetElementsCount,
has been added to indicate whether the document contains any disabled fieldset or not.
Also renamed the misleadingly named disabledAttributeChanged to disabledStateChanged, and added
new function of the same name (disabledAttributeChanged) to be used by HTMLFieldSetElement
for keeping the document-level flag up-to-date upon disabled attribute changes.
Tests: fast/forms/fieldset/fieldset-disabled-2.html
* dom/Document.cpp:
(WebCore::Document::Document): Initializes newly added m_disabledFieldsetElementsCount.
(WebCore::Document::~Document): Assert that we've done house keeping right.
* dom/Document.h:
(WebCore::Document::hasDisabledFieldsetElement): Added.
(WebCore::Document::addDisabledFieldsetElement): Added.
(WebCore::Document::removeDisabledFieldsetElement): Added.
* html/HTMLFieldSetElement.cpp:
(WebCore::HTMLFieldSetElement::~HTMLFieldSetElement): Removes itself from the owner document.
(WebCore::updateFromControlElementsAncestorDisabledStateUnder): Added. Updates startNode and
its descendants' ancestor disabled flag. We don't update controls under another disabled
fieldset element since disabled-ness of those controls aren't affected by startNode.
(WebCore::HTMLFieldSetElement::disabledAttributeChanged): Call addDisabledFieldsetElement and
removeDisabledFieldsetElement to update the owner document's flag.
(WebCore::HTMLFieldSetElement::disabledStateChanged): Renamed from disabledAttributeChanged.
Enable form control elements under the first legend element and disable or enable other
descendent form controls in accordance with the presence of disabled content attribute.
(WebCore::HTMLFieldSetElement::childrenChanged): Update disabled-ness of form controls under
child legend elements because controls aren't disabled in the first legend element, and adding
or removing child elements may have changed the first legend element.
(WebCore::HTMLFieldSetElement::didMoveToNewDocument): Update the flag on the owner document.
* html/HTMLFieldSetElement.h:
* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::HTMLFormControlElement):
(WebCore::HTMLFormControlElement::computeIsDisabledByFieldsetAncestor): Returns boolean instead of
updating m_ancestorDisabledState internally. Also renamed from updateAncestorDisabledState.
(WebCore::HTMLFormControlElement::setAncestorDisabled): Replaced ancestorDisabledStateWasChanged.
This function updates m_disabledByAncestorFieldset and calls disabledAttributeChanged as needed.
(WebCore::HTMLFormControlElement::disabledAttributeChanged): Added. Calls disabledStateChanged.
(WebCore::HTMLFormControlElement::disabledStateChanged): Renamed from disabledAttributeChanged.
(WebCore::HTMLFormControlElement::insertedInto): Update m_disabledByAncestorFieldset if there is
a possibility (i.e. the document contains any disabled fieldset element) that this form control
is inserted under a disabled fieldset element.
(WebCore::HTMLFormControlElement::removedFrom): If this form control element is not disabled by
a fieldset ancestor, then there is nothing to do. If it is, then check to see if the element is
still disabled now that we've lost some ancestors.
(WebCore::HTMLFormControlElement::isDisabledFormControl): No longer updates m_ancestorDisabledState
lazily since m_disabledByAncestorFieldset is never ambiguous now.
* html/HTMLFormControlElement.h:
(WebCore::HTMLFormControlElement::disabledByAncestorFieldset): Added.
LayoutTests:
Added more test cases.
* fast/forms/fieldset/fieldset-disabled-2-expected.txt:
* fast/forms/fieldset/fieldset-disabled-2.html:
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@164475
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2014-02-19 Ryosuke Niwa <rniwa@webkit.org>
+
+ m_ancestorDisabledState should never be unknown
+ https://bugs.webkit.org/show_bug.cgi?id=129084
+
+ Reviewed by Benjamin Poulain.
+
+ Added more test cases.
+
+ * fast/forms/fieldset/fieldset-disabled-2-expected.txt:
+ * fast/forms/fieldset/fieldset-disabled-2.html:
+
2014-02-20 Joseph Pecoraro <pecoraro@apple.com>
[iOS] Assert / crash trying to draw empty checked input
PASS isInputDisabledById("inputInsideSecondLegend") is false
PASS isInputDisabledById("inputInsideNestedFirstLegend") is false
PASS isInputDisabledById("inputInsideFirstLegendWithDisabledOuterFieldset") is false
+
+contentDocument = createIframe();
+fieldset = contentDocument.createElement("fieldset"); contentDocument.body.appendChild(fieldset);
+PASS input = contentDocument.createElement("input"); fieldset.appendChild(input); isInputDisabled(input) is false
+PASS fieldset.disabled = true; isInputDisabled(input) is true
+PASS contentDocument.body.appendChild(input); isInputDisabled(input) is false
+PASS document.body.appendChild(input); isInputDisabled(input) is false
+PASS fieldset.appendChild(input); isInputDisabled(input) is true
+fieldset2 = document.createElement("fieldset"); fieldset2.disabled = true
+input2 = document.createElement("input"); fieldset2.appendChild(input2)
+PASS contentDocument.body.appendChild(fieldset2); isInputDisabled(input2) is true
+PASS document.body.appendChild(fieldset); isInputDisabled(input) is true
+
+setDisabledOnAllFieldsets(true)
+PASS isInputDisabledById("inputOutsideLegend") is true
+PASS isInputDisabledById("inputInsideFirstLegend") is false
+PASS isInputDisabledById("inputInsideSecondLegend") is true
+PASS isInputDisabledById("inputInsideNestedFirstLegend") is false
+PASS isInputDisabledById("inputInsideFirstLegendWithDisabledOuterFieldset") is true
PASS successfullyParsed is true
TEST COMPLETE
description("Additional tests for fieldset element disabling descendent input elements");
-function isInputDisabledById(id) {
- var input = document.getElementById(id);
+function isInputDisabled(input) {
return getComputedStyle(input).color == 'rgb(102, 102, 102)';
}
+function isInputDisabledById(id) {
+ return isInputDisabled(document.getElementById(id));
+}
+
shouldBeTrue('isInputDisabledById("inputOutsideLegend")');
shouldBeFalse('isInputDisabledById("inputInsideFirstLegend")');
shouldBeTrue('isInputDisabledById("inputInsideSecondLegend")');
shouldBeTrue('isInputDisabledById("inputInsideFirstLegendWithDisabledOuterFieldset")');
function setDisabledOnAllFieldsets(value) {
- var fieldsets = document.querySelectorAll('fieldset');
+ var fieldsets = document.querySelectorAll('#container > fieldset, body > fieldset');
for (var i = 0; i < fieldsets.length; i++)
fieldsets[i].disabled = value;
}
shouldBeFalse('isInputDisabledById("inputInsideNestedFirstLegend")');
shouldBeFalse('isInputDisabledById("inputInsideFirstLegendWithDisabledOuterFieldset")');
+function createIframe() {
+ var iframe = document.createElement("iframe");
+ document.getElementById('container').appendChild(iframe);
+ iframe.contentDocument.head.appendChild(document.querySelector('body style').cloneNode(true));
+ return iframe.contentDocument;
+}
+
+function insertNewFieldsetIntoBody(contentDocument) {
+ fieldset = contentDocument.createElement("fieldset");
+ contentDocument.body.appendChild(fieldset);
+ return fieldset;
+}
+
+debug('');
+evalAndLog('contentDocument = createIframe();');
+evalAndLog('fieldset = contentDocument.createElement("fieldset"); contentDocument.body.appendChild(fieldset);');
+shouldBeFalse('input = contentDocument.createElement("input"); fieldset.appendChild(input); isInputDisabled(input)');
+shouldBeTrue('fieldset.disabled = true; isInputDisabled(input)');
+shouldBeFalse('contentDocument.body.appendChild(input); isInputDisabled(input)');
+shouldBeFalse('document.body.appendChild(input); isInputDisabled(input)');
+shouldBeTrue('fieldset.appendChild(input); isInputDisabled(input)');
+evalAndLog('fieldset2 = document.createElement("fieldset"); fieldset2.disabled = true');
+evalAndLog('input2 = document.createElement("input"); fieldset2.appendChild(input2)');
+shouldBeTrue('contentDocument.body.appendChild(fieldset2); isInputDisabled(input2)');
+shouldBeTrue('document.body.appendChild(fieldset); isInputDisabled(input)');
+
+debug('');
+evalAndLog('setDisabledOnAllFieldsets(true)');
+shouldBeTrue('isInputDisabledById("inputOutsideLegend")');
+shouldBeFalse('isInputDisabledById("inputInsideFirstLegend")');
+shouldBeTrue('isInputDisabledById("inputInsideSecondLegend")');
+shouldBeFalse('isInputDisabledById("inputInsideNestedFirstLegend")');
+shouldBeTrue('isInputDisabledById("inputInsideFirstLegendWithDisabledOuterFieldset")');
+
document.getElementById('container').style.display = 'none';
</script>
+2014-02-20 Ryosuke Niwa <rniwa@webkit.org>
+
+ m_ancestorDisabledState should never be unknown
+ https://bugs.webkit.org/show_bug.cgi?id=129084
+
+ Reviewed by Benjamin Poulain.
+
+ In order to resolve the bug 129035, a text form control elements needs to synchronously change
+ its inner text element's editability by setting or unsetting contenteditable content attribute.
+ Before this patch, we could not do this because editability of a text form control dependent on
+ its disabled-ness which was only computed lazily via updateAncestorDisabledState().
+
+ This patch makes HTMLFieldSetElement and HTMLFormControlElement update this state synchronously.
+ To avoid O(k) DOM traversal, where k is the depth of the tree, in insertedInto and removedFrom of
+ HTMLFormControlElement on most pages, a new document-level flag, m_disabledFieldsetElementsCount,
+ has been added to indicate whether the document contains any disabled fieldset or not.
+
+ Also renamed the misleadingly named disabledAttributeChanged to disabledStateChanged, and added
+ new function of the same name (disabledAttributeChanged) to be used by HTMLFieldSetElement
+ for keeping the document-level flag up-to-date upon disabled attribute changes.
+
+ Tests: fast/forms/fieldset/fieldset-disabled-2.html
+
+ * dom/Document.cpp:
+ (WebCore::Document::Document): Initializes newly added m_disabledFieldsetElementsCount.
+ (WebCore::Document::~Document): Assert that we've done house keeping right.
+ * dom/Document.h:
+ (WebCore::Document::hasDisabledFieldsetElement): Added.
+ (WebCore::Document::addDisabledFieldsetElement): Added.
+ (WebCore::Document::removeDisabledFieldsetElement): Added.
+
+ * html/HTMLFieldSetElement.cpp:
+ (WebCore::HTMLFieldSetElement::~HTMLFieldSetElement): Removes itself from the owner document.
+
+ (WebCore::updateFromControlElementsAncestorDisabledStateUnder): Added. Updates startNode and
+ its descendants' ancestor disabled flag. We don't update controls under another disabled
+ fieldset element since disabled-ness of those controls aren't affected by startNode.
+
+ (WebCore::HTMLFieldSetElement::disabledAttributeChanged): Call addDisabledFieldsetElement and
+ removeDisabledFieldsetElement to update the owner document's flag.
+
+ (WebCore::HTMLFieldSetElement::disabledStateChanged): Renamed from disabledAttributeChanged.
+ Enable form control elements under the first legend element and disable or enable other
+ descendent form controls in accordance with the presence of disabled content attribute.
+
+ (WebCore::HTMLFieldSetElement::childrenChanged): Update disabled-ness of form controls under
+ child legend elements because controls aren't disabled in the first legend element, and adding
+ or removing child elements may have changed the first legend element.
+
+ (WebCore::HTMLFieldSetElement::didMoveToNewDocument): Update the flag on the owner document.
+ * html/HTMLFieldSetElement.h:
+
+ * html/HTMLFormControlElement.cpp:
+ (WebCore::HTMLFormControlElement::HTMLFormControlElement):
+ (WebCore::HTMLFormControlElement::computeIsDisabledByFieldsetAncestor): Returns boolean instead of
+ updating m_ancestorDisabledState internally. Also renamed from updateAncestorDisabledState.
+
+ (WebCore::HTMLFormControlElement::setAncestorDisabled): Replaced ancestorDisabledStateWasChanged.
+ This function updates m_disabledByAncestorFieldset and calls disabledAttributeChanged as needed.
+
+ (WebCore::HTMLFormControlElement::disabledAttributeChanged): Added. Calls disabledStateChanged.
+ (WebCore::HTMLFormControlElement::disabledStateChanged): Renamed from disabledAttributeChanged.
+
+ (WebCore::HTMLFormControlElement::insertedInto): Update m_disabledByAncestorFieldset if there is
+ a possibility (i.e. the document contains any disabled fieldset element) that this form control
+ is inserted under a disabled fieldset element.
+
+ (WebCore::HTMLFormControlElement::removedFrom): If this form control element is not disabled by
+ a fieldset ancestor, then there is nothing to do. If it is, then check to see if the element is
+ still disabled now that we've lost some ancestors.
+
+ (WebCore::HTMLFormControlElement::isDisabledFormControl): No longer updates m_ancestorDisabledState
+ lazily since m_disabledByAncestorFieldset is never ambiguous now.
+
+ * html/HTMLFormControlElement.h:
+ (WebCore::HTMLFormControlElement::disabledByAncestorFieldset): Added.
+
2014-02-20 Zalan Bujtas <zalan@apple.com>
Remove redundant deviceScaleFactor() functions and make callers use Document::deviceScaleFactor() when accessible.
, m_inputCursor(EmptyInputCursor::create())
#endif
, m_didAssociateFormControlsTimer(this, &Document::didAssociateFormControlsTimerFired)
+ , m_disabledFieldsetElementsCount(0)
, m_hasInjectedPlugInsScript(false)
, m_renderTreeBeingDestroyed(false)
{
ASSERT(!m_inPageCache);
ASSERT(m_ranges.isEmpty());
ASSERT(!m_parentTreeScope);
+ ASSERT(!m_disabledFieldsetElementsCount);
#if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS)
m_deviceMotionClient->deviceMotionControllerDestroyed();
#endif
void didAssociateFormControl(Element*);
+ bool hasDisabledFieldsetElement() const { return m_disabledFieldsetElementsCount; }
+ void addDisabledFieldsetElement() { m_disabledFieldsetElementsCount++; }
+ void removeDisabledFieldsetElement() { ASSERT(m_disabledFieldsetElementsCount); m_disabledFieldsetElementsCount--; }
virtual void addConsoleMessage(MessageSource, MessageLevel, const String& message, unsigned long requestIdentifier = 0) override;
Timer<Document> m_didAssociateFormControlsTimer;
HashSet<RefPtr<Element>> m_associatedFormControls;
+ unsigned m_disabledFieldsetElementsCount;
bool m_hasInjectedPlugInsScript;
bool m_renderTreeBeingDestroyed;
ASSERT(hasTagName(fieldsetTag));
}
+HTMLFieldSetElement::~HTMLFieldSetElement()
+{
+ if (hasAttribute(disabledAttr))
+ document().removeDisabledFieldsetElement();
+}
+
PassRefPtr<HTMLFieldSetElement> HTMLFieldSetElement::create(const QualifiedName& tagName, Document& document, HTMLFormElement* form)
{
return adoptRef(new HTMLFieldSetElement(tagName, document, form));
}
-void HTMLFieldSetElement::invalidateDisabledStateUnder(Element* base)
+static void updateFromControlElementsAncestorDisabledStateUnder(HTMLElement& startNode, bool isDisabled)
{
- for (auto& control : descendantsOfType<HTMLFormControlElement>(*base))
- control.ancestorDisabledStateWasChanged();
+ HTMLFormControlElement* control;
+ if (isHTMLFormControlElement(startNode))
+ control = &toHTMLFormControlElement(startNode);
+ else
+ control = Traversal<HTMLFormControlElement>::firstWithin(&startNode);
+ while (control) {
+ control->setAncestorDisabled(isDisabled);
+ // Don't call setAncestorDisabled(false) on form contorls inside disabled fieldsets.
+ if (isHTMLFieldSetElement(control) && control->hasAttribute(disabledAttr))
+ control = Traversal<HTMLFormControlElement>::nextSkippingChildren(control, &startNode);
+ else
+ control = Traversal<HTMLFormControlElement>::next(control, &startNode);
+ }
}
void HTMLFieldSetElement::disabledAttributeChanged()
{
- // This element must be updated before the style of nodes in its subtree gets recalculated.
+ if (hasAttribute(disabledAttr))
+ document().addDisabledFieldsetElement();
+ else
+ document().removeDisabledFieldsetElement();
+
HTMLFormControlElement::disabledAttributeChanged();
- invalidateDisabledStateUnder(this);
+}
+
+void HTMLFieldSetElement::disabledStateChanged()
+{
+ // This element must be updated before the style of nodes in its subtree gets recalculated.
+ HTMLFormControlElement::disabledStateChanged();
+
+ if (disabledByAncestorFieldset())
+ return;
+
+ bool thisFieldsetIsDisabled = hasAttribute(disabledAttr);
+ bool hasSeenFirstLegendElement = false;
+ for (auto& control : childrenOfType<HTMLElement>(*this)) {
+ if (!hasSeenFirstLegendElement && isHTMLLegendElement(control)) {
+ hasSeenFirstLegendElement = true;
+ updateFromControlElementsAncestorDisabledStateUnder(control, false /* isDisabled */);
+ continue;
+ }
+ updateFromControlElementsAncestorDisabledStateUnder(control, thisFieldsetIsDisabled);
+ }
}
void HTMLFieldSetElement::childrenChanged(const ChildChange& change)
{
HTMLFormControlElement::childrenChanged(change);
+ if (!hasAttribute(disabledAttr))
+ return;
+
+ HTMLLegendElement* legend = Traversal<HTMLLegendElement>::firstChild(this);
+ if (!legend)
+ return;
+
+ // We only care about the first legend element (in which form contorls are not disabled by this element) changing here.
+ updateFromControlElementsAncestorDisabledStateUnder(*legend, false /* isDisabled */);
+ while ((legend = Traversal<HTMLLegendElement>::nextSibling(legend)))
+ updateFromControlElementsAncestorDisabledStateUnder(*legend, true);
+}
- for (auto& legend : childrenOfType<HTMLLegendElement>(*this))
- invalidateDisabledStateUnder(&legend);
+void HTMLFieldSetElement::didMoveToNewDocument(Document* oldDocument)
+{
+ HTMLFormControlElement::didMoveToNewDocument(oldDocument);
+ if (hasAttribute(disabledAttr)) {
+ if (oldDocument)
+ oldDocument->removeDisabledFieldsetElement();
+ document().addDisabledFieldsetElement();
+ }
}
bool HTMLFieldSetElement::supportsFocus() const
unsigned length() const;
protected:
- virtual void disabledAttributeChanged() override;
private:
HTMLFieldSetElement(const QualifiedName&, Document&, HTMLFormElement*);
+ ~HTMLFieldSetElement();
virtual bool isEnumeratable() const override { return true; }
virtual bool supportsFocus() const override;
virtual RenderPtr<RenderElement> createElementRenderer(PassRef<RenderStyle>) override;
virtual const AtomicString& formControlType() const override;
virtual bool recalcWillValidate() const override { return false; }
+ virtual void disabledAttributeChanged() override;
+ virtual void disabledStateChanged() override;
virtual void childrenChanged(const ChildChange&) override;
+ virtual void didMoveToNewDocument(Document* oldDocument) override;
- static void invalidateDisabledStateUnder(Element*);
void refreshElementsIfNeeded() const;
mutable Vector<FormAssociatedElement*> m_associatedElements;
, m_isReadOnly(false)
, m_isRequired(false)
, m_valueMatchesRenderer(false)
- , m_ancestorDisabledState(AncestorDisabledStateUnknown)
+ , m_disabledByAncestorFieldset(false)
, m_dataListAncestorState(Unknown)
, m_willValidateInitialized(false)
, m_willValidate(true)
return fastHasAttribute(formnovalidateAttr);
}
-void HTMLFormControlElement::updateAncestorDisabledState() const
+bool HTMLFormControlElement::computeIsDisabledByFieldsetAncestor() const
{
Element* previousAncestor = nullptr;
for (Element* ancestor = parentElement(); ancestor; ancestor = ancestor->parentElement()) {
if (isHTMLFieldSetElement(ancestor) && ancestor->hasAttribute(disabledAttr)) {
HTMLFieldSetElement& fieldSetAncestor = toHTMLFieldSetElement(*ancestor);
bool isInFirstLegend = previousAncestor && isHTMLLegendElement(previousAncestor) && previousAncestor == fieldSetAncestor.legend();
- m_ancestorDisabledState = isInFirstLegend ? AncestorDisabledStateEnabled : AncestorDisabledStateDisabled;
- return;
+ return !isInFirstLegend;
}
previousAncestor = ancestor;
}
- m_ancestorDisabledState = AncestorDisabledStateEnabled;
+ return false;
}
-void HTMLFormControlElement::ancestorDisabledStateWasChanged()
+void HTMLFormControlElement::setAncestorDisabled(bool isDisabled)
{
- m_ancestorDisabledState = AncestorDisabledStateUnknown;
- disabledAttributeChanged();
+ ASSERT(computeIsDisabledByFieldsetAncestor() == isDisabled);
+ bool oldValue = m_disabledByAncestorFieldset;
+ m_disabledByAncestorFieldset = isDisabled;
+ if (oldValue != m_disabledByAncestorFieldset)
+ disabledStateChanged();
}
void HTMLFormControlElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
}
void HTMLFormControlElement::disabledAttributeChanged()
+{
+ disabledStateChanged();
+}
+
+void HTMLFormControlElement::disabledStateChanged()
{
setNeedsWillValidateCheck();
didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled);
Node::InsertionNotificationRequest HTMLFormControlElement::insertedInto(ContainerNode& insertionPoint)
{
- m_ancestorDisabledState = AncestorDisabledStateUnknown;
+ if (document().hasDisabledFieldsetElement())
+ setAncestorDisabled(computeIsDisabledByFieldsetAncestor());
m_dataListAncestorState = Unknown;
setNeedsWillValidateCheck();
HTMLElement::insertedInto(insertionPoint);
void HTMLFormControlElement::removedFrom(ContainerNode& insertionPoint)
{
m_validationMessage = nullptr;
- m_ancestorDisabledState = AncestorDisabledStateUnknown;
+ if (m_disabledByAncestorFieldset)
+ setAncestorDisabled(computeIsDisabledByFieldsetAncestor());
m_dataListAncestorState = Unknown;
HTMLElement::removedFrom(insertionPoint);
FormAssociatedElement::removedFrom(insertionPoint);
bool HTMLFormControlElement::isDisabledFormControl() const
{
- if (m_disabled)
- return true;
-
- if (m_ancestorDisabledState == AncestorDisabledStateUnknown)
- updateAncestorDisabledState();
- if (m_ancestorDisabledState == AncestorDisabledStateDisabled)
- return true;
- return HTMLElement::isDisabledFormControl();
+ return m_disabled || m_disabledByAncestorFieldset;
}
bool HTMLFormControlElement::isRequired() const
void setFormMethod(const String&);
bool formNoValidate() const;
- void ancestorDisabledStateWasChanged();
+ void setAncestorDisabled(bool isDisabled);
virtual void reset() { }
protected:
HTMLFormControlElement(const QualifiedName& tagName, Document&, HTMLFormElement*);
+ bool disabledByAncestorFieldset() const { return m_disabledByAncestorFieldset; }
+
virtual void parseAttribute(const QualifiedName&, const AtomicString&) override;
virtual void requiredAttributeChanged();
virtual void disabledAttributeChanged();
+ virtual void disabledStateChanged();
virtual void didAttachRenderers() override;
virtual InsertionNotificationRequest insertedInto(ContainerNode&) override;
virtual void removedFrom(ContainerNode&) override;
virtual HTMLFormElement* virtualForm() const override;
virtual bool isDefaultButtonForForm() const override;
virtual bool isValidFormControlElement() const override;
- void updateAncestorDisabledState() const;
+
+ bool computeIsDisabledByFieldsetAncestor() const;
virtual HTMLElement& asHTMLElement() override final { return *this; }
virtual const HTMLFormControlElement& asHTMLElement() const override final { return *this; }
bool m_isReadOnly : 1;
bool m_isRequired : 1;
bool m_valueMatchesRenderer : 1;
+ bool m_disabledByAncestorFieldset : 1;
- enum AncestorDisabledState { AncestorDisabledStateUnknown, AncestorDisabledStateEnabled, AncestorDisabledStateDisabled };
- mutable AncestorDisabledState m_ancestorDisabledState;
enum DataListAncestorState { Unknown, InsideDataList, NotInsideDataList };
mutable enum DataListAncestorState m_dataListAncestorState;