tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

HTMLTextAreaElement.cpp (37890B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/dom/HTMLTextAreaElement.h"
      8 
      9 #include "mozAutoDocUpdate.h"
     10 #include "mozilla/AsyncEventDispatcher.h"
     11 #include "mozilla/EventDispatcher.h"
     12 #include "mozilla/MappedDeclarationsBuilder.h"
     13 #include "mozilla/MouseEvents.h"
     14 #include "mozilla/PresState.h"
     15 #include "mozilla/TextControlState.h"
     16 #include "mozilla/dom/Document.h"
     17 #include "mozilla/dom/FormData.h"
     18 #include "mozilla/dom/HTMLTextAreaElementBinding.h"
     19 #include "nsAttrValueInlines.h"
     20 #include "nsBaseCommandController.h"
     21 #include "nsContentCreatorFunctions.h"
     22 #include "nsError.h"
     23 #include "nsFocusManager.h"
     24 #include "nsIConstraintValidation.h"
     25 #include "nsIControllers.h"
     26 #include "nsIFormControl.h"
     27 #include "nsIFrame.h"
     28 #include "nsIMutationObserver.h"
     29 #include "nsLayoutUtils.h"
     30 #include "nsLinebreakConverter.h"
     31 #include "nsPlainTextSerializer.h"
     32 #include "nsPresContext.h"
     33 #include "nsReadableUtils.h"
     34 #include "nsStyleConsts.h"
     35 #include "nsTextControlFrame.h"
     36 #include "nsThreadUtils.h"
     37 #include "nsXULControllers.h"
     38 
     39 NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(TextArea)
     40 
     41 namespace mozilla::dom {
     42 
     43 HTMLTextAreaElement::HTMLTextAreaElement(
     44    already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
     45    FromParser aFromParser)
     46    : TextControlElement(std::move(aNodeInfo), aFromParser,
     47                         FormControlType::Textarea),
     48      mDoneAddingChildren(!aFromParser),
     49      mInhibitStateRestoration(!!(aFromParser & FROM_PARSER_FRAGMENT)),
     50      mAutocompleteAttrState(nsContentUtils::eAutocompleteAttrState_Unknown),
     51      mAutocompleteInfoState(nsContentUtils::eAutocompleteAttrState_Unknown),
     52      mState(TextControlState::Construct(this)) {
     53  AddMutationObserver(this);
     54 
     55  // Set up our default state.  By default we're enabled (since we're
     56  // a control type that can be disabled but not actually disabled right now),
     57  // optional, read-write, and valid. Also by default we don't have to show
     58  // validity UI and so forth.
     59  AddStatesSilently(ElementState::ENABLED | ElementState::OPTIONAL_ |
     60                    ElementState::READWRITE | ElementState::VALID |
     61                    ElementState::VALUE_EMPTY);
     62  RemoveStatesSilently(ElementState::READONLY);
     63 }
     64 
     65 HTMLTextAreaElement::~HTMLTextAreaElement() {
     66  mState->Destroy();
     67  mState = nullptr;
     68 }
     69 
     70 NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLTextAreaElement)
     71 
     72 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLTextAreaElement,
     73                                                  TextControlElement)
     74  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
     75  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControllers)
     76  if (tmp->mState) {
     77    tmp->mState->Traverse(cb);
     78  }
     79 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     80 
     81 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLTextAreaElement,
     82                                                TextControlElement)
     83  NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
     84  NS_IMPL_CYCLE_COLLECTION_UNLINK(mControllers)
     85  if (tmp->mState) {
     86    tmp->mState->Unlink();
     87  }
     88 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     89 
     90 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLTextAreaElement,
     91                                             TextControlElement,
     92                                             nsIMutationObserver,
     93                                             nsIConstraintValidation)
     94 
     95 // nsIDOMHTMLTextAreaElement
     96 
     97 nsresult HTMLTextAreaElement::Clone(dom::NodeInfo* aNodeInfo,
     98                                    nsINode** aResult) const {
     99  *aResult = nullptr;
    100  RefPtr<HTMLTextAreaElement> it = new (aNodeInfo->NodeInfoManager())
    101      HTMLTextAreaElement(do_AddRef(aNodeInfo));
    102 
    103  nsresult rv = const_cast<HTMLTextAreaElement*>(this)->CopyInnerTo(it);
    104  NS_ENSURE_SUCCESS(rv, rv);
    105 
    106  it->SetLastValueChangeWasInteractive(mLastValueChangeWasInteractive);
    107  it.forget(aResult);
    108  return NS_OK;
    109 }
    110 
    111 // nsIContent
    112 
    113 void HTMLTextAreaElement::Select() {
    114  if (FocusState() != FocusTristate::eUnfocusable) {
    115    if (RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager()) {
    116      fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL);
    117    }
    118  }
    119 
    120  SetSelectionRange(0, UINT32_MAX, Optional<nsAString>(), IgnoreErrors());
    121 }
    122 
    123 void HTMLTextAreaElement::SelectAll() {
    124  // FIXME(emilio): Should we try to call Select(), which will avoid flushing?
    125  if (nsTextControlFrame* tf =
    126          do_QueryFrame(GetPrimaryFrame(FlushType::Frames))) {
    127    tf->SelectAll();
    128  }
    129 }
    130 
    131 enum class Wrap {
    132  Off,
    133  Hard,
    134  Soft,
    135 };
    136 
    137 static Wrap WrapValue(const HTMLTextAreaElement& aElement) {
    138  static mozilla::dom::Element::AttrValuesArray strings[] = {
    139      nsGkAtoms::HARD, nsGkAtoms::OFF, nullptr};
    140  switch (aElement.FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::wrap, strings,
    141                                   eIgnoreCase)) {
    142    case 0:
    143      return Wrap::Hard;
    144    case 1:
    145      return Wrap::Off;
    146    default:
    147      return Wrap::Soft;
    148  }
    149 }
    150 
    151 bool HTMLTextAreaElement::IsHTMLFocusable(IsFocusableFlags aFlags,
    152                                          bool* aIsFocusable,
    153                                          int32_t* aTabIndex) {
    154  if (nsGenericHTMLFormControlElementWithState::IsHTMLFocusable(
    155          aFlags, aIsFocusable, aTabIndex)) {
    156    return true;
    157  }
    158 
    159  // disabled textareas are not focusable
    160  *aIsFocusable = !IsDisabled();
    161  return false;
    162 }
    163 
    164 int32_t HTMLTextAreaElement::TabIndexDefault() { return 0; }
    165 
    166 void HTMLTextAreaElement::GetType(nsAString& aType) {
    167  aType.AssignLiteral("textarea");
    168 }
    169 
    170 void HTMLTextAreaElement::GetValue(nsAString& aValue) {
    171  GetValueInternal(aValue);
    172  MOZ_ASSERT(aValue.FindChar(static_cast<char16_t>('\r')) == -1);
    173 }
    174 
    175 void HTMLTextAreaElement::GetValueInternal(nsAString& aValue) const {
    176  MOZ_ASSERT(mState);
    177  mState->GetValue(aValue, /* aForDisplay = */ true);
    178 }
    179 
    180 nsIEditor* HTMLTextAreaElement::GetEditorForBindings() {
    181  if (!GetPrimaryFrame()) {
    182    GetPrimaryFrame(FlushType::Frames);
    183  }
    184  return GetTextEditor();
    185 }
    186 
    187 TextEditor* HTMLTextAreaElement::GetTextEditor() {
    188  MOZ_ASSERT(mState);
    189  return mState->GetTextEditor();
    190 }
    191 
    192 TextEditor* HTMLTextAreaElement::GetExtantTextEditor() const {
    193  MOZ_ASSERT(mState);
    194  return mState->GetExtantTextEditor();
    195 }
    196 
    197 nsISelectionController* HTMLTextAreaElement::GetSelectionController() {
    198  MOZ_ASSERT(mState);
    199  return mState->GetSelectionController();
    200 }
    201 
    202 nsFrameSelection* HTMLTextAreaElement::GetIndependentFrameSelection() const {
    203  MOZ_ASSERT(mState);
    204  return mState->GetIndependentFrameSelection();
    205 }
    206 
    207 nsresult HTMLTextAreaElement::BindToFrame(nsTextControlFrame* aFrame) {
    208  MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript());
    209  MOZ_ASSERT(mState);
    210  return mState->BindToFrame(aFrame);
    211 }
    212 
    213 void HTMLTextAreaElement::UnbindFromFrame(nsTextControlFrame* aFrame) {
    214  MOZ_ASSERT(mState);
    215  if (aFrame) {
    216    mState->UnbindFromFrame(aFrame);
    217  }
    218 }
    219 
    220 nsresult HTMLTextAreaElement::CreateEditor() {
    221  MOZ_ASSERT(mState);
    222  return mState->PrepareEditor();
    223 }
    224 
    225 void HTMLTextAreaElement::SetPreviewValue(const nsAString& aValue) {
    226  MOZ_ASSERT(mState);
    227  mState->SetPreviewText(aValue, true);
    228 }
    229 
    230 void HTMLTextAreaElement::GetPreviewValue(nsAString& aValue) {
    231  MOZ_ASSERT(mState);
    232  mState->GetPreviewText(aValue);
    233 }
    234 
    235 void HTMLTextAreaElement::EnablePreview() {
    236  if (mIsPreviewEnabled) {
    237    return;
    238  }
    239 
    240  mIsPreviewEnabled = true;
    241  // Reconstruct the frame to append an anonymous preview node
    242  nsLayoutUtils::PostRestyleEvent(this, RestyleHint{0},
    243                                  nsChangeHint_ReconstructFrame);
    244 }
    245 
    246 bool HTMLTextAreaElement::IsPreviewEnabled() { return mIsPreviewEnabled; }
    247 
    248 nsresult HTMLTextAreaElement::SetValueInternal(
    249    const nsAString& aValue, const ValueSetterOptions& aOptions) {
    250  MOZ_ASSERT(mState);
    251 
    252  // Need to set the value changed flag here if our value has in fact changed
    253  // (i.e. if ValueSetterOption::SetValueChanged is in aOptions), so that
    254  // retrieves the correct value if needed.
    255  if (aOptions.contains(ValueSetterOption::SetValueChanged)) {
    256    SetValueChanged(true);
    257  }
    258 
    259  if (!mState->SetValue(aValue, aOptions)) {
    260    return NS_ERROR_OUT_OF_MEMORY;
    261  }
    262 
    263  return NS_OK;
    264 }
    265 
    266 void HTMLTextAreaElement::SetValue(const nsAString& aValue,
    267                                   ErrorResult& aError) {
    268  // If the value has been set by a script, we basically want to keep the
    269  // current change event state. If the element is ready to fire a change
    270  // event, we should keep it that way. Otherwise, we should make sure the
    271  // element will not fire any event because of the script interaction.
    272  //
    273  // NOTE: this is currently quite expensive work (too much string
    274  // manipulation). We should probably optimize that.
    275  nsAutoString currentValue;
    276  GetValueInternal(currentValue);
    277 
    278  nsresult rv = SetValueInternal(
    279      aValue,
    280      {ValueSetterOption::ByContentAPI, ValueSetterOption::SetValueChanged,
    281       ValueSetterOption::MoveCursorToEndIfValueChanged});
    282  if (NS_WARN_IF(NS_FAILED(rv))) {
    283    aError.Throw(rv);
    284    return;
    285  }
    286 
    287  if (mFocusedValue.Equals(currentValue)) {
    288    GetValueInternal(mFocusedValue);
    289  }
    290 }
    291 
    292 void HTMLTextAreaElement::SetUserInput(const nsAString& aValue,
    293                                       nsIPrincipal& aSubjectPrincipal) {
    294  SetValueInternal(aValue, {ValueSetterOption::BySetUserInputAPI,
    295                            ValueSetterOption::SetValueChanged,
    296                            ValueSetterOption::MoveCursorToEndIfValueChanged});
    297 }
    298 
    299 void HTMLTextAreaElement::SetValueChanged(bool aValueChanged) {
    300  MOZ_ASSERT(mState);
    301 
    302  bool previousValue = mValueChanged;
    303  mValueChanged = aValueChanged;
    304  if (!aValueChanged && !mState->IsEmpty()) {
    305    mState->EmptyValue();
    306  }
    307  if (mValueChanged == previousValue) {
    308    return;
    309  }
    310  UpdateTooLongValidityState();
    311  UpdateTooShortValidityState();
    312  UpdateValidityElementStates(true);
    313 }
    314 
    315 void HTMLTextAreaElement::SetLastValueChangeWasInteractive(
    316    bool aWasInteractive) {
    317  if (aWasInteractive == mLastValueChangeWasInteractive) {
    318    return;
    319  }
    320  mLastValueChangeWasInteractive = aWasInteractive;
    321  const bool wasValid = IsValid();
    322  UpdateTooLongValidityState();
    323  UpdateTooShortValidityState();
    324  if (wasValid != IsValid()) {
    325    UpdateValidityElementStates(true);
    326  }
    327 }
    328 
    329 void HTMLTextAreaElement::GetDefaultValue(nsAString& aDefaultValue,
    330                                          ErrorResult& aError) const {
    331  if (!nsContentUtils::GetNodeTextContent(this, false, aDefaultValue,
    332                                          fallible)) {
    333    aError.Throw(NS_ERROR_OUT_OF_MEMORY);
    334  }
    335 }
    336 
    337 void HTMLTextAreaElement::SetDefaultValue(const nsAString& aDefaultValue,
    338                                          ErrorResult& aError) {
    339  // setting the value of an textarea element using `.defaultValue = "foo"`
    340  // must be interpreted as a two-step operation:
    341  // 1. clearing all child nodes
    342  // 2. adding a new text node with the new content
    343  // Step 1 must therefore collapse the Selection to 0.
    344  // Calling `SetNodeTextContent()` with an empty string will do that for us.
    345  nsContentUtils::SetNodeTextContent(this, EmptyString(), true);
    346  nsresult rv = nsContentUtils::SetNodeTextContent(this, aDefaultValue, true);
    347  if (NS_SUCCEEDED(rv) && !mValueChanged) {
    348    Reset();
    349  }
    350  if (NS_FAILED(rv)) {
    351    aError.Throw(rv);
    352  }
    353 }
    354 
    355 bool HTMLTextAreaElement::ParseAttribute(int32_t aNamespaceID,
    356                                         nsAtom* aAttribute,
    357                                         const nsAString& aValue,
    358                                         nsIPrincipal* aMaybeScriptedPrincipal,
    359                                         nsAttrValue& aResult) {
    360  if (aNamespaceID == kNameSpaceID_None) {
    361    if (aAttribute == nsGkAtoms::maxlength ||
    362        aAttribute == nsGkAtoms::minlength) {
    363      return aResult.ParseNonNegativeIntValue(aValue);
    364    } else if (aAttribute == nsGkAtoms::cols) {
    365      aResult.ParseIntWithFallback(aValue, DEFAULT_COLS);
    366      return true;
    367    } else if (aAttribute == nsGkAtoms::rows) {
    368      aResult.ParseIntWithFallback(aValue, DEFAULT_ROWS_TEXTAREA);
    369      return true;
    370    } else if (aAttribute == nsGkAtoms::autocomplete) {
    371      aResult.ParseAtomArray(aValue);
    372      return true;
    373    }
    374  }
    375  return TextControlElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
    376                                            aMaybeScriptedPrincipal, aResult);
    377 }
    378 
    379 void HTMLTextAreaElement::MapAttributesIntoRule(
    380    MappedDeclarationsBuilder& aBuilder) {
    381  // wrap=off
    382  const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::wrap);
    383  if (value &&
    384      (value->Type() == nsAttrValue::eString ||
    385       value->Type() == nsAttrValue::eAtom) &&
    386      value->Equals(nsGkAtoms::OFF, eIgnoreCase)) {
    387    // Equivalent to expanding `white-space; pre`
    388    aBuilder.SetKeywordValue(eCSSProperty_white_space_collapse,
    389                             StyleWhiteSpaceCollapse::Preserve);
    390    aBuilder.SetKeywordValue(eCSSProperty_text_wrap_mode,
    391                             StyleTextWrapMode::Nowrap);
    392  }
    393 
    394  nsGenericHTMLFormControlElementWithState::MapDivAlignAttributeInto(aBuilder);
    395  nsGenericHTMLFormControlElementWithState::MapCommonAttributesInto(aBuilder);
    396 }
    397 
    398 nsChangeHint HTMLTextAreaElement::GetAttributeChangeHint(
    399    const nsAtom* aAttribute, AttrModType aModType) const {
    400  nsChangeHint retval =
    401      nsGenericHTMLFormControlElementWithState::GetAttributeChangeHint(
    402          aAttribute, aModType);
    403 
    404  const bool isAdditionOrRemoval = IsAdditionOrRemoval(aModType);
    405  if (aAttribute == nsGkAtoms::rows || aAttribute == nsGkAtoms::cols) {
    406    retval |= NS_STYLE_HINT_REFLOW;
    407  } else if (aAttribute == nsGkAtoms::wrap) {
    408    retval |= nsChangeHint_ReconstructFrame;
    409  } else if (aAttribute == nsGkAtoms::placeholder && isAdditionOrRemoval) {
    410    retval |= nsChangeHint_ReconstructFrame;
    411  }
    412  return retval;
    413 }
    414 
    415 NS_IMETHODIMP_(bool)
    416 HTMLTextAreaElement::IsAttributeMapped(const nsAtom* aAttribute) const {
    417  static const MappedAttributeEntry attributes[] = {{nsGkAtoms::wrap},
    418                                                    {nullptr}};
    419 
    420  static const MappedAttributeEntry* const map[] = {
    421      attributes,
    422      sDivAlignAttributeMap,
    423      sCommonAttributeMap,
    424  };
    425 
    426  return FindAttributeDependence(aAttribute, map);
    427 }
    428 
    429 nsMapRuleToAttributesFunc HTMLTextAreaElement::GetAttributeMappingFunction()
    430    const {
    431  return &MapAttributesIntoRule;
    432 }
    433 
    434 bool HTMLTextAreaElement::IsDisabledForEvents(WidgetEvent* aEvent) {
    435  return IsElementDisabledForEvents(aEvent, GetPrimaryFrame());
    436 }
    437 
    438 void HTMLTextAreaElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
    439  aVisitor.mCanHandle = false;
    440  if (IsDisabledForEvents(aVisitor.mEvent)) {
    441    return;
    442  }
    443 
    444  // Don't dispatch a second select event if we are already handling
    445  // one.
    446  if (aVisitor.mEvent->mMessage == eFormSelect) {
    447    if (mHandlingSelect) {
    448      return;
    449    }
    450    mHandlingSelect = true;
    451  }
    452 
    453  if (aVisitor.mEvent->mMessage == eBlur) {
    454    // Set mWantsPreHandleEvent and fire change event in PreHandleEvent to
    455    // prevent it breaks event target chain creation.
    456    aVisitor.mWantsPreHandleEvent = true;
    457  }
    458 
    459  nsGenericHTMLFormControlElementWithState::GetEventTargetParent(aVisitor);
    460 }
    461 
    462 nsresult HTMLTextAreaElement::PreHandleEvent(EventChainVisitor& aVisitor) {
    463  if (aVisitor.mEvent->mMessage == eBlur) {
    464    // Fire onchange (if necessary), before we do the blur, bug 370521.
    465    FireChangeEventIfNeeded();
    466  }
    467  return nsGenericHTMLFormControlElementWithState::PreHandleEvent(aVisitor);
    468 }
    469 
    470 void HTMLTextAreaElement::FireChangeEventIfNeeded() {
    471  nsString value;
    472  GetValueInternal(value);
    473 
    474  // NOTE(emilio): This is not quite on the spec, but matches <input>, see
    475  // https://github.com/whatwg/html/issues/10011 and
    476  // https://github.com/whatwg/html/issues/10013
    477  if (mValueChanged) {
    478    SetUserInteracted(true);
    479  }
    480 
    481  if (mFocusedValue.Equals(value)) {
    482    return;
    483  }
    484 
    485  // Dispatch the change event.
    486  mFocusedValue = value;
    487  nsContentUtils::DispatchTrustedEvent(OwnerDoc(), this, u"change"_ns,
    488                                       CanBubble::eYes, Cancelable::eNo);
    489 }
    490 
    491 nsresult HTMLTextAreaElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
    492  if (aVisitor.mEvent->mMessage == eFormSelect) {
    493    mHandlingSelect = false;
    494  }
    495  if (aVisitor.mEvent->mMessage == eFocus) {
    496    GetValueInternal(mFocusedValue);
    497  }
    498  return NS_OK;
    499 }
    500 
    501 void HTMLTextAreaElement::DoneAddingChildren(bool aHaveNotified) {
    502  if (!mValueChanged) {
    503    if (!mDoneAddingChildren) {
    504      // Reset now that we're done adding children if the content sink tried to
    505      // sneak some text in without calling AppendChildTo.
    506      Reset();
    507    }
    508 
    509    if (!mInhibitStateRestoration) {
    510      GenerateStateKey();
    511      RestoreFormControlState();
    512    }
    513  }
    514 
    515  mDoneAddingChildren = true;
    516 }
    517 
    518 // Controllers Methods
    519 
    520 nsIControllers* HTMLTextAreaElement::GetControllers(ErrorResult& aError) {
    521  if (!mControllers) {
    522    mControllers = new nsXULControllers();
    523    if (!mControllers) {
    524      aError.Throw(NS_ERROR_FAILURE);
    525      return nullptr;
    526    }
    527 
    528    RefPtr<nsBaseCommandController> commandController =
    529        nsBaseCommandController::CreateEditorController();
    530    if (!commandController) {
    531      aError.Throw(NS_ERROR_FAILURE);
    532      return nullptr;
    533    }
    534 
    535    mControllers->AppendController(commandController);
    536 
    537    commandController = nsBaseCommandController::CreateEditingController();
    538    if (!commandController) {
    539      aError.Throw(NS_ERROR_FAILURE);
    540      return nullptr;
    541    }
    542 
    543    mControllers->AppendController(commandController);
    544  }
    545 
    546  return GetExtantControllers();
    547 }
    548 
    549 nsresult HTMLTextAreaElement::GetControllers(nsIControllers** aResult) {
    550  NS_ENSURE_ARG_POINTER(aResult);
    551 
    552  ErrorResult error;
    553  *aResult = GetControllers(error);
    554  NS_IF_ADDREF(*aResult);
    555 
    556  return error.StealNSResult();
    557 }
    558 
    559 uint32_t HTMLTextAreaElement::GetTextLength() {
    560  nsAutoString val;
    561  GetValue(val);
    562  return val.Length();
    563 }
    564 
    565 Nullable<uint32_t> HTMLTextAreaElement::GetSelectionStart(ErrorResult& aError) {
    566  uint32_t selStart, selEnd;
    567  GetSelectionRange(&selStart, &selEnd, aError);
    568  return Nullable<uint32_t>(selStart);
    569 }
    570 
    571 void HTMLTextAreaElement::SetSelectionStart(
    572    const Nullable<uint32_t>& aSelectionStart, ErrorResult& aError) {
    573  MOZ_ASSERT(mState);
    574  mState->SetSelectionStart(aSelectionStart, aError);
    575 }
    576 
    577 Nullable<uint32_t> HTMLTextAreaElement::GetSelectionEnd(ErrorResult& aError) {
    578  uint32_t selStart, selEnd;
    579  GetSelectionRange(&selStart, &selEnd, aError);
    580  return Nullable<uint32_t>(selEnd);
    581 }
    582 
    583 void HTMLTextAreaElement::SetSelectionEnd(
    584    const Nullable<uint32_t>& aSelectionEnd, ErrorResult& aError) {
    585  MOZ_ASSERT(mState);
    586  mState->SetSelectionEnd(aSelectionEnd, aError);
    587 }
    588 
    589 void HTMLTextAreaElement::GetSelectionRange(uint32_t* aSelectionStart,
    590                                            uint32_t* aSelectionEnd,
    591                                            ErrorResult& aRv) {
    592  MOZ_ASSERT(mState);
    593  return mState->GetSelectionRange(aSelectionStart, aSelectionEnd, aRv);
    594 }
    595 
    596 void HTMLTextAreaElement::GetSelectionDirection(nsAString& aDirection,
    597                                                ErrorResult& aError) {
    598  MOZ_ASSERT(mState);
    599  mState->GetSelectionDirectionString(aDirection, aError);
    600 }
    601 
    602 void HTMLTextAreaElement::SetSelectionDirection(const nsAString& aDirection,
    603                                                ErrorResult& aError) {
    604  MOZ_ASSERT(mState);
    605  mState->SetSelectionDirection(aDirection, aError);
    606 }
    607 
    608 void HTMLTextAreaElement::SetSelectionRange(
    609    uint32_t aSelectionStart, uint32_t aSelectionEnd,
    610    const Optional<nsAString>& aDirection, ErrorResult& aError) {
    611  MOZ_ASSERT(mState);
    612  mState->SetSelectionRange(aSelectionStart, aSelectionEnd, aDirection, aError);
    613 }
    614 
    615 void HTMLTextAreaElement::SetRangeText(const nsAString& aReplacement,
    616                                       ErrorResult& aRv) {
    617  MOZ_ASSERT(mState);
    618  mState->SetRangeText(aReplacement, aRv);
    619 }
    620 
    621 void HTMLTextAreaElement::SetRangeText(const nsAString& aReplacement,
    622                                       uint32_t aStart, uint32_t aEnd,
    623                                       SelectionMode aSelectMode,
    624                                       ErrorResult& aRv) {
    625  MOZ_ASSERT(mState);
    626  mState->SetRangeText(aReplacement, aStart, aEnd, aSelectMode, aRv);
    627 }
    628 
    629 void HTMLTextAreaElement::GetValueFromSetRangeText(nsAString& aValue) {
    630  GetValueInternal(aValue);
    631 }
    632 
    633 nsresult HTMLTextAreaElement::SetValueFromSetRangeText(
    634    const nsAString& aValue) {
    635  return SetValueInternal(aValue, {ValueSetterOption::ByContentAPI,
    636                                   ValueSetterOption::BySetRangeTextAPI,
    637                                   ValueSetterOption::SetValueChanged});
    638 }
    639 
    640 nsresult HTMLTextAreaElement::Reset() {
    641  nsAutoString resetVal;
    642  GetDefaultValue(resetVal, IgnoreErrors());
    643  SetValueChanged(false);
    644  SetUserInteracted(false);
    645 
    646  nsresult rv = SetValueInternal(resetVal, ValueSetterOption::ByInternalAPI);
    647  NS_ENSURE_SUCCESS(rv, rv);
    648 
    649  return NS_OK;
    650 }
    651 
    652 NS_IMETHODIMP
    653 HTMLTextAreaElement::SubmitNamesValues(FormData* aFormData) {
    654  //
    655  // Get the name (if no name, no submit)
    656  //
    657  nsAutoString name;
    658  GetAttr(nsGkAtoms::name, name);
    659  if (name.IsEmpty()) {
    660    return NS_OK;
    661  }
    662 
    663  // Get the value
    664  nsAutoString value;
    665  GetValueInternal(value);
    666  if (WrapValue(*this) == Wrap::Hard) {
    667    if (auto cols = GetWrapCols(); cols > 0) {
    668      int32_t flags = nsIDocumentEncoder::OutputLFLineBreak |
    669                      nsIDocumentEncoder::OutputPreformatted |
    670                      nsIDocumentEncoder::OutputPersistNBSP |
    671                      nsIDocumentEncoder::OutputBodyOnly |
    672                      nsIDocumentEncoder::OutputWrap;
    673      nsPlainTextSerializer::HardWrapString(value, cols, flags);
    674    }
    675  }
    676 
    677  // Submit name=value
    678  const nsresult rv = aFormData->AddNameValuePair(name, value);
    679  if (NS_FAILED(rv)) {
    680    return rv;
    681  }
    682 
    683  // Submit dirname=dir
    684  return SubmitDirnameDir(aFormData);
    685 }
    686 
    687 void HTMLTextAreaElement::SaveState() {
    688  // Only save if value != defaultValue (bug 62713)
    689  PresState* state = nullptr;
    690  if (mValueChanged) {
    691    state = GetPrimaryPresState();
    692    if (state) {
    693      nsAutoString value;
    694      GetValueInternal(value);
    695 
    696      if (NS_FAILED(nsLinebreakConverter::ConvertStringLineBreaks(
    697              value, nsLinebreakConverter::eLinebreakPlatform,
    698              nsLinebreakConverter::eLinebreakContent))) {
    699        NS_ERROR("Converting linebreaks failed!");
    700        return;
    701      }
    702 
    703      state->contentData() =
    704          TextContentData(value, mLastValueChangeWasInteractive);
    705    }
    706  }
    707 
    708  if (mDisabledChanged) {
    709    if (!state) {
    710      state = GetPrimaryPresState();
    711    }
    712    if (state) {
    713      // We do not want to save the real disabled state but the disabled
    714      // attribute.
    715      state->disabled() = HasAttr(nsGkAtoms::disabled);
    716      state->disabledSet() = true;
    717    }
    718  }
    719 }
    720 
    721 bool HTMLTextAreaElement::RestoreState(PresState* aState) {
    722  const PresContentData& state = aState->contentData();
    723 
    724  if (state.type() == PresContentData::TTextContentData) {
    725    ErrorResult rv;
    726    SetValue(state.get_TextContentData().value(), rv);
    727    if (NS_WARN_IF(rv.Failed())) {
    728      rv.SuppressException();
    729      return false;
    730    }
    731    if (state.get_TextContentData().lastValueChangeWasInteractive()) {
    732      SetLastValueChangeWasInteractive(true);
    733    }
    734  }
    735  if (aState->disabledSet() && !aState->disabled()) {
    736    SetDisabled(false, IgnoreErrors());
    737  }
    738 
    739  return false;
    740 }
    741 
    742 void HTMLTextAreaElement::UpdateValidityElementStates(bool aNotify) {
    743  AutoStateChangeNotifier notifier(*this, aNotify);
    744  RemoveStatesSilently(ElementState::VALIDITY_STATES);
    745  if (!IsCandidateForConstraintValidation()) {
    746    return;
    747  }
    748  ElementState state;
    749  if (IsValid()) {
    750    state |= ElementState::VALID;
    751    if (mUserInteracted) {
    752      state |= ElementState::USER_VALID;
    753    }
    754  } else {
    755    state |= ElementState::INVALID;
    756    if (mUserInteracted) {
    757      state |= ElementState::USER_INVALID;
    758    }
    759  }
    760  AddStatesSilently(state);
    761 }
    762 
    763 nsresult HTMLTextAreaElement::BindToTree(BindContext& aContext,
    764                                         nsINode& aParent) {
    765  nsresult rv =
    766      nsGenericHTMLFormControlElementWithState::BindToTree(aContext, aParent);
    767  NS_ENSURE_SUCCESS(rv, rv);
    768 
    769  // Set direction based on value if dir=auto
    770  ResetDirFormAssociatedElement(this, false, HasDirAuto());
    771 
    772  // If there is a disabled fieldset in the parent chain, the element is now
    773  // barred from constraint validation and can't suffer from value missing.
    774  UpdateValueMissingValidityState();
    775  UpdateBarredFromConstraintValidation();
    776 
    777  // And now make sure our state is up to date
    778  UpdateValidityElementStates(false);
    779 
    780  return rv;
    781 }
    782 
    783 void HTMLTextAreaElement::UnbindFromTree(UnbindContext& aContext) {
    784  nsGenericHTMLFormControlElementWithState::UnbindFromTree(aContext);
    785 
    786  // We might be no longer disabled because of parent chain changed.
    787  UpdateValueMissingValidityState();
    788  UpdateBarredFromConstraintValidation();
    789 
    790  // And now make sure our state is up to date
    791  UpdateValidityElementStates(false);
    792 }
    793 
    794 void HTMLTextAreaElement::BeforeSetAttr(int32_t aNameSpaceID, nsAtom* aName,
    795                                        const nsAttrValue* aValue,
    796                                        bool aNotify) {
    797  if (aNotify && aName == nsGkAtoms::disabled &&
    798      aNameSpaceID == kNameSpaceID_None) {
    799    mDisabledChanged = true;
    800  }
    801 
    802  return nsGenericHTMLFormControlElementWithState::BeforeSetAttr(
    803      aNameSpaceID, aName, aValue, aNotify);
    804 }
    805 
    806 void HTMLTextAreaElement::CharacterDataChanged(nsIContent* aContent,
    807                                               const CharacterDataChangeInfo&) {
    808  ContentChanged(aContent);
    809 }
    810 
    811 void HTMLTextAreaElement::ContentAppended(nsIContent* aFirstNewContent,
    812                                          const ContentAppendInfo&) {
    813  ContentChanged(aFirstNewContent);
    814 }
    815 
    816 void HTMLTextAreaElement::ContentInserted(nsIContent* aChild,
    817                                          const ContentInsertInfo&) {
    818  ContentChanged(aChild);
    819 }
    820 
    821 void HTMLTextAreaElement::ContentWillBeRemoved(nsIContent* aChild,
    822                                               const ContentRemoveInfo& aInfo) {
    823  if (mValueChanged || !mDoneAddingChildren ||
    824      (aInfo.mBatchRemovalState && !aInfo.mBatchRemovalState->mIsFirst) ||
    825      !nsContentUtils::IsInSameAnonymousTree(this, aChild)) {
    826    return;
    827  }
    828  if (mState->IsSelectionCached()) {
    829    // Collapse the selection when removing nodes if necessary, see bug 1818686.
    830    auto& props = mState->GetSelectionProperties();
    831    props.CollapseToStart();
    832  }
    833  nsContentUtils::AddScriptRunner(
    834      NewRunnableMethod("HTMLTextAreaElement::ResetIfUnchanged", this,
    835                        &HTMLTextAreaElement::ResetIfUnchanged));
    836 }
    837 
    838 void HTMLTextAreaElement::ContentChanged(nsIContent* aContent) {
    839  if (mValueChanged || !mDoneAddingChildren ||
    840      !nsContentUtils::IsInSameAnonymousTree(this, aContent)) {
    841    return;
    842  }
    843  // We should wait all ranges finish handling the mutation before updating
    844  // the anonymous subtree with a call of Reset.
    845  nsContentUtils::AddScriptRunner(
    846      NewRunnableMethod("HTMLTextAreaElement::ResetIfUnchanged", this,
    847                        &HTMLTextAreaElement::ResetIfUnchanged));
    848 }
    849 
    850 void HTMLTextAreaElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
    851                                       const nsAttrValue* aValue,
    852                                       const nsAttrValue* aOldValue,
    853                                       nsIPrincipal* aSubjectPrincipal,
    854                                       bool aNotify) {
    855  if (aNameSpaceID == kNameSpaceID_None) {
    856    if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled ||
    857        aName == nsGkAtoms::readonly) {
    858      if (aName == nsGkAtoms::disabled) {
    859        // This *has* to be called *before* validity state check because
    860        // UpdateBarredFromConstraintValidation and
    861        // UpdateValueMissingValidityState depend on our disabled state.
    862        UpdateDisabledState(aNotify);
    863      }
    864 
    865      if (aName == nsGkAtoms::required) {
    866        // This *has* to be called *before* UpdateValueMissingValidityState
    867        // because UpdateValueMissingValidityState depends on our required
    868        // state.
    869        UpdateRequiredState(!!aValue, aNotify);
    870      }
    871 
    872      if (aName == nsGkAtoms::readonly && !!aValue != !!aOldValue) {
    873        UpdateReadOnlyState(aNotify);
    874      }
    875 
    876      UpdateValueMissingValidityState();
    877 
    878      // This *has* to be called *after* validity has changed.
    879      if (aName == nsGkAtoms::readonly || aName == nsGkAtoms::disabled) {
    880        UpdateBarredFromConstraintValidation();
    881      }
    882      UpdateValidityElementStates(aNotify);
    883    } else if (aName == nsGkAtoms::autocomplete) {
    884      // Clear the cached @autocomplete attribute state.
    885      mAutocompleteAttrState = nsContentUtils::eAutocompleteAttrState_Unknown;
    886      mAutocompleteInfoState = nsContentUtils::eAutocompleteAttrState_Unknown;
    887    } else if (aName == nsGkAtoms::maxlength) {
    888      UpdateTooLongValidityState();
    889      UpdateValidityElementStates(aNotify);
    890    } else if (aName == nsGkAtoms::minlength) {
    891      UpdateTooShortValidityState();
    892      UpdateValidityElementStates(aNotify);
    893    } else if (aName == nsGkAtoms::placeholder) {
    894      if (nsTextControlFrame* f = do_QueryFrame(GetPrimaryFrame())) {
    895        f->PlaceholderChanged(aOldValue, aValue);
    896      }
    897      UpdatePlaceholderShownState();
    898    } else if (aName == nsGkAtoms::dir && aValue &&
    899               aValue->Equals(nsGkAtoms::_auto, eIgnoreCase)) {
    900      ResetDirFormAssociatedElement(this, aNotify, true);
    901    }
    902  }
    903 
    904  return nsGenericHTMLFormControlElementWithState::AfterSetAttr(
    905      aNameSpaceID, aName, aValue, aOldValue, aSubjectPrincipal, aNotify);
    906 }
    907 
    908 nsresult HTMLTextAreaElement::CopyInnerTo(Element* aDest) {
    909  nsresult rv = nsGenericHTMLFormControlElementWithState::CopyInnerTo(aDest);
    910  NS_ENSURE_SUCCESS(rv, rv);
    911 
    912  if (mValueChanged || aDest->OwnerDoc()->IsStaticDocument()) {
    913    // Set our value on the clone.
    914    auto* dest = static_cast<HTMLTextAreaElement*>(aDest);
    915 
    916    nsAutoString value;
    917    GetValueInternal(value);
    918 
    919    // SetValueInternal handles setting mValueChanged for us. dest is a fresh
    920    // element so setting its value can't really run script.
    921    if (NS_WARN_IF(
    922            NS_FAILED(rv = MOZ_KnownLive(dest)->SetValueInternal(
    923                          value, {ValueSetterOption::SetValueChanged})))) {
    924      return rv;
    925    }
    926  }
    927 
    928  return NS_OK;
    929 }
    930 
    931 bool HTMLTextAreaElement::IsMutable() const { return !IsDisabledOrReadOnly(); }
    932 
    933 void HTMLTextAreaElement::SetCustomValidity(const nsAString& aError) {
    934  ConstraintValidation::SetCustomValidity(aError);
    935  UpdateValidityElementStates(true);
    936 }
    937 
    938 bool HTMLTextAreaElement::IsTooLong() {
    939  if (!mValueChanged || !mLastValueChangeWasInteractive ||
    940      !HasAttr(nsGkAtoms::maxlength)) {
    941    return false;
    942  }
    943 
    944  int32_t maxLength = MaxLength();
    945 
    946  // Maxlength of -1 means parsing error.
    947  if (maxLength == -1) {
    948    return false;
    949  }
    950 
    951  int32_t textLength = GetTextLength();
    952 
    953  return textLength > maxLength;
    954 }
    955 
    956 bool HTMLTextAreaElement::IsTooShort() {
    957  if (!mValueChanged || !mLastValueChangeWasInteractive ||
    958      !HasAttr(nsGkAtoms::minlength)) {
    959    return false;
    960  }
    961 
    962  int32_t minLength = MinLength();
    963 
    964  // Minlength of -1 means parsing error.
    965  if (minLength == -1) {
    966    return false;
    967  }
    968 
    969  int32_t textLength = GetTextLength();
    970 
    971  return textLength && textLength < minLength;
    972 }
    973 
    974 bool HTMLTextAreaElement::IsValueMissing() const {
    975  if (!Required() || !IsMutable()) {
    976    return false;
    977  }
    978  return IsValueEmpty();
    979 }
    980 
    981 void HTMLTextAreaElement::UpdateTooLongValidityState() {
    982  SetValidityState(VALIDITY_STATE_TOO_LONG, IsTooLong());
    983 }
    984 
    985 void HTMLTextAreaElement::UpdateTooShortValidityState() {
    986  SetValidityState(VALIDITY_STATE_TOO_SHORT, IsTooShort());
    987 }
    988 
    989 void HTMLTextAreaElement::UpdateValueMissingValidityState() {
    990  SetValidityState(VALIDITY_STATE_VALUE_MISSING, IsValueMissing());
    991 }
    992 
    993 void HTMLTextAreaElement::UpdateBarredFromConstraintValidation() {
    994  SetBarredFromConstraintValidation(
    995      HasAttr(nsGkAtoms::readonly) ||
    996      HasFlag(ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR) || IsDisabled());
    997 }
    998 
    999 nsresult HTMLTextAreaElement::GetValidationMessage(
   1000    nsAString& aValidationMessage, ValidityStateType aType) {
   1001  nsresult rv = NS_OK;
   1002 
   1003  switch (aType) {
   1004    case VALIDITY_STATE_TOO_LONG: {
   1005      nsAutoString message;
   1006      int32_t maxLength = MaxLength();
   1007      int32_t textLength = GetTextLength();
   1008      nsAutoString strMaxLength;
   1009      nsAutoString strTextLength;
   1010 
   1011      strMaxLength.AppendInt(maxLength);
   1012      strTextLength.AppendInt(textLength);
   1013 
   1014      rv = nsContentUtils::FormatMaybeLocalizedString(
   1015          message, nsContentUtils::eDOM_PROPERTIES, "FormValidationTextTooLong",
   1016          OwnerDoc(), strMaxLength, strTextLength);
   1017      aValidationMessage = message;
   1018    } break;
   1019    case VALIDITY_STATE_TOO_SHORT: {
   1020      nsAutoString message;
   1021      int32_t minLength = MinLength();
   1022      int32_t textLength = GetTextLength();
   1023      nsAutoString strMinLength;
   1024      nsAutoString strTextLength;
   1025 
   1026      strMinLength.AppendInt(minLength);
   1027      strTextLength.AppendInt(textLength);
   1028 
   1029      rv = nsContentUtils::FormatMaybeLocalizedString(
   1030          message, nsContentUtils::eDOM_PROPERTIES,
   1031          "FormValidationTextTooShort", OwnerDoc(), strMinLength,
   1032          strTextLength);
   1033      aValidationMessage = message;
   1034    } break;
   1035    case VALIDITY_STATE_VALUE_MISSING: {
   1036      nsAutoString message;
   1037      rv = nsContentUtils::GetMaybeLocalizedString(
   1038          nsContentUtils::eDOM_PROPERTIES, "FormValidationValueMissing",
   1039          OwnerDoc(), message);
   1040      aValidationMessage = message;
   1041    } break;
   1042    default:
   1043      rv =
   1044          ConstraintValidation::GetValidationMessage(aValidationMessage, aType);
   1045  }
   1046 
   1047  return rv;
   1048 }
   1049 
   1050 bool HTMLTextAreaElement::IsSingleLineTextControl() const { return false; }
   1051 
   1052 bool HTMLTextAreaElement::IsTextArea() const { return true; }
   1053 
   1054 bool HTMLTextAreaElement::IsPasswordTextControl() const { return false; }
   1055 
   1056 Maybe<int32_t> HTMLTextAreaElement::GetCols() {
   1057  const nsAttrValue* value = GetParsedAttr(nsGkAtoms::cols);
   1058  if (!value || value->Type() != nsAttrValue::eInteger) {
   1059    return {};
   1060  }
   1061  return Some(value->GetIntegerValue());
   1062 }
   1063 
   1064 int32_t HTMLTextAreaElement::GetWrapCols() {
   1065  if (WrapValue(*this) == Wrap::Off) {
   1066    return 0;
   1067  }
   1068  // Otherwise we just wrap at the given number of columns
   1069  return GetColsOrDefault();
   1070 }
   1071 
   1072 int32_t HTMLTextAreaElement::GetRows() {
   1073  const nsAttrValue* attr = GetParsedAttr(nsGkAtoms::rows);
   1074  if (attr && attr->Type() == nsAttrValue::eInteger) {
   1075    int32_t rows = attr->GetIntegerValue();
   1076    return (rows <= 0) ? DEFAULT_ROWS_TEXTAREA : rows;
   1077  }
   1078 
   1079  return DEFAULT_ROWS_TEXTAREA;
   1080 }
   1081 
   1082 void HTMLTextAreaElement::GetDefaultValueFromContent(nsAString& aValue, bool) {
   1083  GetDefaultValue(aValue, IgnoreErrors());
   1084 }
   1085 
   1086 bool HTMLTextAreaElement::ValueChanged() const { return mValueChanged; }
   1087 
   1088 void HTMLTextAreaElement::GetTextEditorValue(nsAString& aValue) const {
   1089  MOZ_ASSERT(mState);
   1090  mState->GetValue(aValue, /* aForDisplay = */ true);
   1091 }
   1092 
   1093 void HTMLTextAreaElement::InitializeKeyboardEventListeners() {
   1094  MOZ_ASSERT(mState);
   1095  mState->InitializeKeyboardEventListeners();
   1096 }
   1097 
   1098 void HTMLTextAreaElement::UpdatePlaceholderShownState() {
   1099  SetStates(ElementState::PLACEHOLDER_SHOWN,
   1100            IsValueEmpty() && HasAttr(nsGkAtoms::placeholder));
   1101 }
   1102 
   1103 void HTMLTextAreaElement::OnValueChanged(ValueChangeKind aKind,
   1104                                         bool aNewValueEmpty,
   1105                                         const nsAString* aKnownNewValue) {
   1106  if (aKind != ValueChangeKind::Internal) {
   1107    mLastValueChangeWasInteractive = aKind == ValueChangeKind::UserInteraction;
   1108  }
   1109 
   1110  if (aNewValueEmpty != IsValueEmpty()) {
   1111    SetStates(ElementState::VALUE_EMPTY, aNewValueEmpty);
   1112    UpdatePlaceholderShownState();
   1113  }
   1114 
   1115  // Update the validity state
   1116  const bool validBefore = IsValid();
   1117  UpdateTooLongValidityState();
   1118  UpdateTooShortValidityState();
   1119  UpdateValueMissingValidityState();
   1120 
   1121  ResetDirFormAssociatedElement(this, true, HasDirAuto(), aKnownNewValue);
   1122 
   1123  if (validBefore != IsValid()) {
   1124    UpdateValidityElementStates(true);
   1125  }
   1126 }
   1127 
   1128 bool HTMLTextAreaElement::HasCachedSelection() {
   1129  MOZ_ASSERT(mState);
   1130  return mState->IsSelectionCached();
   1131 }
   1132 
   1133 void HTMLTextAreaElement::SetUserInteracted(bool aInteracted) {
   1134  if (mUserInteracted == aInteracted) {
   1135    return;
   1136  }
   1137  mUserInteracted = aInteracted;
   1138  UpdateValidityElementStates(true);
   1139 }
   1140 
   1141 void HTMLTextAreaElement::FieldSetDisabledChanged(bool aNotify) {
   1142  // This *has* to be called before UpdateBarredFromConstraintValidation and
   1143  // UpdateValueMissingValidityState because these two functions depend on our
   1144  // disabled state.
   1145  nsGenericHTMLFormControlElementWithState::FieldSetDisabledChanged(aNotify);
   1146 
   1147  UpdateValueMissingValidityState();
   1148  UpdateBarredFromConstraintValidation();
   1149  UpdateValidityElementStates(true);
   1150 }
   1151 
   1152 JSObject* HTMLTextAreaElement::WrapNode(JSContext* aCx,
   1153                                        JS::Handle<JSObject*> aGivenProto) {
   1154  return HTMLTextAreaElement_Binding::Wrap(aCx, this, aGivenProto);
   1155 }
   1156 
   1157 void HTMLTextAreaElement::GetAutocomplete(nsAString& aValue) {
   1158  aValue.Truncate();
   1159  const nsAttrValue* attributeVal = GetParsedAttr(nsGkAtoms::autocomplete);
   1160 
   1161  mAutocompleteAttrState = nsContentUtils::SerializeAutocompleteAttribute(
   1162      attributeVal, aValue, mAutocompleteAttrState);
   1163 }
   1164 
   1165 void HTMLTextAreaElement::GetAutocompleteInfo(AutocompleteInfo& aInfo) {
   1166  const nsAttrValue* attributeVal = GetParsedAttr(nsGkAtoms::autocomplete);
   1167  mAutocompleteInfoState = nsContentUtils::SerializeAutocompleteAttribute(
   1168      attributeVal, aInfo, mAutocompleteInfoState, true);
   1169 }
   1170 
   1171 }  // namespace mozilla::dom