Commit f8501ee2 authored by Masayuki Nakano's avatar Masayuki Nakano
Browse files

Bug 1890915 - Make `EditorBase::CloneAttributesWithTransaction()` collect all...

Bug 1890915 - Make `EditorBase::CloneAttributesWithTransaction()` collect all attributes before updating the DOM tree r=m_kato

`while (RefPtr<Attr> attr = attributes->Item(0))` causes a warning in
`nsDOMAttributeMap::IndexedGetter()` because of out of bounds.  Additionally,
we should not make a loop with live DOM tree information if the loop updates
the DOM tree.  Therefore, this patch makes it collect all attributes first
before touching the DOM tree.

Depends on D207240

Differential Revision: https://phabricator.services.mozilla.com/D207241
parent 2e9ae035
Loading
Loading
Loading
Loading
+22 −6
Original line number Diff line number Diff line
@@ -2940,8 +2940,17 @@ void EditorBase::CloneAttributesWithTransaction(Element& aDestElement,
  bool isDestElementInBody = rootElement->Contains(destElement);

  // Clear existing attributes
  RefPtr<nsDOMAttributeMap> destAttributes = destElement->Attributes();
  while (RefPtr<Attr> attr = destAttributes->Item(0)) {
  AutoTArray<OwningNonNull<Attr>, 16> destElementAttributes;
  if (nsDOMAttributeMap* attributes = destElement->Attributes()) {
    const uint32_t numberOfAttributes = attributes->Length();
    destElementAttributes.SetCapacity(numberOfAttributes);
    for (const auto i : IntegerRange(numberOfAttributes)) {
      if (Attr* attr = attributes->Item(i)) {
        destElementAttributes.AppendElement(*attr);
      }
    }
  }
  for (const OwningNonNull<Attr>& attr : destElementAttributes) {
    if (isDestElementInBody) {
      DebugOnly<nsresult> rvIgnored = RemoveAttributeWithTransaction(
          destElement, MOZ_KnownLive(*attr->NodeInfo()->NameAtom()));
@@ -2957,10 +2966,17 @@ void EditorBase::CloneAttributesWithTransaction(Element& aDestElement,
  }

  // Set just the attributes that the source element has
  RefPtr<nsDOMAttributeMap> sourceAttributes = sourceElement->Attributes();
  uint32_t sourceCount = sourceAttributes->Length();
  for (uint32_t i = 0; i < sourceCount; i++) {
    RefPtr<Attr> attr = sourceAttributes->Item(i);
  AutoTArray<OwningNonNull<Attr>, 16> sourceElementAttributes;
  if (nsDOMAttributeMap* attributes = sourceElement->Attributes()) {
    const uint32_t numberOfAttributes = attributes->Length();
    sourceElementAttributes.SetCapacity(numberOfAttributes);
    for (const auto i : IntegerRange(numberOfAttributes)) {
      if (Attr* attr = attributes->Item(i)) {
        sourceElementAttributes.AppendElement(*attr);
      }
    }
  }
  for (const OwningNonNull<Attr>& attr : sourceElementAttributes) {
    nsAutoString value;
    attr->GetValue(value);
    if (isDestElementInBody) {