void HTMLTextAreaElement::setSuggestedValue(const String& value) {
  m_suggestedValue = value;

  if (!value.isNull())
    setInnerEditorValue(m_suggestedValue);
  else
    setInnerEditorValue(m_value);
  updatePlaceholderVisibility();
  setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(
                                              StyleChangeReason::ControlValue));
}
void HTMLTextAreaElement::setValueCommon(const String& newValue,
                                         TextFieldEventBehavior eventBehavior,
                                         SetValueCommonOption setValueOption) {
  // Code elsewhere normalizes line endings added by the user via the keyboard
  // or pasting.  We normalize line endings coming from JavaScript here.
  String normalizedValue = newValue.isNull() ? "" : newValue;
  normalizedValue.replace("\r\n", "\n");
  normalizedValue.replace('\r', '\n');

  // Return early because we don't want to trigger other side effects
  // when the value isn't changing.
  // FIXME: Simple early return doesn't match the Firefox ever.
  // Remove these lines.
  if (normalizedValue == value()) {
    if (setValueOption == SetSeletion) {
      setNeedsValidityCheck();
      if (isFinishedParsingChildren()) {
        // Set the caret to the end of the text value except for initialize.
        unsigned endOfString = m_value.length();
        setSelectionRange(endOfString, endOfString);
      }
    }
    return;
  }

  m_value = normalizedValue;
  setInnerEditorValue(m_value);
  if (eventBehavior == DispatchNoEvent)
    setLastChangeWasNotUserEdit();
  updatePlaceholderVisibility();
  setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(
                                              StyleChangeReason::ControlValue));
  m_suggestedValue = String();
  setNeedsValidityCheck();
  if (isFinishedParsingChildren()) {
    // Set the caret to the end of the text value except for initialize.
    unsigned endOfString = m_value.length();
    setSelectionRange(endOfString, endOfString);
  }

  notifyFormStateChanged();
  switch (eventBehavior) {
    case DispatchChangeEvent:
      dispatchFormControlChangeEvent();
      break;

    case DispatchInputAndChangeEvent:
      dispatchFormControlInputEvent();
      dispatchFormControlChangeEvent();
      break;

    case DispatchNoEvent:
      // We need to update textAsOfLastFormControlChangeEvent for |value| IDL
      // setter without focus because input-assist features use setValue("...",
      // DispatchChangeEvent) without setting focus.
      if (!isFocused())
        setTextAsOfLastFormControlChangeEvent(normalizedValue);
      break;
  }
}
void HTMLTextAreaElement::childrenChanged(const ChildrenChange& change) {
  HTMLElement::childrenChanged(change);
  setLastChangeWasNotUserEdit();
  if (m_isDirty)
    setInnerEditorValue(value());
  else
    setNonDirtyValue(defaultValue());
}
void HTMLTextFormControlElement::setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode, ExceptionState& exceptionState)
{
    if (start > end) {
        exceptionState.throwDOMException(IndexSizeError, "The provided start value (" + String::number(start) + ") is larger than the provided end value (" + String::number(end) + ").");
        return;
    }
    if (hasAuthorShadowRoot())
        return;

    String text = innerEditorValue();
    unsigned textLength = text.length();
    unsigned replacementLength = replacement.length();
    unsigned newSelectionStart = selectionStart();
    unsigned newSelectionEnd = selectionEnd();

    start = std::min(start, textLength);
    end = std::min(end, textLength);

    if (start < end)
        text.replace(start, end - start, replacement);
    else
        text.insert(replacement, start);

    setInnerEditorValue(text);

    // FIXME: What should happen to the value (as in value()) if there's no renderer?
    if (!renderer())
        return;

    subtreeHasChanged();

    if (equalIgnoringCase(selectionMode, "select")) {
        newSelectionStart = start;
        newSelectionEnd = start + replacementLength;
    } else if (equalIgnoringCase(selectionMode, "start"))
        newSelectionStart = newSelectionEnd = start;
    else if (equalIgnoringCase(selectionMode, "end"))
        newSelectionStart = newSelectionEnd = start + replacementLength;
    else {
        // Default is "preserve".
        long delta = replacementLength - (end - start);

        if (newSelectionStart > end)
            newSelectionStart += delta;
        else if (newSelectionStart > start)
            newSelectionStart = start;

        if (newSelectionEnd > end)
            newSelectionEnd += delta;
        else if (newSelectionEnd > start)
            newSelectionEnd = start + replacementLength;
    }

    setSelectionRange(newSelectionStart, newSelectionEnd, SelectionHasNoDirection);
}