Title: [242309] trunk
Revision
242309
Author
[email protected]
Date
2019-03-01 22:09:31 -0800 (Fri, 01 Mar 2019)

Log Message

[Datalist] fast/forms/datalist/datalist-child-validation.html crashes with a debug assertion in isValidFormControlElement()
https://bugs.webkit.org/show_bug.cgi?id=190620
<rdar://problem/19226679>

Reviewed by Ryosuke Niwa.

Source/WebCore:

Fixes and re-enables an existing layout test that is asserting on debug builds (and failing on release builds).
To understand why we hit this assertion, we first note several observations:

    -   The validity of a form control (`isValid()`) depends on the value of `willValidate()`.
    -   Both of these results are cached in member variables: `m_isValid` and `m_willValidate`, respectively.
    -   `willValidate()` changes the cached value of `m_willValidate` if necessary, but `isValid()` uses the
        cached value without update.

Now, consider the following scenario:

    1.  Something changes in the DOM that changes the result of `willValidate()`. This can happen as a result of
        several things:
        a.  The form control changes readonly state
        b.  The form control changes disabled state
        c.  The form control is added to a datalist element
        d.  The form control is removed from a datalist element
    2.  Call `willValidate()`.
    3.  Call `isValid()`.

In scenarios (a) - (c), we ensure that cached form control validity (`m_isValid`) is updated alongside
`m_willValidate` by invoking `setNeedsWillValidateCheck()`, such that the result of `isValid()` matches the
result of `m_isValid` in step (3). However, in the last scenario (d), we don't do this, which causes form
control validity to fall out of sync with the result of `isValid()`. To fix the bug, we update willValidate and
isValid when a form control is removed from an ancestor, only if one of its ancestors is a datalist element.

* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::insertedIntoAncestor):
(WebCore::HTMLFormControlElement::removedFromAncestor):

