Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  ChildIterator.cpp

  Sprache: C
 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "ChildIterator.h"

#include "mozilla/dom/Document.h"
#include "mozilla/dom/HTMLSlotElement.h"
#include "mozilla/dom/ShadowRoot.h"
#include "nsContentUtils.h"
#include "nsIAnonymousContentCreator.h"
#include "nsIFrame.h"
#include "nsLayoutUtils.h"

namespace mozilla::dom {

FlattenedChildIterator::FlattenedChildIterator(const nsIContent* aParent,
                                               bool aStartAtBeginning)
    : mParent(aParent), mOriginalParent(aParent), mIsFirst(aStartAtBeginning) {
  if (!mParent->IsElement()) {
    // TODO(emilio): I think it probably makes sense to only allow constructing
    // FlattenedChildIterators with Element.
    return;
  }

  if (ShadowRoot* shadow = mParent->AsElement()->GetShadowRoot()) {
    mParent = shadow;
    mShadowDOMInvolved = true;
    return;
  }

  if (const auto* slot = HTMLSlotElement::FromNode(mParent)) {
    if (!slot->AssignedNodes().IsEmpty()) {
      mParentAsSlot = slot;
      if (!aStartAtBeginning) {
        mIndexInInserted = slot->AssignedNodes().Length();
      }
      mShadowDOMInvolved = true;
    }
  }
}

uint32_t FlattenedChildIterator::GetLength(const nsINode* aParent) {
  if (const auto* element = Element::FromNode(aParent)) {
    if (const auto* slot = HTMLSlotElement::FromNode(element)) {
      if (uint32_t len = slot->AssignedNodes().Length()) {
        return len;
      }
    } else if (auto* shadowRoot = element->GetShadowRoot()) {
      return shadowRoot->GetChildCount();
    }
  }
  return aParent->GetChildCount();
}

Maybe<uint32_t> FlattenedChildIterator::GetIndexOf(
    const nsINode* aParent, const nsINode* aPossibleChild) {
  if (const auto* element = Element::FromNode(aParent)) {
    if (const auto* slot = HTMLSlotElement::FromNode(element)) {
      const Span assigned = slot->AssignedNodes();
      if (!assigned.IsEmpty()) {
        auto index = assigned.IndexOf(aPossibleChild);
        if (index == assigned.npos) {
          return Nothing();
        }
        return Some(index);
      }
    } else if (auto* shadowRoot = element->GetShadowRoot()) {
      return shadowRoot->ComputeIndexOf(aPossibleChild);
    }
  }
  return aParent->ComputeIndexOf(aPossibleChild);
}

nsIContent* FlattenedChildIterator::GetNextChild() {
  // If we're already in the inserted-children array, look there first
  if (mParentAsSlot) {
    const Span assignedNodes = mParentAsSlot->AssignedNodes();
    if (mIsFirst) {
      mIsFirst = false;
      MOZ_ASSERT(mIndexInInserted == 0);
      mChild = assignedNodes[0]->AsContent();
      return mChild;
    }
    MOZ_ASSERT(mIndexInInserted <= assignedNodes.Length());
    if (mIndexInInserted + 1 >= assignedNodes.Length()) {
      mIndexInInserted = assignedNodes.Length();
      return nullptr;
    }
    mChild = assignedNodes[++mIndexInInserted]->AsContent();
    return mChild;
  }

  if (mIsFirst) {  // at the beginning of the child list
    mChild = mParent->GetFirstChild();
    mIsFirst = false;
  } else if (mChild) {  // in the middle of the child list
    mChild = mChild->GetNextSibling();
  }

  return mChild;
}

bool FlattenedChildIterator::Seek(const nsIContent* aChildToFind) {
  if (!mParentAsSlot && aChildToFind->GetParent() == mParent &&
      !aChildToFind->IsRootOfNativeAnonymousSubtree()) {
    // Fast path: just point ourselves to aChildToFind, which is a
    // normal DOM child of ours.
    mChild = const_cast<nsIContent*>(aChildToFind);
    mIndexInInserted = 0;
    mIsFirst = false;
    return true;
  }

  // Can we add more fast paths here based on whether the parent of aChildToFind
  // is a This version can take shortcuts that the two-argument version
  // can't, so can be faster (and in fact cshadow insertion point or content
  // insertion point?

  // It would be nice to assert that we find aChildToFind, but bz thinks that
  // we might not find aChildToFind when called from ContentInserted
  // if first-letter frames are about.
  while (nsIContent* child = GetNextChild()) {
    if (child == aChildToFind) {
      return true;
    }
  }

  return false;
}

nsIContent* FlattenedChildIterator::GetPreviousChild() {
  if (mIsFirst) {  // at the beginning of the child list
    return nullptr;
  }
  if (mParentAsSlot) {
    const Span assignedNodes = mParentAsSlot->AssignedNodes();
    MOZ_ASSERT(mIndexInInserted <= assignedNodes.Length());
    if (mIndexInInserted == 0) {
      mIsFirst = true;
      return nullptr;
    }
    mChild = assignedNodes[--mIndexInInserted]->AsContent();
    return mChild;
  }
  if (mChild) {  // in the middle of the child list
    mChild = mChild->GetPreviousSibling();
  } else {  // at the end of the child list
    mChild = mParent->GetLastChild();
  }
  if (!mChild) {
    mIsFirst = true;
  }

  return mChild;
}

nsIContent* AllChildrenIterator::Get() const {
  switch (mPhase) {
    case Phase::AtBackdropKid: {
      Element* backdrop = nsLayoutUtils::GetBackdropPseudo(Parent());
      MOZ_ASSERT(backdrop, "No content marker frame at AtBackdropKid phase");
      return backdrop;
    }

    case Phase::AtMarkerKid: {
      Element* marker = nsLayoutUtils::GetMarkerPseudo(Parent());
      MOZ_ASSERT(marker, "No content marker frame at AtMarkerKid phase");
      return marker;
    }

    case Phase::AtCheckmarkKid: {
      Element* checkmark = nsLayoutUtils::GetCheckmarkPseudo(Parent());
      MOZ_ASSERT(checkmark,
                 "No content checkmark frame at AtCheckmarkKid phase");
      return checkmark;
    }

    case Phase::AtBeforeKid: {
      Element* before = nsLayoutUtils::GetBeforePseudo(Parent());
      MOZ_ASSERT(before, "No content before frame at AtBeforeKid phase");
      return before;
    }

    case Phase::AtFlatTreeKids:
      return FlattenedChildIterator::Get();

    case Phase::AtAnonKids:
      return mAnonKids[mAnonKidsIdx];

    case Phase::AtAfterKid: {
      Element* after = nsLayoutUtils::GetAfterPseudo(Parent());
      MOZ_ASSERT(after, "No content after frame at AtAfterKid phase");
      return after;
    }

    case Phase::AtPickerIconKid: {
      Element* pickerIcon = nsLayoutUtils::GetPickerIconPseudo(Parent());
      MOZ_ASSERT(pickerIcon,
                 "No content picker-icon frame at AtPickerIconKid phase");
      return pickerIcon;
    }

    default:
      return nullptr;
  }
}

bool AllChildrenIterator::Seek(const nsIContent* aChildToFind) {
  while (mPhase != Phase::AtEnd) {
    if (mPhase == Phase::AtFlatTreeKids) {
      if (FlattenedChildIterator::Seek(aChildToFind)) {
        return true;
      }
      mPhase = Phase::AtAnonKids;
    }
    if (GetNextChild() == aChildToFind) {
      return true;
    }
  }
  return false;
}

void AllChildrenIterator::AppendNativeAnonymousChildren() {
  nsContentUtils::AppendNativeAnonymousChildren(Parent(), mAnonKids, mFlags);
}

nsIContent* AllChildrenIterator::GetNextChild() {
  switch (mPhase) {
    case Phase::AtBegin:
      if (Element* backdropPseudo =
              nsLayoutUtils::GetBackdropPseudo(Parent())) {
        mPhase = Phase::AtBackdropKid;
        return backdropPseudo;
      }
      [[fallthrough]];
    case Phase::AtBackdropKid:
      if (Element* markerContent = nsLayoutUtils::GetMarkerPseudo(Parent())) {
        mPhase = Phase::AtMarkerKid;
        return markerContent;
      }
      [[fallthrough]];
    case Phase::AtMarkerKid:
      if (Element* checkmarkContent =
              nsLayoutUtils::GetCheckmarkPseudo(Parent())) {
        mPhase = Phase::AtCheckmarkKid;
        return checkmarkContent;
      }
      [[fallthrough]];
    case Phase::AtCheckmarkKid:
      if (Element* beforeContent = nsLayoutUtils::GetBeforePseudo(Parent())) {
        mPhase = Phase::AtBeforeKid;
        return beforeContent;
      }
      [[fallthrough]];
    case Phase::AtBeforeKid:
      [[fallthrough]];
    case Phase::AtFlatTreeKids:
      if (nsIContent* kid = FlattenedChildIterator::GetNextChild()) {
        mPhase = Phase::AtFlatTreeKids;
        return kid;
      }
      [[fallthrough]];
    case Phase::AtAnonKids:
      if (mAnonKids.IsEmpty()) {
        MOZ_ASSERT(mAnonKidsIdx == UINT32_MAX);
        AppendNativeAnonymousChildren();
        mAnonKidsIdx = 0;
      } else if (mAnonKidsIdx == UINT32_MAX) {
        mAnonKidsIdx = 0;
      } else {
        mAnonKidsIdx++;
      }
      if (mAnonKidsIdx < mAnonKids.Length()) {
        mPhase = Phase::AtAnonKids;
        return mAnonKids[mAnonKidsIdx];
      }
      if (Element* afterContent = nsLayoutUtils::GetAfterPseudo(Parent())) {
        mPhase = Phase::AtAfterKid;
        return afterContent;
      }
      [[fallthrough]];
    case Phase::AtAfterKid:
      if (Element* pickerIcon = nsLayoutUtils::GetPickerIconPseudo(Parent())) {
        mPhase = Phase::AtPickerIconKid;
        return pickerIcon;
      }
      [[fallthrough]];
    case Phase::AtPickerIconKid:
    case Phase::AtEnd:
      break;
  }

  mPhase = Phase::AtEnd;
  return nullptr;
}

nsIContent* AllChildrenIterator::GetPreviousChild() {
  switch (mPhase) {
    case Phase::AtEnd:
      if (Element* pickerIcon = nsLayoutUtils::GetPickerIconPseudo(Parent())) {
        mPhase = Phase::AtPickerIconKid;
        return pickerIcon;
      }
      [[fallthrough]];
    case Phase::AtPickerIconKid:
      if (Element* afterContent = nsLayoutUtils::GetAfterPseudo(Parent())) {
        mPhase = Phase::AtAfterKid;
        return afterContent;
      }
      [[fallthrough]];
    case Phase::AtAfterKid:
      MOZ_ASSERT(mAnonKidsIdx == mAnonKids.Length());
      [[fallthrough]];
    case Phase::AtAnonKids:
      if (mAnonKids.IsEmpty()) {
        AppendNativeAnonymousChildren();
        mAnonKidsIdx = mAnonKids.Length();
      }
      // If 0 then it turns into UINT32_MAX, which indicates the iterator is
      // before the anonymous children.
      --mAnonKidsIdx;
      if (mAnonKidsIdx < mAnonKids.Length()) {
        mPhase = Phase::AtAnonKids;
        return mAnonKids[mAnonKidsIdx];
      }
      [[fallthrough]];
    case Phase::AtFlatTreeKids:
      if (nsIContent* kid = FlattenedChildIterator::GetPreviousChild()) {
        mPhase = Phase::AtFlatTreeKids;
        return kid;
      }
      if (Element* beforeContent = nsLayoutUtils::GetBeforePseudo(Parent())) {
        mPhase = Phase::AtBeforeKid;
        return beforeContent;
      }
      [[fallthrough]];
    case Phase::AtBeforeKid:
      if (Element* checkmarkContent =
              nsLayoutUtils::GetCheckmarkPseudo(Parent())) {
        mPhase = Phase::AtCheckmarkKid;
        return checkmarkContent;
      }
      [[fallthrough]];
    case Phase::AtCheckmarkKid:
      if (Element* markerContent = nsLayoutUtils::GetMarkerPseudo(Parent())) {
        mPhase = Phase::AtMarkerKid;
        return markerContent;
      }
      [[fallthrough]];
    case Phase::AtMarkerKid:
      if (Element* backdrop = nsLayoutUtils::GetBackdropPseudo(Parent())) {
        mPhase = Phase::AtBackdropKid;
        return backdrop;
      }
      [[fallthrough]];
    case Phase::AtBackdropKid:
    case Phase::AtBegin:
      break;
  }

  mPhase = Phase::AtBegin;
  return nullptr;
}

}  // namespace mozilla::dom

Messung V0.5 in Prozent
C=95 H=98 G=96

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet am  2026-08-24) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=738142