Commit 9e7c428d authored by Emilio Cobos Álvarez's avatar Emilio Cobos Álvarez
Browse files

Bug 1776238 - Pack TextControlState a bit better. r=masayuki

I've confirmed that with this we can add a new string without going over
the current limit of 128 bytes here:

  https://searchfox.org/mozilla-central/rev/6d0ba065e3d41822337c708c8c0aca334ddd9218/dom/html/TextControlState.cpp#1426

Differential Revision: https://phabricator.services.mozilla.com/D150145
parent e998d303
Loading
Loading
Loading
Loading
+38 −47
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ namespace mozilla {
using namespace dom;
using ValueSetterOption = TextControlState::ValueSetterOption;
using ValueSetterOptions = TextControlState::ValueSetterOptions;
using SelectionDirection = nsITextControlFrame::SelectionDirection;

/*****************************************************************************
 * TextControlElement
@@ -1414,7 +1415,6 @@ bool TextControlState::sHasShutDown = false;

TextControlState::TextControlState(TextControlElement* aOwningElement)
    : mTextCtrlElement(aOwningElement),
      mBoundFrame(nullptr),
      mEverInited(false),
      mEditorInitialized(false),
      mValueTransferInProgress(false),
@@ -1486,7 +1486,7 @@ void TextControlState::DeleteOrCacheForReuse() {

    // Prepare for reuse, unlink and release any refcountable objects.
    UnlinkInternal();
    mValue.reset();
    mValue.SetIsVoid(true);
    mTextCtrlElement = nullptr;

    // Put this instance to the cache.  Note that now, the array may be full,
@@ -2067,8 +2067,7 @@ void TextControlState::GetSelectionRange(uint32_t* aSelectionStart,
                                            *aSelectionEnd);
}

nsITextControlFrame::SelectionDirection TextControlState::GetSelectionDirection(
    ErrorResult& aRv) {
SelectionDirection TextControlState::GetSelectionDirection(ErrorResult& aRv) {
  MOZ_ASSERT(IsSelectionCached() || GetSelectionController(),
             "How can we not have a cached selection if we have no selection "
             "controller?");
@@ -2082,21 +2081,21 @@ nsITextControlFrame::SelectionDirection TextControlState::GetSelectionDirection(
  Selection* sel = mSelCon->GetSelection(SelectionType::eNormal);
  if (NS_WARN_IF(!sel)) {
    aRv.Throw(NS_ERROR_FAILURE);
    return nsITextControlFrame::eForward;  // Doesn't really matter
    return SelectionDirection::Forward;
  }

  nsDirection direction = sel->GetDirection();
  if (direction == eDirNext) {
    return nsITextControlFrame::eForward;
    return SelectionDirection::Forward;
  }

  MOZ_ASSERT(direction == eDirPrevious);
  return nsITextControlFrame::eBackward;
  return SelectionDirection::Backward;
}

void TextControlState::SetSelectionRange(
    uint32_t aStart, uint32_t aEnd,
    nsITextControlFrame::SelectionDirection aDirection, ErrorResult& aRv,
void TextControlState::SetSelectionRange(uint32_t aStart, uint32_t aEnd,
                                         SelectionDirection aDirection,
                                         ErrorResult& aRv,
                                         ScrollAfterSelection aScroll) {
  MOZ_ASSERT(IsSelectionCached() || mBoundFrame,
             "How can we have a non-cached selection but no frame?");
@@ -2168,7 +2167,7 @@ void TextControlState::SetSelectionStart(const Nullable<uint32_t>& aStart,
    return;
  }

  nsITextControlFrame::SelectionDirection dir = GetSelectionDirection(aRv);
  SelectionDirection dir = GetSelectionDirection(aRv);
  if (aRv.Failed()) {
    return;
  }
@@ -2194,7 +2193,7 @@ void TextControlState::SetSelectionEnd(const Nullable<uint32_t>& aEnd,
    return;
  }

  nsITextControlFrame::SelectionDirection dir = GetSelectionDirection(aRv);
  SelectionDirection dir = GetSelectionDirection(aRv);
  if (aRv.Failed()) {
    return;
  }
@@ -2203,49 +2202,42 @@ void TextControlState::SetSelectionEnd(const Nullable<uint32_t>& aEnd,
  // The instance may have already been deleted here.
}

static void DirectionToName(nsITextControlFrame::SelectionDirection dir,
                            nsAString& aDirection) {
static void DirectionToName(SelectionDirection dir, nsAString& aDirection) {
  switch (dir) {
    case nsITextControlFrame::eNone:
    case SelectionDirection::None:
      // TODO(mbrodesser): this should be supported, see
      // https://bugzilla.mozilla.org/show_bug.cgi?id=1541454.
      NS_WARNING("We don't actually support this... how did we get it?");
      aDirection.AssignLiteral("none");
      break;
    case nsITextControlFrame::eForward:
      aDirection.AssignLiteral("forward");
      break;
    case nsITextControlFrame::eBackward:
      aDirection.AssignLiteral("backward");
      break;
    default:
      MOZ_ASSERT_UNREACHABLE("Invalid SelectionDirection value");
      return aDirection.AssignLiteral("none");
    case SelectionDirection::Forward:
      return aDirection.AssignLiteral("forward");
    case SelectionDirection::Backward:
      return aDirection.AssignLiteral("backward");
  }
  MOZ_ASSERT_UNREACHABLE("Invalid SelectionDirection value");
}

void TextControlState::GetSelectionDirectionString(nsAString& aDirection,
                                                   ErrorResult& aRv) {
  nsITextControlFrame::SelectionDirection dir = GetSelectionDirection(aRv);
  SelectionDirection dir = GetSelectionDirection(aRv);
  if (aRv.Failed()) {
    return;
  }
  DirectionToName(dir, aDirection);
}

static nsITextControlFrame::SelectionDirection
DirectionStringToSelectionDirection(const nsAString& aDirection) {
static SelectionDirection DirectionStringToSelectionDirection(
    const nsAString& aDirection) {
  if (aDirection.EqualsLiteral("backward")) {
    return nsITextControlFrame::eBackward;
    return SelectionDirection::Backward;
  }

  // We don't support directionless selections, see bug 1541454.
  return nsITextControlFrame::eForward;
  return SelectionDirection::Forward;
}

void TextControlState::SetSelectionDirection(const nsAString& aDirection,
                                             ErrorResult& aRv) {
  nsITextControlFrame::SelectionDirection dir =
      DirectionStringToSelectionDirection(aDirection);
  SelectionDirection dir = DirectionStringToSelectionDirection(aDirection);

  uint32_t start, end;
  GetSelectionRange(&start, &end, aRv);
@@ -2257,11 +2249,11 @@ void TextControlState::SetSelectionDirection(const nsAString& aDirection,
  // The instance may have already been deleted here.
}

static nsITextControlFrame::SelectionDirection
DirectionStringToSelectionDirection(const Optional<nsAString>& aDirection) {
static SelectionDirection DirectionStringToSelectionDirection(
    const Optional<nsAString>& aDirection) {
  if (!aDirection.WasPassed()) {
    // We don't support directionless selections.
    return nsITextControlFrame::eForward;
    return SelectionDirection::Forward;
  }

  return DirectionStringToSelectionDirection(aDirection.Value());
@@ -2272,8 +2264,7 @@ void TextControlState::SetSelectionRange(uint32_t aSelectionStart,
                                         const Optional<nsAString>& aDirection,
                                         ErrorResult& aRv,
                                         ScrollAfterSelection aScroll) {
  nsITextControlFrame::SelectionDirection dir =
      DirectionStringToSelectionDirection(aDirection);
  SelectionDirection dir = DirectionStringToSelectionDirection(aDirection);

  SetSelectionRange(aSelectionStart, aSelectionEnd, dir, aRv, aScroll);
  // The instance may have already been deleted here.
@@ -2587,7 +2578,7 @@ void TextControlState::GetValue(nsAString& aValue, bool aIgnoreWrap) const {
      mBoundFrame->ClearCachedValue();
    }
  } else {
    if (!mTextCtrlElement->ValueChanged() || !mValue) {
    if (!mTextCtrlElement->ValueChanged() || mValue.IsVoid()) {
      // Use nsString to avoid copying string buffer at setting aValue.
      nsString value;
      mTextCtrlElement->GetDefaultValueFromContent(value);
@@ -2595,7 +2586,7 @@ void TextControlState::GetValue(nsAString& aValue, bool aIgnoreWrap) const {
      nsContentUtils::PlatformToDOMLineBreaks(value);
      aValue = value;
    } else {
      aValue = *mValue;
      aValue = mValue;
      MOZ_ASSERT(aValue.FindChar(u'\r') == -1);
    }
  }
@@ -2882,13 +2873,13 @@ bool TextControlState::SetValueWithoutTextEditor(
                       "Failed to commit composition before setting value.  "
                       "Investigate the cause!");

  if (!mValue) {
    mValue.emplace();
  if (mValue.IsVoid()) {
    mValue.SetIsVoid(false);
  }

  // We can't just early-return here, because OnValueChanged below still need to
  // be called.
  if (!mValue->Equals(aHandlingSetValue.GetSettingValue()) ||
  if (!mValue.Equals(aHandlingSetValue.GetSettingValue()) ||
      !StaticPrefs::dom_input_skip_cursor_move_for_same_value_set()) {
    bool handleSettingValue = true;
    // If `SetValue()` call is nested, `GetSettingValue()` result will be
@@ -2948,7 +2939,7 @@ bool TextControlState::SetValueWithoutTextEditor(
    }

    if (handleSettingValue) {
      if (!mValue->Assign(aHandlingSetValue.GetSettingValue(), fallible)) {
      if (!mValue.Assign(aHandlingSetValue.GetSettingValue(), fallible)) {
        return false;
      }

@@ -2969,13 +2960,13 @@ bool TextControlState::SetValueWithoutTextEditor(
                ValueSetterOption::MoveCursorToEndIfValueChanged)) {
          props.SetStart(aHandlingSetValue.GetSettingValue().Length());
          props.SetEnd(aHandlingSetValue.GetSettingValue().Length());
          props.SetDirection(nsITextControlFrame::eForward);
          props.SetDirection(SelectionDirection::Forward);
        } else if (aHandlingSetValue.ValueSetterOptionsRef().contains(
                       ValueSetterOption::
                           MoveCursorToBeginSetSelectionDirectionForward)) {
          props.SetStart(0);
          props.SetEnd(0);
          props.SetDirection(nsITextControlFrame::eForward);
          props.SetDirection(SelectionDirection::Forward);
        }
      }

+20 −19
Original line number Diff line number Diff line
@@ -187,8 +187,9 @@ class RestoreSelectionState;

class TextControlState final : public SupportsWeakPtr {
 public:
  typedef dom::Element Element;
  typedef dom::HTMLInputElement HTMLInputElement;
  using Element = dom::Element;
  using HTMLInputElement = dom::HTMLInputElement;
  using SelectionDirection = nsITextControlFrame::SelectionDirection;

  static TextControlState* Construct(TextControlElement* aOwningElement);

@@ -299,11 +300,11 @@ class TextControlState final : public SupportsWeakPtr {
  // XXX We might have to add assertion when it is into editable,
  // or reconsider fixing bug 597525 to remove these.
  void EmptyValue() {
    if (mValue) {
      mValue->Truncate();
    if (!mValue.IsVoid()) {
      mValue.Truncate();
    }
  }
  bool IsEmpty() const { return mValue ? mValue->IsEmpty() : true; }
  bool IsEmpty() const { return mValue.IsEmpty(); }

  Element* GetRootNode();
  Element* GetPreviewNode();
@@ -331,7 +332,7 @@ class TextControlState final : public SupportsWeakPtr {
   public:
    bool IsDefault() const {
      return mStart == 0 && mEnd == 0 &&
             mDirection == nsITextControlFrame::eForward;
             mDirection == SelectionDirection::Forward;
    }
    uint32_t GetStart() const { return mStart; }
    bool SetStart(uint32_t value) {
@@ -349,10 +350,8 @@ class TextControlState final : public SupportsWeakPtr {
      mIsDirty |= changed;
      return changed;
    }
    nsITextControlFrame::SelectionDirection GetDirection() const {
      return mDirection;
    }
    bool SetDirection(nsITextControlFrame::SelectionDirection value) {
    SelectionDirection GetDirection() const { return mDirection; }
    bool SetDirection(SelectionDirection value) {
      bool changed = mDirection != value;
      mDirection = value;
      mIsDirty |= changed;
@@ -376,8 +375,7 @@ class TextControlState final : public SupportsWeakPtr {
    uint32_t mEnd = 0;
    Maybe<uint32_t> mMaxLength;
    bool mIsDirty = false;
    nsITextControlFrame::SelectionDirection mDirection =
        nsITextControlFrame::eForward;
    SelectionDirection mDirection = SelectionDirection::Forward;
  };

  bool IsSelectionCached() const { return mSelectionCached; }
@@ -513,16 +511,19 @@ class TextControlState final : public SupportsWeakPtr {
  RefPtr<TextInputSelectionController> mSelCon;
  RefPtr<RestoreSelectionState> mRestoringSelection;
  RefPtr<TextEditor> mTextEditor;
  nsTextControlFrame* mBoundFrame;
  nsTextControlFrame* mBoundFrame = nullptr;
  RefPtr<TextInputListener> mTextListener;
  UniquePtr<PasswordMaskData> mPasswordMaskData;
  Maybe<nsString> mValue;

  nsString mValue { VoidString() };  // Void if there's no value.

  SelectionProperties mSelectionProperties;
  bool mEverInited;  // Have we ever been initialized?
  bool mEditorInitialized;
  bool mValueTransferInProgress;  // Whether a value is being transferred to the
                                  // frame
  bool mSelectionCached;          // Whether mSelectionProperties is valid

  bool mEverInited : 1;  // Have we ever been initialized?
  bool mEditorInitialized : 1;
  bool mValueTransferInProgress : 1;  // Whether a value is being transferred to
                                      // the frame
  bool mSelectionCached : 1;          // Whether mSelectionProperties is valid

  /**
   * For avoiding allocation cost of the instance, we should reuse instances
+2 −2
Original line number Diff line number Diff line
@@ -22,13 +22,13 @@ class nsITextControlFrame : public nsIFormControlFrame {
 public:
  NS_DECL_QUERYFRAME_TARGET(nsITextControlFrame)

  enum SelectionDirection { eNone, eForward, eBackward };
  enum class SelectionDirection : uint8_t { None, Forward, Backward };

  virtual already_AddRefed<mozilla::TextEditor> GetTextEditor() = 0;

  MOZ_CAN_RUN_SCRIPT NS_IMETHOD
  SetSelectionRange(uint32_t aSelectionStart, uint32_t aSelectionEnd,
                    SelectionDirection aDirection = eNone) = 0;
                    SelectionDirection = SelectionDirection::None) = 0;

  NS_IMETHOD GetOwnedSelectionController(nsISelectionController** aSelCon) = 0;
  virtual nsFrameSelection* GetOwnedFrameSelection() = 0;
+4 −3
Original line number Diff line number Diff line
@@ -922,7 +922,7 @@ already_AddRefed<TextEditor> nsTextControlFrame::GetTextEditor() {

nsresult nsTextControlFrame::SetSelectionInternal(
    nsINode* aStartNode, uint32_t aStartOffset, nsINode* aEndNode,
    uint32_t aEndOffset, nsITextControlFrame::SelectionDirection aDirection) {
    uint32_t aEndOffset, SelectionDirection aDirection) {
  // Get the selection, clear it and add the new range to it!
  TextControlElement* textControlElement =
      TextControlElement::FromNode(GetContent());
@@ -935,11 +935,12 @@ nsresult nsTextControlFrame::SetSelectionInternal(
  NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);

  nsDirection direction;
  if (aDirection == eNone) {
  if (aDirection == SelectionDirection::None) {
    // Preserve the direction
    direction = selection->GetDirection();
  } else {
    direction = (aDirection == eBackward) ? eDirPrevious : eDirNext;
    direction =
        (aDirection == SelectionDirection::Backward) ? eDirPrevious : eDirNext;
  }

  MOZ_TRY(selection->SetStartAndEndInLimiter(*aStartNode, aStartOffset,
+3 −3
Original line number Diff line number Diff line
@@ -156,7 +156,7 @@ class nsTextControlFrame : public nsContainerFrame,
  GetTextEditor() override;
  MOZ_CAN_RUN_SCRIPT NS_IMETHOD
  SetSelectionRange(uint32_t aSelectionStart, uint32_t aSelectionEnd,
                    SelectionDirection aDirection = eNone) override;
                    SelectionDirection = SelectionDirection::None) override;
  NS_IMETHOD GetOwnedSelectionController(
      nsISelectionController** aSelCon) override;
  nsFrameSelection* GetOwnedFrameSelection() override;
@@ -311,11 +311,11 @@ class nsTextControlFrame : public nsContainerFrame,
  // helper methods
  MOZ_CAN_RUN_SCRIPT nsresult SetSelectionInternal(
      nsINode* aStartNode, uint32_t aStartOffset, nsINode* aEndNode,
      uint32_t aEndOffset, SelectionDirection aDirection = eNone);
      uint32_t aEndOffset, SelectionDirection = SelectionDirection::None);
  MOZ_CAN_RUN_SCRIPT nsresult SelectAllOrCollapseToEndOfText(bool aSelect);
  MOZ_CAN_RUN_SCRIPT nsresult
  SetSelectionEndPoints(uint32_t aSelStart, uint32_t aSelEnd,
                        SelectionDirection aDirection = eNone);
                        SelectionDirection = SelectionDirection::None);

  void FinishedInitializer() { RemoveProperty(TextControlInitializer()); }