Make a couple of minor tweaks:
  - Currently, we always invalidate `m_dataListAncestorState` by resetting the state to `Unknown` when the form
    control is removed from an ancestor or inserted. Instead, we only need to reset it when the form control
    already has an ancestor that is a datalist (in the case where it's being removed) or when the form control
    does not yet have an ancestor (in the case where it is being added).
  - If the form control was inside a datalist prior to removal, recompute its cached value of `m_willValidate`,
    as well as its cached validity (`m_isValid`).

LayoutTests:

Re-enables a crashing layout test. See WebCore ChangeLog for more details.

* platform/ios/TestExpectations:
* platform/mac/TestExpectations:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (242308 => 242309)


--- trunk/LayoutTests/ChangeLog	2019-03-02 05:45:11 UTC (rev 242308)
+++ trunk/LayoutTests/ChangeLog	2019-03-02 06:09:31 UTC (rev 242309)
@@ -1,3 +1,16 @@
+2019-03-01  Wenson Hsieh  <[email protected]>
+
+        [Datalist] fast/forms/datalist/datalist-child-validation.html crashes with a debug assertion in isValidFormControlElement()
+        https://bugs.webkit.org/show_bug.cgi?id=190620
+        <rdar://problem/19226679>
+
+        Reviewed by Ryosuke Niwa.
+
+        Re-enables a crashing layout test. See WebCore ChangeLog for more details.
+
+        * platform/ios/TestExpectations:
+        * platform/mac/TestExpectations:
+
 2019-03-01  Zalan Bujtas  <[email protected]>
 
         [ContentChangeObserver] Check for pending style recalcs at the end of each timer run.

Modified: trunk/LayoutTests/platform/ios/TestExpectations (242308 => 242309)


--- trunk/LayoutTests/platform/ios/TestExpectations	2019-03-02 05:45:11 UTC (rev 242308)
+++ trunk/LayoutTests/platform/ios/TestExpectations	2019-03-02 06:09:31 UTC (rev 242309)
@@ -1962,8 +1962,6 @@
 # <rdar://problem/19226623> ASSERT(isIdentifierStart<CharacterType>()) fails in CSSParser::parseIdentifier()
 fast/css/css-selector-text.html
 
-webkit.org/b/190620 fast/forms/datalist/datalist-child-validation.html [ Skip ]
-
 # <rdar://problem/19227549> ASSERT(!m_webFrame->_private->provisionalURL) fails in WebFrameLoaderClient::dispatchDidStartProvisionalLoad()
 fast/forms/validation-message-user-modify.html
 

Modified: trunk/LayoutTests/platform/mac/TestExpectations (242308 => 242309)


--- trunk/LayoutTests/platform/mac/TestExpectations	2019-03-02 05:45:11 UTC (rev 242308)
+++ trunk/LayoutTests/platform/mac/TestExpectations	2019-03-02 06:09:31 UTC (rev 242309)
@@ -131,9 +131,6 @@
 # EventSender::dumpFilenameBeingDragged not implemented.
 webkit.org/b/61827 fast/events/drag-image-filename.html
 
-# Datalist
-webkit.org/b/190620 fast/forms/datalist/datalist-child-validation.html [ Skip ]
-
 # ENABLE_INPUT_TYPE_* are not enabled.
 # https://bugs.webkit.org/show_bug.cgi?id=29359
 fast/forms/date

Modified: trunk/Source/WebCore/ChangeLog (242308 => 242309)


--- trunk/Source/WebCore/ChangeLog	2019-03-02 05:45:11 UTC (rev 242308)
+++ trunk/Source/WebCore/ChangeLog	2019-03-02 06:09:31 UTC (rev 242309)
@@ -1,3 +1,48 @@
+2019-03-01  Wenson Hsieh  <[email protected]>
+
+        [Datalist] fast/forms/datalist/datalist-child-validation.html crashes with a debug assertion in isValidFormControlElement()
+        https://bugs.webkit.org/show_bug.cgi?id=190620
+        <rdar://problem/19226679>
+
+        Reviewed by Ryosuke Niwa.
+
+        Fixes and re-enables an existing layout test that is asserting on debug builds (and failing on release builds).
+        To understand why we hit this assertion, we first note several observations:
+
+            -   The validity of a form control (`isValid()`) depends on the value of `willValidate()`.
+            -   Both of these results are cached in member variables: `m_isValid` and `m_willValidate`, respectively.
+            -   `willValidate()` changes the cached value of `m_willValidate` if necessary, but `isValid()` uses the
+                cached value without update.
+
+        Now, consider the following scenario:
+
+            1.  Something changes in the DOM that changes the result of `willValidate()`. This can happen as a result of
+                several things:
+                a.  The form control changes readonly state
+                b.  The form control changes disabled state
+                c.  The form control is added to a datalist element
+                d.  The form control is removed from a datalist element
+            2.  Call `willValidate()`.
+            3.  Call `isValid()`.
+
+        In scenarios (a) - (c), we ensure that cached form control validity (`m_isValid`) is updated alongside
+        `m_willValidate` by invoking `setNeedsWillValidateCheck()`, such that the result of `isValid()` matches the
+        result of `m_isValid` in step (3). However, in the last scenario (d), we don't do this, which causes form
+        control validity to fall out of sync with the result of `isValid()`. To fix the bug, we update willValidate and
+        isValid when a form control is removed from an ancestor, only if one of its ancestors is a datalist element.
+
+        * html/HTMLFormControlElement.cpp:
+        (WebCore::HTMLFormControlElement::insertedIntoAncestor):
+        (WebCore::HTMLFormControlElement::removedFromAncestor):
+
+        Make a couple of minor tweaks:
+          - Currently, we always invalidate `m_dataListAncestorState` by resetting the state to `Unknown` when the form
+            control is removed from an ancestor or inserted. Instead, we only need to reset it when the form control
+            already has an ancestor that is a datalist (in the case where it's being removed) or when the form control
+            does not yet have an ancestor (in the case where it is being added).
+          - If the form control was inside a datalist prior to removal, recompute its cached value of `m_willValidate`,
+            as well as its cached validity (`m_isValid`).
+
 2019-03-01  Darin Adler  <[email protected]>
 
         Finish removing String::format

Modified: trunk/Source/WebCore/html/HTMLFormControlElement.cpp (242308 => 242309)


--- trunk/Source/WebCore/html/HTMLFormControlElement.cpp	2019-03-02 05:45:11 UTC (rev 242308)
+++ trunk/Source/WebCore/html/HTMLFormControlElement.cpp	2019-03-02 06:09:31 UTC (rev 242309)
@@ -280,7 +280,9 @@
 
 Node::InsertedIntoAncestorResult HTMLFormControlElement::insertedIntoAncestor(InsertionType insertionType, ContainerNode& parentOfInsertedTree)
 {
-    m_dataListAncestorState = Unknown;
+    if (m_dataListAncestorState == NotInsideDataList)
+        m_dataListAncestorState = Unknown;
+
     setNeedsWillValidateCheck();
     if (willValidate() && !isValidFormControlElement())
         addInvalidElementToAncestorFromInsertionPoint(*this, &parentOfInsertedTree);
@@ -303,12 +305,21 @@
     m_validationMessage = nullptr;
     if (m_disabledByAncestorFieldset)
         setAncestorDisabled(computeIsDisabledByFieldsetAncestor());
-    m_dataListAncestorState = Unknown;
+
+    bool wasInsideDataList = false;
+    if (m_dataListAncestorState == InsideDataList) {
+        m_dataListAncestorState = Unknown;
+        wasInsideDataList = true;
+    }
+
     HTMLElement::removedFromAncestor(removalType, oldParentOfRemovedTree);
     FormAssociatedElement::removedFromAncestor(removalType, oldParentOfRemovedTree);
 
     if (wasMatchingInvalidPseudoClass)
         removeInvalidElementToAncestorFromInsertionPoint(*this, &oldParentOfRemovedTree);
+
+    if (wasInsideDataList)
+        setNeedsWillValidateCheck();
 }
 
 void HTMLFormControlElement::setChangedSinceLastFormControlChangeEvent(bool changed)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to