is<HTMLTextFormControlElement> reports the input type.
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 13 Dec 2017 04:05:33 +0000 (04:05 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 13 Dec 2017 04:05:33 +0000 (04:05 +0000)
https://bugs.webkit.org/show_bug.cgi?id=180721
<rdar://problem/36005123>

Reviewed by Ryosuke Niwa.

This patch ensures that is<HTMLTextFormControlElement> consistently returns true even
when the input type changes from text to non-text (checkbox etc).

* accessibility/AccessibilityObject.cpp:
(WebCore::AccessibilityObject::selectText):
* dom/Element.h:
(WebCore::Element::isTextFormControlElement const):
(WebCore::Element::isTextField const):
(WebCore::Element::isTextFormControl const): Deleted.
* editing/Editor.cpp:
(WebCore::Editor::selectionForCommand):
(WebCore::Editor::setBaseWritingDirection):
(WebCore::findFirstMarkable):
* editing/FrameSelection.cpp:
(WebCore::FrameSelection::selectAll):
* html/FormController.cpp:
(WebCore::FormController::formElementsCharacterCount const):
* html/HTMLElement.cpp:
(WebCore::HTMLElement::directionality const):
* html/HTMLInputElement.h:
* html/HTMLTextAreaElement.h:
* html/HTMLTextFormControlElement.cpp:
(WebCore::HTMLTextFormControlElement::didEditInnerTextValue):
(WebCore::HTMLTextFormControlElement::selectedText const):
(WebCore::HTMLTextFormControlElement::setSelectionRange):
(WebCore::HTMLTextFormControlElement::selectionStart const):
(WebCore::HTMLTextFormControlElement::computeSelectionStart const):
(WebCore::HTMLTextFormControlElement::selectionEnd const):
(WebCore::HTMLTextFormControlElement::computeSelectionEnd const):
(WebCore::HTMLTextFormControlElement::selectionDirection const):
(WebCore::HTMLTextFormControlElement::computeSelectionDirection const):
(WebCore::HTMLTextFormControlElement::selection const):
(WebCore::HTMLTextFormControlElement::selectionChanged):
(WebCore::HTMLTextFormControlElement::lastChangeWasUserEdit const):
(WebCore::HTMLTextFormControlElement::setInnerTextValue):
(WebCore::HTMLTextFormControlElement::valueWithHardLineBreaks const):
(WebCore::enclosingTextFormControl):
* html/HTMLTextFormControlElement.h:
(isType):
* rendering/HitTestResult.cpp:
(WebCore::HitTestResult::isOverTextInsideFormControlElement const):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@225837 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
Source/WebCore/ChangeLog
Source/WebCore/accessibility/AccessibilityObject.cpp
Source/WebCore/cssjit/SelectorCompiler.cpp
Source/WebCore/dom/Element.h
Source/WebCore/editing/Editor.cpp
Source/WebCore/editing/FrameSelection.cpp
Source/WebCore/html/FormController.cpp
Source/WebCore/html/HTMLElement.cpp
Source/WebCore/html/HTMLInputElement.h
Source/WebCore/html/HTMLTextAreaElement.h
Source/WebCore/html/HTMLTextFormControlElement.cpp
Source/WebCore/html/HTMLTextFormControlElement.h
Source/WebCore/rendering/HitTestResult.cpp

index 8d7c918..96fe1fc 100644 (file)
@@ -1,3 +1,53 @@
+2017-12-12  Zalan Bujtas  <zalan@apple.com>
+
+        is<HTMLTextFormControlElement> reports the input type.
+        https://bugs.webkit.org/show_bug.cgi?id=180721
+        <rdar://problem/36005123>
+
+        Reviewed by Ryosuke Niwa.
+
+        This patch ensures that is<HTMLTextFormControlElement> consistently returns true even
+        when the input type changes from text to non-text (checkbox etc).
+
+        * accessibility/AccessibilityObject.cpp:
+        (WebCore::AccessibilityObject::selectText):
+        * dom/Element.h:
+        (WebCore::Element::isTextFormControlElement const):
+        (WebCore::Element::isTextField const):
+        (WebCore::Element::isTextFormControl const): Deleted.
+        * editing/Editor.cpp:
+        (WebCore::Editor::selectionForCommand):
+        (WebCore::Editor::setBaseWritingDirection):
+        (WebCore::findFirstMarkable):
+        * editing/FrameSelection.cpp:
+        (WebCore::FrameSelection::selectAll):
+        * html/FormController.cpp:
+        (WebCore::FormController::formElementsCharacterCount const):
+        * html/HTMLElement.cpp:
+        (WebCore::HTMLElement::directionality const):
+        * html/HTMLInputElement.h:
+        * html/HTMLTextAreaElement.h:
+        * html/HTMLTextFormControlElement.cpp:
+        (WebCore::HTMLTextFormControlElement::didEditInnerTextValue):
+        (WebCore::HTMLTextFormControlElement::selectedText const):
+        (WebCore::HTMLTextFormControlElement::setSelectionRange):
+        (WebCore::HTMLTextFormControlElement::selectionStart const):
+        (WebCore::HTMLTextFormControlElement::computeSelectionStart const):
+        (WebCore::HTMLTextFormControlElement::selectionEnd const):
+        (WebCore::HTMLTextFormControlElement::computeSelectionEnd const):
+        (WebCore::HTMLTextFormControlElement::selectionDirection const):
+        (WebCore::HTMLTextFormControlElement::computeSelectionDirection const):
+        (WebCore::HTMLTextFormControlElement::selection const):
+        (WebCore::HTMLTextFormControlElement::selectionChanged):
+        (WebCore::HTMLTextFormControlElement::lastChangeWasUserEdit const):
+        (WebCore::HTMLTextFormControlElement::setInnerTextValue):
+        (WebCore::HTMLTextFormControlElement::valueWithHardLineBreaks const):
+        (WebCore::enclosingTextFormControl):
+        * html/HTMLTextFormControlElement.h:
+        (isType):
+        * rendering/HitTestResult.cpp:
+        (WebCore::HitTestResult::isOverTextInsideFormControlElement const):
+
 2017-12-12  Dean Jackson  <dino@apple.com>
 
         Unify some WebGL sources
index 3f03c51..a6228c7 100644 (file)
@@ -828,7 +828,7 @@ String AccessibilityObject::selectText(AccessibilitySelectTextCriteria* criteria
     // Determine which candidate is closest to the selection and perform the activity.
     if (RefPtr<Range> closestStringRange = rangeClosestToRange(selectedStringRange.get(), WTFMove(closestAfterStringRange), WTFMove(closestBeforeStringRange))) {
         // If the search started within a text control, ensure that the result is inside that element.
-        if (element() && element()->isTextFormControl()) {
+        if (element() && element()->isTextField()) {
             if (!closestStringRange->startContainer().isDescendantOrShadowDescendantOf(element()) || !closestStringRange->endContainer().isDescendantOrShadowDescendantOf(element()))
                 return String();
         }
index b40eab1..e920542 100644 (file)
@@ -3344,7 +3344,7 @@ void SelectorCodeGenerator::generateElementIsOnlyChild(Assembler::JumpList& fail
 
 static bool makeContextStyleUniqueIfNecessaryAndTestIsPlaceholderShown(const Element* element, SelectorChecker::CheckingContext* checkingContext)
 {
-    if (is<HTMLTextFormControlElement>(*element)) {
+    if (is<HTMLTextFormControlElement>(*element) && element->isTextField()) {
         if (checkingContext->resolvingMode == SelectorChecker::Mode::ResolvingStyle)
             checkingContext->styleRelations.append({ *element, Style::Relation::Unique, 1 });
         return downcast<HTMLTextFormControlElement>(*element).isPlaceholderVisible();
index 38001cb..215c95f 100644 (file)
@@ -436,7 +436,8 @@ public:
 
     virtual bool isFormControlElement() const { return false; }
     virtual bool isSpinButtonElement() const { return false; }
-    virtual bool isTextFormControl() const { return false; }
+    virtual bool isTextFormControlElement() const { return false; }
+    virtual bool isTextField() const { return false; }
     virtual bool isOptionalFormControl() const { return false; }
     virtual bool isRequiredFormControl() const { return false; }
     virtual bool isInRange() const { return false; }
index 32bd2f7..5a79465 100644 (file)
@@ -243,7 +243,7 @@ VisibleSelection Editor::selectionForCommand(Event* event)
         return selection;
     // If the target is a text control, and the current selection is outside of its shadow tree,
     // then use the saved selection for that text control.
-    if (is<HTMLTextFormControlElement>(event->target())) {
+    if (is<Element>(event->target()) && downcast<Element>(*event->target()).isTextField()) {
         auto& target = downcast<HTMLTextFormControlElement>(*event->target());
         auto start = selection.start();
         if (start.isNull() || &target != enclosingTextFormControl(start)) {
@@ -1721,7 +1721,7 @@ void Editor::setBaseWritingDirection(WritingDirection direction)
 #endif
         
     Element* focusedElement = document().focusedElement();
-    if (is<HTMLTextFormControlElement>(focusedElement)) {
+    if (focusedElement && focusedElement->isTextField()) {
         if (direction == NaturalWritingDirection)
             return;
 
@@ -3626,7 +3626,7 @@ static Node* findFirstMarkable(Node* node)
             return nullptr;
         if (node->renderer()->isTextOrLineBreak())
             return node;
-        if (is<HTMLTextFormControlElement>(*node))
+        if (is<Element>(*node) && downcast<Element>(*node).isTextField())
             node = downcast<HTMLTextFormControlElement>(*node).visiblePositionForIndex(1).deepEquivalent().deprecatedNode();
         else if (node->firstChild())
             node = node->firstChild();
index f36e05e..c711651 100644 (file)
@@ -1922,7 +1922,7 @@ void FrameSelection::selectAll()
             selectStartTarget = root.get();
     } else {
         if (m_selection.isNone() && focusedElement) {
-            if (is<HTMLTextFormControlElement>(*focusedElement)) {
+            if (focusedElement->isTextField()) {
                 downcast<HTMLTextFormControlElement>(*focusedElement).select();
                 return;
             }
index fef6266..66529ba 100644 (file)
@@ -345,7 +345,7 @@ unsigned FormController::formElementsCharacterCount() const
 {
     unsigned count = 0;
     for (auto& element : m_formElementsWithState) {
-        if (element->isTextFormControl())
+        if (element->isTextField())
             count += element->saveFormControlState()[0].length();
     }
     return count;
index 491cb62..b1d5bb1 100644 (file)
@@ -793,7 +793,7 @@ TextDirection HTMLElement::directionalityIfhasDirAutoAttribute(bool& isAuto) con
 
 TextDirection HTMLElement::directionality(Node** strongDirectionalityTextNode) const
 {
-    if (is<HTMLTextFormControlElement>(*this)) {
+    if (isTextField()) {
         HTMLTextFormControlElement& textElement = downcast<HTMLTextFormControlElement>(const_cast<HTMLElement&>(*this));
         bool hasStrongDirectionality;
         UCharDirection textDirection = textElement.value().defaultWritingDirection(&hasStrongDirectionality);
@@ -806,7 +806,7 @@ TextDirection HTMLElement::directionality(Node** strongDirectionalityTextNode) c
     while (node) {
         // Skip bdi, script, style and text form controls.
         if (equalLettersIgnoringASCIICase(node->nodeName(), "bdi") || node->hasTagName(scriptTag) || node->hasTagName(styleTag)
-            || (is<Element>(*node) && downcast<Element>(*node).isTextFormControl())) {
+            || (is<Element>(*node) && downcast<Element>(*node).isTextField())) {
             node = NodeTraversal::nextSkippingChildren(*node, this);
             continue;
         }
index 815444b..a764079 100644 (file)
@@ -97,7 +97,7 @@ public:
     bool isTextButton() const;
 
     bool isRadioButton() const;
-    WEBCORE_EXPORT bool isTextField() const;
+    WEBCORE_EXPORT bool isTextField() const final;
     WEBCORE_EXPORT bool isSearchField() const;
     bool isInputTypeHidden() const;
     WEBCORE_EXPORT bool isPasswordField() const;
@@ -371,8 +371,6 @@ private:
     void updateFocusAppearance(SelectionRestorationMode, SelectionRevealMode) final;
     bool shouldUseInputMethod() final;
 
-    bool isTextFormControl() const final { return isTextField(); }
-
     bool canTriggerImplicitSubmission() const final { return isTextField(); }
 
     const AtomicString& formControlType() const final;
index 0346806..f2c7a6a 100644 (file)
@@ -102,7 +102,7 @@ private:
     FormControlState saveFormControlState() const final;
     void restoreFormControlState(const FormControlState&) final;
 
-    bool isTextFormControl() const final { return true; }
+    bool isTextField() const final { return true; }
 
     void childrenChanged(const ChildChange&) final;
     void parseAttribute(const QualifiedName&, const AtomicString&) final;
index e2cbde0..276d35c 100644 (file)
@@ -107,7 +107,7 @@ void HTMLTextFormControlElement::dispatchBlurEvent(RefPtr<Element>&& newFocusedE
 
 void HTMLTextFormControlElement::didEditInnerTextValue()
 {
-    if (!isTextFormControl())
+    if (!isTextField())
         return;
 
     LOG(Editing, "HTMLTextFormControlElement %p didEditInnerTextValue", this);
@@ -198,7 +198,7 @@ void HTMLTextFormControlElement::select(const AXTextStateChangeIntent& intent)
 
 String HTMLTextFormControlElement::selectedText() const
 {
-    if (!isTextFormControl())
+    if (!isTextField())
         return String();
     return value().substring(selectionStart(), selectionEnd() - selectionStart());
 }
@@ -284,7 +284,7 @@ void HTMLTextFormControlElement::setSelectionRange(int start, int end, const Str
 
 void HTMLTextFormControlElement::setSelectionRange(int start, int end, TextFieldSelectionDirection direction, const AXTextStateChangeIntent& intent)
 {
-    if (!isTextFormControl())
+    if (!isTextField())
         return;
 
     end = std::max(end, 0);
@@ -343,7 +343,7 @@ VisiblePosition HTMLTextFormControlElement::visiblePositionForIndex(int index) c
 
 int HTMLTextFormControlElement::selectionStart() const
 {
-    if (!isTextFormControl())
+    if (!isTextField())
         return 0;
     if (document().focusedElement() != this && hasCachedSelection())
         return m_cachedSelectionStart;
@@ -353,7 +353,7 @@ int HTMLTextFormControlElement::selectionStart() const
 
 int HTMLTextFormControlElement::computeSelectionStart() const
 {
-    ASSERT(isTextFormControl());
+    ASSERT(isTextField());
     RefPtr<Frame> frame = document().frame();
     if (!frame)
         return 0;
@@ -363,7 +363,7 @@ int HTMLTextFormControlElement::computeSelectionStart() const
 
 int HTMLTextFormControlElement::selectionEnd() const
 {
-    if (!isTextFormControl())
+    if (!isTextField())
         return 0;
     if (document().focusedElement() != this && hasCachedSelection())
         return m_cachedSelectionEnd;
@@ -372,7 +372,7 @@ int HTMLTextFormControlElement::selectionEnd() const
 
 int HTMLTextFormControlElement::computeSelectionEnd() const
 {
-    ASSERT(isTextFormControl());
+    ASSERT(isTextField());
     RefPtr<Frame> frame = document().frame();
     if (!frame)
         return 0;
@@ -401,7 +401,7 @@ static const AtomicString& directionString(TextFieldSelectionDirection direction
 
 const AtomicString& HTMLTextFormControlElement::selectionDirection() const
 {
-    if (!isTextFormControl())
+    if (!isTextField())
         return directionString(SelectionHasNoDirection);
     if (document().focusedElement() != this && hasCachedSelection())
         return directionString(cachedSelectionDirection());
@@ -411,7 +411,7 @@ const AtomicString& HTMLTextFormControlElement::selectionDirection() const
 
 TextFieldSelectionDirection HTMLTextFormControlElement::computeSelectionDirection() const
 {
-    ASSERT(isTextFormControl());
+    ASSERT(isTextField());
     RefPtr<Frame> frame = document().frame();
     if (!frame)
         return SelectionHasNoDirection;
@@ -433,7 +433,7 @@ static inline void setContainerAndOffsetForRange(Node* node, int offset, Node*&
 
 RefPtr<Range> HTMLTextFormControlElement::selection() const
 {
-    if (!renderer() || !isTextFormControl() || !hasCachedSelection())
+    if (!renderer() || !isTextField() || !hasCachedSelection())
         return nullptr;
 
     int start = m_cachedSelectionStart;
@@ -479,7 +479,7 @@ void HTMLTextFormControlElement::restoreCachedSelection(const AXTextStateChangeI
 
 void HTMLTextFormControlElement::selectionChanged(bool shouldFireSelectEvent)
 {
-    if (!isTextFormControl())
+    if (!isTextField())
         return;
 
     // FIXME: Don't re-compute selection start and end if this function was called inside setSelectionRange.
@@ -519,7 +519,7 @@ void HTMLTextFormControlElement::updateInnerTextElementEditability()
 
 bool HTMLTextFormControlElement::lastChangeWasUserEdit() const
 {
-    if (!isTextFormControl())
+    if (!isTextField())
         return false;
     return m_lastChangeWasUserEdit;
 }
@@ -552,7 +552,7 @@ void HTMLTextFormControlElement::setInnerTextValue(const String& value)
     if (!innerText)
         return;
 
-    ASSERT(isTextFormControl());
+    ASSERT(isTextField());
     String previousValue = innerTextValueFrom(*innerText);
     bool textIsChanged = value != previousValue;
     if (textIsChanged || !innerText->hasChildNodes()) {
@@ -685,7 +685,7 @@ String HTMLTextFormControlElement::valueWithHardLineBreaks() const
 {
     // FIXME: It's not acceptable to ignore the HardWrap setting when there is no renderer.
     // While we have no evidence this has ever been a practical problem, it would be best to fix it some day.
-    if (!isTextFormControl())
+    if (!isTextField())
         return value();
 
     auto innerText = innerTextElement();
@@ -739,7 +739,7 @@ HTMLTextFormControlElement* enclosingTextFormControl(const Position& position)
     if (!container)
         return nullptr;
     RefPtr<Element> ancestor = container->shadowHost();
-    return ancestor && is<HTMLTextFormControlElement>(*ancestor) ? downcast<HTMLTextFormControlElement>(ancestor.get()) : nullptr;
+    return ancestor && ancestor->isTextField() ? downcast<HTMLTextFormControlElement>(ancestor.get()) : nullptr;
 }
 
 static const Element* parentHTMLElement(const Element* element)
index 14c8e70..c8d1047 100644 (file)
@@ -132,6 +132,8 @@ protected:
 private:
     TextFieldSelectionDirection cachedSelectionDirection() const { return static_cast<TextFieldSelectionDirection>(m_cachedSelectionDirection); }
 
+    bool isTextFormControlElement() const final { return true; }
+
     int computeSelectionStart() const;
     int computeSelectionEnd() const;
     TextFieldSelectionDirection computeSelectionDirection() const;
@@ -169,7 +171,7 @@ HTMLTextFormControlElement* enclosingTextFormControl(const Position&);
 } // namespace WebCore
 
 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::HTMLTextFormControlElement)
-    static bool isType(const WebCore::Element& element) { return element.isTextFormControl(); }
+    static bool isType(const WebCore::Element& element) { return element.isTextFormControlElement(); }
     static bool isType(const WebCore::Node& node) { return is<WebCore::Element>(node) && isType(downcast<WebCore::Element>(node)); }
     static bool isType(const WebCore::EventTarget& target) { return is<WebCore::Node>(target) && isType(downcast<WebCore::Node>(target)); }
 SPECIALIZE_TYPE_TRAITS_END()
index dedef8e..a81ec3c 100644 (file)
@@ -572,7 +572,7 @@ bool HitTestResult::isOverTextInsideFormControlElement() const
     if (!node)
         return false;
 
-    if (!is<HTMLTextFormControlElement>(*node))
+    if (!is<Element>(*node) || !downcast<Element>(*node).isTextField())
         return false;
 
     Frame* frame = node->document().frame();