REGRESSION(r231291): InputType should hold a WeakPtr to its HTMLInputElement
[WebKit-https.git] / Source / WebCore / html / TextFieldInputType.cpp
index 1faeb51..dc054fe 100644 (file)
@@ -75,16 +75,18 @@ TextFieldInputType::~TextFieldInputType()
 
 bool TextFieldInputType::isKeyboardFocusable(KeyboardEvent*) const
 {
+    ASSERT(element());
 #if PLATFORM(IOS)
-    if (element().isReadOnly())
+    if (element()->isReadOnly())
         return false;
 #endif
-    return element().isTextFormControlFocusable();
+    return element()->isTextFormControlFocusable();
 }
 
 bool TextFieldInputType::isMouseFocusable() const
 {
-    return element().isTextFormControlFocusable();
+    ASSERT(element());
+    return element()->isTextFormControlFocusable();
 }
 
 bool TextFieldInputType::isTextField() const
@@ -106,14 +108,17 @@ bool TextFieldInputType::isEmptyValue() const
 
 bool TextFieldInputType::valueMissing(const String& value) const
 {
-    return element().isRequired() && value.isEmpty();
+    ASSERT(element());
+    return element()->isRequired() && value.isEmpty();
 }
 
 void TextFieldInputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior)
 {
+    ASSERT(element());
+
     // Grab this input element to keep reference even if JS event handler
     // changes input type.
-    Ref<HTMLInputElement> input(element());
+    Ref<HTMLInputElement> input(*element());
 
     // We don't ask InputType::setValue to dispatch events because
     // TextFieldInputType dispatches events different way from InputType.
@@ -158,17 +163,19 @@ void TextFieldInputType::setValue(const String& sanitizedValue, bool valueChange
 
 void TextFieldInputType::handleKeydownEvent(KeyboardEvent& event)
 {
-    if (!element().focused())
+    ASSERT(element());
+    if (!element()->focused())
         return;
-    RefPtr<Frame> frame = element().document().frame();
-    if (!frame || !frame->editor().doTextFieldCommandFromEvent(&element(), &event))
+    RefPtr<Frame> frame = element()->document().frame();
+    if (!frame || !frame->editor().doTextFieldCommandFromEvent(element(), &event))
         return;
     event.setDefaultHandled();
 }
 
 void TextFieldInputType::handleKeydownEventForSpinButton(KeyboardEvent& event)
 {
-    if (element().isDisabledOrReadOnly())
+    ASSERT(element());
+    if (element()->isDisabledOrReadOnly())
         return;
     const String& key = event.keyIdentifier();
     if (key == "Up")
@@ -192,13 +199,16 @@ void TextFieldInputType::forwardEvent(Event& event)
     bool isBlurEvent = event.type() == eventNames().blurEvent;
     if (isFocusEvent || isBlurEvent)
         capsLockStateMayHaveChanged();
-    if (event.isMouseEvent() || isFocusEvent || isBlurEvent)
-        element().forwardEvent(event);
+    if (event.isMouseEvent() || isFocusEvent || isBlurEvent) {
+        ASSERT(element());
+        element()->forwardEvent(event);
+    }
 }
 
 void TextFieldInputType::elementDidBlur()
 {
-    auto* renderer = element().renderer();
+    ASSERT(element());
+    auto* renderer = element()->renderer();
     if (!renderer)
         return;
 
@@ -217,15 +227,17 @@ void TextFieldInputType::elementDidBlur()
 
 void TextFieldInputType::handleFocusEvent(Node* oldFocusedNode, FocusDirection)
 {
-    ASSERT_UNUSED(oldFocusedNode, oldFocusedNode != &element());
-    if (RefPtr<Frame> frame = element().document().frame())
-        frame->editor().textFieldDidBeginEditing(&element());
+    ASSERT(element());
+    ASSERT_UNUSED(oldFocusedNode, oldFocusedNode != element());
+    if (RefPtr<Frame> frame = element()->document().frame())
+        frame->editor().textFieldDidBeginEditing(element());
 }
 
 void TextFieldInputType::handleBlurEvent()
 {
     InputType::handleBlurEvent();
-    element().endEditing();
+    ASSERT(element());
+    element()->endEditing();
 }
 
 bool TextFieldInputType::shouldSubmitImplicitly(Event& event)
@@ -236,7 +248,8 @@ bool TextFieldInputType::shouldSubmitImplicitly(Event& event)
 
 RenderPtr<RenderElement> TextFieldInputType::createInputRenderer(RenderStyle&& style)
 {
-    return createRenderer<RenderTextControlSingleLine>(element(), WTFMove(style));
+    ASSERT(element());
+    return createRenderer<RenderTextControlSingleLine>(*element(), WTFMove(style));
 }
 
 bool TextFieldInputType::needsContainer() const
@@ -246,17 +259,20 @@ bool TextFieldInputType::needsContainer() const
 
 bool TextFieldInputType::shouldHaveSpinButton() const
 {
-    return RenderTheme::singleton().shouldHaveSpinButton(element());
+    ASSERT(element());
+    return RenderTheme::singleton().shouldHaveSpinButton(*element());
 }
 
 bool TextFieldInputType::shouldHaveCapsLockIndicator() const
 {
-    return RenderTheme::singleton().shouldHaveCapsLockIndicator(element());
+    ASSERT(element());
+    return RenderTheme::singleton().shouldHaveCapsLockIndicator(*element());
 }
 
 void TextFieldInputType::createShadowSubtree()
 {
-    ASSERT(element().shadowRoot());
+    ASSERT(element());
+    ASSERT(element()->shadowRoot());
 
     ASSERT(!m_innerText);
     ASSERT(!m_innerBlock);
@@ -264,7 +280,7 @@ void TextFieldInputType::createShadowSubtree()
     ASSERT(!m_capsLockIndicator);
     ASSERT(!m_autoFillButton);
 
-    Document& document = element().document();
+    Document& document = element()->document();
     bool shouldHaveSpinButton = this->shouldHaveSpinButton();
     bool shouldHaveCapsLockIndicator = this->shouldHaveCapsLockIndicator();
     bool createsContainer = shouldHaveSpinButton || shouldHaveCapsLockIndicator || needsContainer();
@@ -272,7 +288,7 @@ void TextFieldInputType::createShadowSubtree()
     m_innerText = TextControlInnerTextElement::create(document);
 
     if (!createsContainer) {
-        element().userAgentShadowRoot()->appendChild(*m_innerText);
+        element()->userAgentShadowRoot()->appendChild(*m_innerText);
         updatePlaceholderText();
         return;
     }
@@ -350,8 +366,10 @@ void TextFieldInputType::destroyShadowSubtree()
 
 void TextFieldInputType::attributeChanged(const QualifiedName& name)
 {
-    if (name == valueAttr || name == placeholderAttr)
-        updateInnerTextValue();
+    if (name == valueAttr || name == placeholderAttr) {
+        if (element())
+            updateInnerTextValue();
+    }
     InputType::attributeChanged(name);
 }
 
@@ -475,12 +493,13 @@ String TextFieldInputType::sanitizeValue(const String& proposedValue) const
 
 void TextFieldInputType::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent& event)
 {
+    ASSERT(element());
     // Make sure that the text to be inserted will not violate the maxLength.
 
     // We use RenderTextControlSingleLine::text() instead of InputElement::value()
     // because they can be mismatched by sanitizeValue() in
     // HTMLInputElement::subtreeHasChanged() in some cases.
-    String innerText = element().innerTextValue();
+    String innerText = element()->innerTextValue();
     unsigned oldLength = numGraphemeClusters(innerText);
 
     // selectionLength represents the selection length of this text field to be
@@ -489,18 +508,18 @@ void TextFieldInputType::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent&
     // selection length. The selection is the source of text drag-and-drop in
     // that case, and nothing in the text field will be removed.
     unsigned selectionLength = 0;
-    if (element().focused()) {
-        ASSERT(enclosingTextFormControl(element().document().frame()->selection().selection().start()) == &element());
-        int selectionStart = element().selectionStart();
-        ASSERT(selectionStart <= element().selectionEnd());
-        int selectionCodeUnitCount = element().selectionEnd() - selectionStart;
+    if (element()->focused()) {
+        ASSERT(enclosingTextFormControl(element()->document().frame()->selection().selection().start()) == element());
+        int selectionStart = element()->selectionStart();
+        ASSERT(selectionStart <= element()->selectionEnd());
+        int selectionCodeUnitCount = element()->selectionEnd() - selectionStart;
         selectionLength = selectionCodeUnitCount ? numGraphemeClusters(StringView(innerText).substring(selectionStart, selectionCodeUnitCount)) : 0;
     }
     ASSERT(oldLength >= selectionLength);
 
     // Selected characters will be removed by the next text event.
     unsigned baseLength = oldLength - selectionLength;
-    unsigned maxLength = isTextType() ? element().effectiveMaxLength() : HTMLInputElement::maxEffectiveLength;
+    unsigned maxLength = isTextType() ? element()->effectiveMaxLength() : HTMLInputElement::maxEffectiveLength;
     unsigned appendableLength = maxLength > baseLength ? maxLength - baseLength : 0;
 
     // Truncate the inserted text to avoid violating the maxLength and other constraints.
@@ -524,7 +543,8 @@ void TextFieldInputType::updatePlaceholderText()
 {
     if (!supportsPlaceholder())
         return;
-    String placeholderText = element().strippedPlaceholder();
+    ASSERT(element());
+    String placeholderText = element()->strippedPlaceholder();
     if (placeholderText.isEmpty()) {
         if (m_placeholder) {
             m_placeholder->parentNode()->removeChild(*m_placeholder);
@@ -533,8 +553,8 @@ void TextFieldInputType::updatePlaceholderText()
         return;
     }
     if (!m_placeholder) {
-        m_placeholder = TextControlPlaceholderElement::create(element().document());
-        element().userAgentShadowRoot()->insertBefore(*m_placeholder, m_container ? m_container.get() : innerTextElement().get());
+        m_placeholder = TextControlPlaceholderElement::create(element()->document());
+        element()->userAgentShadowRoot()->insertBefore(*m_placeholder, m_container ? m_container.get() : innerTextElement().get());
     }
     m_placeholder->setInnerText(placeholderText);
 }
@@ -542,9 +562,10 @@ void TextFieldInputType::updatePlaceholderText()
 bool TextFieldInputType::appendFormData(DOMFormData& formData, bool multipart) const
 {
     InputType::appendFormData(formData, multipart);
-    auto& dirnameAttrValue = element().attributeWithoutSynchronization(dirnameAttr);
+    ASSERT(element());
+    auto& dirnameAttrValue = element()->attributeWithoutSynchronization(dirnameAttr);
     if (!dirnameAttrValue.isNull())
-        formData.append(dirnameAttrValue, element().directionForFormData());
+        formData.append(dirnameAttrValue, element()->directionForFormData());
     return true;
 }
 
@@ -555,7 +576,8 @@ String TextFieldInputType::convertFromVisibleValue(const String& visibleValue) c
 
 void TextFieldInputType::subtreeHasChanged()
 {
-    element().setChangedSinceLastFormControlChangeEvent(true);
+    ASSERT(element());
+    element()->setChangedSinceLastFormControlChangeEvent(true);
 
     // We don't need to call sanitizeUserInputValue() function here because
     // HTMLInputElement::handleBeforeTextInsertedEvent() has already called
@@ -567,23 +589,24 @@ void TextFieldInputType::subtreeHasChanged()
     // user input in order to retain parity between what's in the model and
     // what's on the screen. Otherwise, we retain the sanitization process for
     // backward compatibility. https://bugs.webkit.org/show_bug.cgi?id=150346
-    String innerText = convertFromVisibleValue(element().innerTextValue());
+    String innerText = convertFromVisibleValue(element()->innerTextValue());
     if (!supportsSelectionAPI())
         innerText = sanitizeValue(innerText);
-    element().setValueFromRenderer(innerText);
-    element().updatePlaceholderVisibility();
+    element()->setValueFromRenderer(innerText);
+    element()->updatePlaceholderVisibility();
     // Recalc for :invalid change.
-    element().invalidateStyleForSubtree();
+    element()->invalidateStyleForSubtree();
 
     didSetValueByUserEdit();
 }
 
 void TextFieldInputType::didSetValueByUserEdit()
 {
-    if (!element().focused())
+    ASSERT(element());
+    if (!element()->focused())
         return;
-    if (RefPtr<Frame> frame = element().document().frame())
-        frame->editor().textDidChangeInTextField(&element());
+    if (RefPtr<Frame> frame = element()->document().frame())
+        frame->editor().textDidChangeInTextField(element());
 }
 
 void TextFieldInputType::spinButtonStepDown()
@@ -598,40 +621,45 @@ void TextFieldInputType::spinButtonStepUp()
 
 void TextFieldInputType::updateInnerTextValue()
 {
-    if (!element().formControlValueMatchesRenderer()) {
+    ASSERT(element());
+    if (!element()->formControlValueMatchesRenderer()) {
         // Update the renderer value if the formControlValueMatchesRenderer() flag is false.
         // It protects an unacceptable renderer value from being overwritten with the DOM value.
-        element().setInnerTextValue(visibleValue());
-        element().updatePlaceholderVisibility();
+        element()->setInnerTextValue(visibleValue());
+        element()->updatePlaceholderVisibility();
     }
 }
 
 void TextFieldInputType::focusAndSelectSpinButtonOwner()
 {
-    Ref<HTMLInputElement> input(element());
+    ASSERT(element());
+    Ref<HTMLInputElement> input(*element());
     input->focus();
     input->select();
 }
 
 bool TextFieldInputType::shouldSpinButtonRespondToMouseEvents()
 {
-    return !element().isDisabledOrReadOnly();
+    ASSERT(element());
+    return !element()->isDisabledOrReadOnly();
 }
 
 bool TextFieldInputType::shouldSpinButtonRespondToWheelEvents()
 {
-    return shouldSpinButtonRespondToMouseEvents() && element().focused();
+    ASSERT(element());
+    return shouldSpinButtonRespondToMouseEvents() && element()->focused();
 }
 
 bool TextFieldInputType::shouldDrawCapsLockIndicator() const
 {
-    if (element().document().focusedElement() != &element())
+    ASSERT(element());
+    if (element()->document().focusedElement() != element())
         return false;
 
-    if (element().isDisabledOrReadOnly())
+    if (element()->isDisabledOrReadOnly())
         return false;
 
-    RefPtr<Frame> frame = element().document().frame();
+    RefPtr<Frame> frame = element()->document().frame();
     if (!frame)
         return false;
 
@@ -652,30 +680,33 @@ void TextFieldInputType::capsLockStateMayHaveChanged()
 
 bool TextFieldInputType::shouldDrawAutoFillButton() const
 {
-    return !element().isDisabledOrReadOnly() && element().autoFillButtonType() != AutoFillButtonType::None;
+    ASSERT(element());
+    return !element()->isDisabledOrReadOnly() && element()->autoFillButtonType() != AutoFillButtonType::None;
 }
 
 void TextFieldInputType::autoFillButtonElementWasClicked()
 {
-    Page* page = element().document().page();
+    ASSERT(element());
+    Page* page = element()->document().page();
     if (!page)
         return;
 
-    page->chrome().client().handleAutoFillButtonClick(element());
+    page->chrome().client().handleAutoFillButtonClick(*element());
 }
 
 void TextFieldInputType::createContainer()
 {
     ASSERT(!m_container);
+    ASSERT(element());
 
-    m_container = TextControlInnerContainer::create(element().document());
+    m_container = TextControlInnerContainer::create(element()->document());
     m_container->setPseudo(AtomicString("-webkit-textfield-decoration-container", AtomicString::ConstructFromLiteral));
 
-    m_innerBlock = TextControlInnerElement::create(element().document());
+    m_innerBlock = TextControlInnerElement::create(element()->document());
     m_innerBlock->appendChild(*m_innerText);
     m_container->appendChild(*m_innerBlock);
 
-    element().userAgentShadowRoot()->appendChild(*m_container);
+    element()->userAgentShadowRoot()->appendChild(*m_container);
 }
 
 void TextFieldInputType::createAutoFillButton(AutoFillButtonType autoFillButtonType)
@@ -685,7 +716,8 @@ void TextFieldInputType::createAutoFillButton(AutoFillButtonType autoFillButtonT
     if (autoFillButtonType == AutoFillButtonType::None)
         return;
 
-    m_autoFillButton = AutoFillButtonElement::create(element().document(), *this);
+    ASSERT(element());
+    m_autoFillButton = AutoFillButtonElement::create(element()->document(), *this);
     m_autoFillButton->setPseudo(autoFillButtonTypeToAutoFillButtonPseudoClassName(autoFillButtonType));
     m_autoFillButton->setAttributeWithoutSynchronization(roleAttr, AtomicString("button", AtomicString::ConstructFromLiteral));
     m_autoFillButton->setAttributeWithoutSynchronization(aria_labelAttr, autoFillButtonTypeToAccessibilityLabel(autoFillButtonType));
@@ -699,7 +731,8 @@ void TextFieldInputType::updateAutoFillButton()
         if (!m_container)
             createContainer();
 
-        AutoFillButtonType autoFillButtonType = element().autoFillButtonType();
+        ASSERT(element());
+        AutoFillButtonType autoFillButtonType = element()->autoFillButtonType();
         if (!m_autoFillButton)
             createAutoFillButton(autoFillButtonType);