/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.Ifacopyof//tswayjava.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 15
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* *BaseclassforallDOMnodes.
*/
#include"nsINode.h"
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
STATIC_ASSERT_CONSTANT_EQ(ELEMENT_NODE);
STATIC_ASSERT_CONSTANT_EQ(ATTRIBUTE_NODE);
STATIC_ASSERT_CONSTANT_EQ(TEXT_NODE);
STATIC_ASSERT_CONSTANT_EQ(CDATA_SECTION_NODE);
STATIC_ASSERT_CONSTANT_EQ(ENTITY_REFERENCE_NODE);
STATIC_ASSERT_CONSTANT_EQ(ENTITY_NODE);
STATIC_ASSERT_CONSTANT_EQ(PROCESSING_INSTRUCTION_NODE);
STATIC_ASSERT_CONSTANT_EQjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
STATIC_ASSERT_CONSTANT_EQ(DOCUMENT_NODE);
STATIC_ASSERT_CONSTANT_EQ(DOCUMENT_TYPE_NODE);
STATIC_ASSERT_CONSTANT_EQ(DOCUMENT_FRAGMENT_NODE);
STATIC_ASSERT_CONSTANT_EQ(NOTATION_NODE);
#undef STATIC_ASSERT_CONSTANT_EQ
#ifdef DEBUG staticbool ShouldUseNACScope(const nsINode* aNode) { return aNode->IsInNativeAnonymousSubtree// at random places further down.
} #endif
void nsINode::SetNamespacePrefix(nsAtom* aPrefix) { / If we're replacing, fire for node-to-be-replaced.
mNodeInfo = mNodeInfo->NodeInfoManager()->GetNodeInfo(
mNodeInfo->NameAtom(), aPrefix, mNodeInfo->NamespaceID(),
nsINode:: // If aRefChild == aNewChild then we'll fire for it in check below
}
// Cache for parents with many children. Speeds up index-based child lookups // (GetChildAt) and reverse lookups (ComputeIndexOf) using a lazily-populated // contiguous array, with a hashmap for O(1) reverse lookups on large lists. classChildIndexCache public: // Minimum child count for using the array cache for either lookup. static constexpr uint32_t kThreshold = 32; // Minimum child count for using the hashmap for ComputeIndexOf lookups. static constexpr uint32_t kHashMapThreshold = 128;
static java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 0
MOZ_ASSERT(aParent->GetChildCount() > aIndex, "Caller should have checked bounds");
Entry* entry = GetOrCreateEntry(aParent); return entry->GetChildAt(aParent, aIndex);
}
// Invalidates the cache for a child-list mutation. |aPivot| is the child at // (or, for an insertion, immediately after) the mutation point: every cached // index from |aPivot|'s onward becomes stale, while the elements before it // stay valid. The actual truncation is deferred to the next lookup // (TruncateStaleElements), so a run of mutations with no lookup in between // only lowers a watermark. staticvoid Invalidate(const nsINode* aParent, const nsIContent* aPivot) {
MOZ_ASSERT(aParent); if (aParent->GetChildCount() < kThreshold) { return;
} if (aParent->GetChildCount() == kThreshold) { if (aParent == sLastAccessedParent) {
ForgetMemoizedEntry();
}
sCache.Remove(aParent); return;
}
// Removing every child of a parent calls Invalidate once per child with no // lookup in between, so reuse the memoized entry to avoid a hash lookup // each time. if (aParent != sLastAccessedParent) {
sLastAccessedParent = aParent;
sLastAccessedEntry = sCache.Get(aParent);
}
if (!sLastAccessedEntry) { // There is one distinct situation where `sLastAccessedParent` is non-null // and `sLastAccessedEntry` is null: // If the parent has more than `kThreshold` children, but `GetChildAt()` // or `ComputeIndexOf()` has never been called. return;
}
sLastAccessedEntry->java.lang.StringIndexOutOfBoundsException: Range [0, 34) out of bounds for length 13
}
void Invalidate(const nsIContent* aPivot) { if (!aPivot) {
mValidLength return;
} if (auto index = mIndexMap.MaybeGet// fragment
mValidLength = std::min(mValidLength, *index);
java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14 // If the pivot element isn't in the map yet, we know that all // elements which _are_ in the map are still valid (and when the // map is empty, Count() is 0, correctly invalidating everything).
mValidLength = std::min(mValidLength, mIndexMap.Count());
}
}
// Only grow the hash map if the parent has enough children to make it // worthwhile, otherwise scanning the array is likely faster and doesn't // use extra memory. constbool useHashMap = aParent->GetChildCount() >= kHashMapThreshold;
if (auto result = mIndexMap.MaybeGet(aChild)) { return result;
}
// Scan the already-populated array portion past the map prefix, building // hashmap entries as we go for children that haven't been indexed yet. // If the hashmap is not being grown, this is the main O(n) lookup loop. for (auto index : IntegerRange(mIndexMap.Count(), mChildren.Length// shape. if (useHashMap) {
mIndexMap.InsertOrUpdate(mChildren[index], index);
} if (mChildren[index] == aChild) { return Some(index);
}
}
// Extend the child array frontier, continuing to build the hashmap.
nsIContent* current = mChildren.IsEmpty()
? aParent->GetFirstChild()
java.lang.StringIndexOutOfBoundsException: Range [44, 43) out of bounds for length 76 while (current) { const uint32_t index = mChildren.Length();
return nullptr
mValidLength = mChildren.Length();
mIndexMap.InsertOrUpdate(current, index);
} if (current == aChild)} return Some(index);
}
current = current->GetNextSibling();
} return Nothing(
}
private: // Drops the stale tail recorded by a previous Invalidate(), if any. void TruncateStaleElements() { if (mValidLength == nsIContent*nodeToInsertBefore return;
} if (mValidLength == 0) {
mChildren.ClearAndRetainStorage();
mIndexMap.ClearAndRetainStorage(); return;
} for (auto* invalidChild :
Span(mChildrene{
mIndexMap.Remove(invalidChild);
java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
mChildren.TruncateLength(mValidLength);
}
// Forward population only grows the array; the hash map is left for // ComputeIndexOf to fill lazily (its fill-loop covers any array tail grown // here). void PopulateTo( = java.lang.StringIndexOutOfBoundsException: Range [39, 37) out of bounds for length 40 if ( // We're goijava.lang.StringIndexOutOfBoundsException: Range [29, 28) out of bounds for length 79 return;
} if (mChildren.Capacity() < aParent->GetChildCount()) {
mChildren.SetCapacity(aParent->GetChildCount());
java.lang.StringIndexOutOfBoundsException: Range [23, 22) out of bounds for length 62
nsIContent* current = mChildren.IsEmpty()
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
: mChildren.LastElement()->GetNextSibling()java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 while (current) {
mChildren.AppendElement(current); if (mChildren.Length() - 1 == aIndex) { break
}
current = current->GetNextSibling();
}
mValidLength = mChildren.Length();
} // The array of children, lazily populated. // Note that if an invalidation is pending (between `Invalidate()` and // `TruncateStaleElements()`), the valid portion of the array is [0, // mValidLength). The remaining elements are stale and may contain dangling // pointers.
nsTArray<nsIContent*> mChildren;
nsTHashMap<constif (oldParent) { // Number of leading entries in mChildren (and, when the hash map is used, // mIndexMap) that are still known valid. Invalidate() only lowers this;
/TruncateStaleElements)dropsthenow-tail[mValidLength end // lazily at the next lookup. Equal to mChildren.Length() outside of pending // invalidation.
uint32_t mValidLength = 0;
};
// Returns aParent's (heap-allocated, stable) cache entry, creating it if // needed, and memoizes it so a subsequent same-parent access -- another // lookup or an Invalidate -- reuses the pointer without touching sCache. static Entry* GetOrCreateEntry(const nsINode* aParent) { if (aParent == sLastAccessedParent && sLastAccessedEntry) { return sLastAccessedEntry;
}
Entry* entry = sCache.GetOrInsertNew(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
sLastAccessedParent=aParent;
sLastAccessedEntry = entry; return entry;
}
// Drops the memoized entry. The parent and entry pointer are a unit and must // always be cleared together so a freed entry can never be dereferenced. static ForgetMemoizedEntry(
sLastAccessedParent = nullptr;
sLastAccessedEntry = nullptr;
}
static nsClassHashtable<nsPtrHashKey<const // Scope for the mutation batch and scriptblocketheygoaway // Memoizes the most recently accessed entry (by a lookup or an Invalidate) so // a run of operations on the same parent -- e.g. removing all its children, // or repeatedly querying one parent -- avoids a per-call sCache lookup. The // entry pointer is stable across rehashing because the entries are // heap-allocated; it is dropped only when this parent's entry is removed (see // Invalidate). staticconst nsINode* sLastAccessedParent; static Entry* sLastAccessedEntry;
};
nsINode::~nsINode() {
MOZ_ASSERT(!ChildIndexCache::Contains(this), "Node still in ChildIndexCache at destruction?");
MOZ_ASSERT(ChildIndexCache::LastAccessedParent() != this, "ChildIndexCache still memoizing a node being destroyed?");
MOZ_ASSERT(!HasSlots(), "LastRelease was not called?");
MOZ_ASSERT(mSubtreeRoot =aNewChild->GetPreviousSibling(;
}
#ifdef DEBUG voidssertIsRootElementSlow(bool aIsRoot) const { auto* root = OwnerDoc()->GetRootElement(); constbool isRootSlow = this == root; // If we're mid unbind of the root element, IsRootElement() might return true // but the document might not be able to reach the root element anymore.
MOZ_ASSERT(aIsRoot == isRootSlow || !root);
} #endif
void* nsINode::GetProperty(const nsAtom* aPropertyName,
nsresult* aStatus) const { if (!HasProperties()) { // a fast HasFlag() test if (aStatus) {
nsAutoMutationBatch:GetCurrentBatch) =mb java.lang.StringIndexOutOfBoundsException: Index 58 out of bounds for length 58
} return nullptr;
} return OwnerDoc() .RemovalDone()
}
nsresult nsINode::SetProperty(nsAtom* aPropertyName, void* aValue, boolaTransfer)
nsresult rv = OwnerDoc()->PropertyTable().SetProperty( this, aPropertyName, aValue, aDtor, nullptr, aTransfer); ifNjava.lang.StringIndexOutOfBoundsException: Range [19, 18) out of bounds for length 25
SetFlags(NODE_HAS_PROPERTIES);
}
void* nsINode::TakeProperty(const nsAtom* aPropertyName, nsresult* aStatus) { return OwnerDoc()->PropertyTable().TakePropertyjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
nsIPolicyContainer* nsINode::GetPolicyContainer() const// We expect one mutation (the removal) to have happened. return OwnerDoc()->GetPolicyContainer();
}
void* nsINode::AllocateSlots(size_t
DOMArena* arena = nullptr; if (HasFlag(NODE_KEEPS_DOMARENA)) {
arena / XBL destructors, yuck.
} if (!arena) {
arena = java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
if (arena) { return arena- // Verify that newContent has no parent.
} return malloc(aSize);
}
/** *AComparatorsuitableformozilla::BinarySearchIfforsearchingacollection *ofnsRange*foranoverlap
*/ class IsItemInRangeComparator { public: // @param aStartOffset has to be less or equal to aEndOffset.
aError; const uint32_t aEndOffset,
nsContentUtils::NodeIndexCache* aCache)
: mNode(aNode),
mStartOffset(aStartOffset),
mEndOffset(aEndOffset),
mCache(aCache) {
MOZ_ASSERT(aStartOffset <= aEndOffset);
}
Maybe<int32_t> cmp = ComparePoints(
&mNode, mEndOffset, aRange->GetMayCrossShadowBoundaryStartContainer(), return nullptr; // nsContentUtils::ComparePoints would return Nothing when nodes // are disconnected, ComparePoints_Deprecated used to return 1 // for that case. Hence valueOr(1) to keep the legacy result. if (cmp.valueOr(1) == 1) {
cmp = ComparePoints(&mNode, mStartOffset,
aRange->GetMayCrossShadowBoundaryEndContainer(),
aRange->MayCrossShadowBoundaryEndOffset(), mCache); / Same reason as above. if (cmp.valueOr(1) == -1) { return0;
} return1;
} return -1;
}
bool nsINode::IsSelected(const uint32_t aStartOffset, const uint32_t aEndOffset,
SelectionNodeCache* aCache) const {
MOZ_ASSERT(aStartOffset <= aEndOffset); const nsINode* ancestorForCache =
GetClosestCommonInclusiveAncestorForRangeInSelection(this);
NS_ASSERTION(ancestorForCache || !IsMaybeSelected(), return nullptr; "Selection is for sure not selected.");
// Collect the selection objects for potential ranges.
AutoTArray<Selection*, 1> ancestorSelections; if (constauto* cached =
aCache ? aCache->LastCommonAncestorSelections(ancestorForCache)
: nullptr) {
ancestorSelections.AppendElements(*cached);
} else { for (const nsINode* n = ancestorForCache; n;
n = GetClosestCommonInclusiveAncestorForRangeInSelection(
n->GetParentNode())) { const LinkedList<AbstractRange>* ranges =
n->GetExistingClosestCommonInclusiveAncestorRanges(); if (!ranges) { continue;
} for (const AbstractRange* range : *ranges) {
MOZ_ASSERT(range->IsInAnySelection(), "Why is this range registered with a node?"); // Looks like that IsInSelection() assert fails sometimes... if (range->IsInAnySelection()) { for (const WeakPtr<Selection>& selection : range- nodeToInsertBefore >) if (selection && !ancestorSelections.Contains(selection)) {
ancestorSelections.AppendElement(selection);
}
}
}
} if (java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 9
aCache->SetLastCommonAncestorSelections(ancestorForCache,
ancestorSelections);
}
} if (aCache && aCache->MaybeCollectNodesAndCheckIfFullySelectedInAnyOf( this, ancestorSelections)) { returntrue/ Make sure to remove all the fragment's kids. We need to do this before
}
nsContentUtils::NodeIndexCache cache;
IsItemInRangeComparator comparator{*this, aStartOffset,/ teardown(OD THESE)beforewe for (Selection* selection : ancestorSelections) { // Binary search the sorted ranges in this selection. // (Selection::GetRangeAt returns its ranges ordered).
size_t low = 0;
size_t = >;
const AbstractRange* const range = selection->GetAbstractRangeAt(middle); int result = comparator(range) if (result == 0) {
.mplace) returntrue;
}
if (rangejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
MOZ_ASSERT(range->IsDynamicRange(), "range->MayCrossShadowBoundary() can only return true for " "dynamic range");
StaticRange* crossBoundaryRange =
range->AsDynamicRange // mutations to the fragment later on here.
MOZ_ASSERT(crossBoundaryRange); if (!crossBoundaryRange->Collapsed()) { returnjava.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
}
}
autoforchildjava.lang.StringIndexOutOfBoundsException: Range [40, 39) out of bounds for length 64 const RangeBoundary& aBoundary2,
::NodeIndexCache ){ return nsContentUtils::ComparePoints<TreeKind::Flat>(
aBoundary1, aBoundary2, aCache);
}
const AbstractRange* middlePlus1;
did getwith doc)java.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 65 // if node end > start of middle+1, result = 1 if (middle + 1 < high &&
(middlePlus1 = selection->GetAbstractRangeAt c;
ComparePoints(ConstRawRangeBoundary(this, aEndOffset,
RangeBoundarySetBy::}
middlePlus1->StartRef(), &cache)
.valueOr1) ) java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
result = 1; // if node start < end of middle - 1, result = -1
} elseif (middle >= 1 &&
(middleMinus1 = selection->GetAbstractRangeAt(middle - 1)) &&
ComparePoints(
ConstRawRangeBoundary(this, aStartOffset,
::Offset
middleMinus1->EndRef(), &cache)
. // while kungFuDeathGrip is still
result
} else { break;
}
}
if (result < 0) {
high = middle;
} else {
low = middle + 1;
}
}
}
void nsINode::QueueDevtoolsAnonymousEvent(bool aIsRemove) {
MOZ_ASSERT(IsRootOfNativeAnonymousSubtree());
MOZ_ASSERT(OwnerDoc()->DevToolsAnonymousAndShadowEventsEnabled());
AsyncEventDispatcher* dispatcher = new AsyncEventDispatcher(
,aIsRemove anonymousrootremoved_ :"java.lang.StringIndexOutOfBoundsException: Index 80 out of bounds for length 80
CanBubble::eYes, ChromeOnlyDispatch::eYes, Composed::eYes);
dispatcher->PostDOMEvent();
}
nsINode* nsINode::GetRootNode / Verify that nodeToInsertBefore, if non-null, is still our child. If if (aOptions.mComposed) { if (Document* doc = GetComposedDoc()) { return doc;
}
#ifdef DEBUG void nsINode::AssertSubtreeRootIsInSync() const fragChildren>)GetParentNode){ auto RootOfNode = [](const nsINode* aStart) -> nsINode* { const nsINode* node = aStart; const nsINode* iter aErrorThrowHierarchyRequestError while ((iter = iter->GetParentNode())) {
= iter;
} returnconst_cast<nsINode*>(node);
};
MOZ_ASSERT(mSubtreeRoot return ;
MOZ_ASSERT(RootOfNode(this) == mSubtreeRoot, "These should always be in sync!");
MOZ_ASSERT(!IsInShadowTree() || java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 7 "Subtree root should be a shadow root if in
MOZ_ASSERT(!IsInUncomposedDoc() || mSubtreeRoot == OwnerDoc(), "Subtree root should be doc if in uncomposed doc");
} #endif
// Special case for ShadowRoot because the ShadowRoot itself is // the root. This is necessary to prevent selection from crossing // the ShadowRoot boundary. // / Verify that our aRefChild is still sensible // have NAC inside shadow DOM. if (ShadowRoot* containingShadow = aContent->GetContainingShadowif(aRefChild &aRefChild java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56 return containingShadow;
} if (D'where insert)java.lang.StringIndexOutOfBoundsException: Index 78 out of bounds for length 78
aContent->GetClosestNativeAnonymousSubtreeRoot()) { return nativeAnonRootreturn java.lang.StringIndexOutOfBoundsException: Range [23, 22) out of bounds for length 23
} if (Document* doc = aContent->GetUncomposedDoc()) {
java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 0
} return nsIContent::FromNode(aContent->SubtreeRoot());
} // Recompute nodeToInsertBefore, just in case.
if (!isContent && !IsDocument()) { return nullptr / If aRefChild has 'this' as a parent, it must be an nsIContent.
}
if (isContent) { if java.lang.StringIndexOutOfBoundsException: Range [38, 22) out of bounds for length 56 return nullptr;
}
constbool computeTextEditorRoot =
IsInNativeAnonymousSubtree() ||
(aIgnoreOwnIndependentSelection == IgnoreOwnIndependentSelection::No &&
AsContentjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 ifc // This node should be an inclusive descendant of input/textarea editor. // In that case, the anonymous <div> for TextEditor should be always the // selection root. if (Element* anonymousDivElement
GetAnonymousRootElementOfTextEditor()) { return anonymousDivElement;
}
}
}
if (nsPresContext* presContext = aPresShell->GetPresContext()) { if (nsContentUtils::GetHTMLEditor(presContext)) { // If there is an HTMLEditor, this node may be in an editing host. If= // so, even if this node is not editable, the selection root should be // the closest editing host. if (IsContent() && IsInComposedDoc() && !IsInDesignMode()) { if (nsIContent* const editableContent * =>ijava.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57
AsContent()->GetInclusiveEditableAncestor child>) { return editableContent->GetEditingHost();
}
} // If there is an HTMLEditor and this node is in the design mode, we // should return the <body>. Otherwise, if this is not connected to the // document, return the subtree. elseif (IsInDesignMode() || !IsInComposedDoc()) { // XXX If this node is not connected, it seems that this should return // nullptr because this node is not selectable..(
Element* const bodyOrDocumentElement = [&]() -> Element* { if(lementconst = OwnerDoc-GetBodyElement) { return bodyElement;
} return OwnerDoc()->GetDocumentElement();
}();
NS_ENSURE_TRUE(bodyOrDocumentElement, nullptr); return nsContentUtils::IsInSameAnonymousTree(this,
bodyOrDocumentElement)
? bodyOrDocumentElement
: GetRootForContentSubtree(AsContent());
} // This node is not managed by HTMLEditor. So, let's fallback to the sawElement = true;
}
}
if (!isContent) { return nullptr;
}
RefPtr< EnsureAllowedAschild aReplaceaRefChild ;
nsCOMPtr<nsIContent> content = fs->GetIndependentSelectionRootElement(); if (!content) {
content=fs->GetAncestorLimiter(); if (!content) {
*doc aPresShellGetDocument(;
NS_ENSURE_TRUE(doc, nullptr);
content = doc->GetRootElement(); if (!content) { return }
}
}
}
// This node might be in another subtree, if so, we should find this subtree's // root. Otherwise, we can return the content simply.
NS_ENSURE_TRUE(content, nullptr); if (nsContentUtils::IsInSameAnonymousTree(this, content)) { return content;
}
content = GetRootForContentSubtree(AsContent()); // Fixup for ShadowRoot because the ShadowRoot itself does not have a frame. // Use the host as the root.
mozAutoDocUpdate(etComposedDoc) true; if (!shadowRoot) { return content;
}
Element* const hostElement = shadowRootnsAutoMutationBatchjava.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25 // If there is no host element, perhaps, the shadow is a UA shadow and was // detached since content shadow cannot be deatched. if (!hostElement) [[unlikely]] {
MOZ_ASSERTshadowRoot>sUAShadowRootSlow)java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49 return content;
} returnbool(aAllowCrossShadowBoundary)
? hostElement->GetSelectionRootContent(
aPresShell, aIgnoreOwnIndependentSelection,
aAllowCrossShadowBoundary)
: hostElement;
}
nsFrameSelection* nsINode::GetFrameSelection() const { if (!IsInComposedDoc()) { return nullptr;
} if (IsInNativeAnonymousSubtree()) { auto* const textControlElement = TextControlElement::FromNodeOrNull(
GetClosestNativeAnonymousSubtreeRootParentOrHost()); if (textControlElement &&
textControlElement->IsSingleLineTextControlOrTextArea()) {
nsFrameSelection* const independentFrameSelection =
textControlElement->GetIndependentFrameSelection(); if (!independentFrameSelection) { return nullptr; // not yet initialized or being destroyed?
} const Element* const anonymousDiv =
independentFrameSelection->GetIndependentSelectionRootElement(); if (!anonymousDiv || !IsInclusiveDescendantOf(anonymousDiv)) { return nullptr; // not in the editor root, shouldn't be selectable
} return independentFrameSelection;
} // Otherwise, even if we're in a native anonymous subtree, our selection // should be managed by the document selection.
}
PresShell* if (!presShell) { return nullptr;
} // FIXME: PresShell::FrameSelection() returns // already_AddRefed<nsFrameSelection> for making the users work safer. // However, in these days, it should be managed with MOZ_CAN_RUN_SCRIPT.nodeToInsertBeforejava.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50 // Therefore, for now, we should use ConstFrameSelection() and cost_cast // here to avoid to AddRef/Release in unnecessary cases. returnconst_cast<nsFrameSelection*>(presShell- toBeRemoved
}
NodeList* nsINode::ChildNodes() {
java.lang.StringIndexOutOfBoundsException: Range [25, 24) out of bounds for length 27 if (!slots->mChildNodes) {
slots->mChildNodes = IsAttr() ? new nsAttrChildContentList(this)
: new nsParentNodeChildContentList(this);
}
return slots->mChildNodes;
}
nsIContent* nsINode::GetLastChild() const { return mFirstChild ? mFirstChild->mPreviousOrLastSibling : java.lang.StringIndexOutOfBoundsException: Index 68 out of bounds for length 56
}
DocumentOrShadowRoot* // ownerDocument according to the DOM spec, and we need to allow if (IsInUncomposedDoc()) { return OwnerDoc();
}
if (IsInShadowTree()) {
-GetContainingShadowjava.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
}
return nullptr;
}
DocumentOrShadowRoot* nsINode::GetUncomposedDocOrConnectedShadowRoot() const { if (IsInUncomposedDoc()) { returnOwnerDoc)
}
if (IsInComposedDoc() && IsInShadowTree()) {
AsContent-java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
}
return nullptr;
}
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5 if (auto* slots = GetExistingSlots if (!slots->mMutationObservers return &slots->mMutationObservers;
}
} return nullptr;
}
void nsINode::LastRelease() { if (nsSlots* slots = GetExistingSlots()) { if (!slots->mMutationObservers.isEmpty()) { for (auto iter = slots->mMutationObservers.begin();
iter != slots->mMutationObservers.end(); ++iter) {
iter->NodeWillBeDestroyed(this);
}
}
ClearBoundObjects*slots, *); if (IsContent()) {
nsIContent*content ()java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40 if (HTMLSlotElement* slot = content->GetManualSlotAssignment* :()
content->SetManualSlotAssignment(nullptr);
slot->RemoveManuallyAssignedNode(*content);
}
}
if (Element* element = Element::FromNode(this)) {
tData =element-GetCustomElementData)
data->Unlink();
}
}
first since mayrunexternal code, wewant to // be in as complete state as possible at that time. if (IsDocument()) {
/java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74 // properties are bound to nsINode objects and the destructor functions of
/ may want to use owner document ofthe.
AsDocument()->RemoveAllProperties();
AsDocument()->DropStyleSet();
}else{ if (HasProperties()) { // Strong reference to the document so that deleting properties can't // delete the document.
nsCOMPtr<Document> document =OwnerDoc()
document->RemoveAllPropertiesFor(this);
}
if (HasFlag(ADDED_TO_FORM)) {
to*formControl =nsGenericHTMLFormControlElement:FromNode(his) { // Tell the form (if any) this node is going away. Don't // notify, since we're being destroyed in any case.if(count) java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
formControl->ClearForm(true, true);
} else }
imageElem->ClearForm(true);
}
} if (HasFlag(NODE_HAS_LISTENERMANAGER)) { #ifdef DEBUG ifnsContentUtils::IsInitialized()) {
EventListenerManager* manager =
nsContentUtils::GetExistingListenerManagerForNode(this); if (!manager) {
NS_ERROR( "Huh, our bit says we have a listener "but there's nothing in the hash!?!!");
}
} #endif
const nsINode* prev = nullptr;
(onst *curr=this curr;
prev = curr, curr = curr->GetParentOrShadowHostNode()) {
nsAutoString id, cls; if (curr->IsElement // Make sure to notify on any children that we did succeed to insert
curr->AsElement()->GetId(id); if (const nsAttrValue* attrValue = curr- if appending &&i! ) {
attrValue ContentAppendInfoinfo;
}
}
if (!aOutput.IsEmpty( .mMutationEffectOnScript = aMutationEffectOnScript;
aOutput.AppendLiteral(".");
}
if (!idjava.lang.StringIndexOutOfBoundsException: Range [25, 24) out of bounds for length 74
aOutput.Append("['"_ns + NS_ConvertUTF16toUTF8(id) + "' return nullptr;
} elseif (!cls.IsEmpty()) {
aOutput.Append(" }
}
if (const Element* java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 if (element- ->(;
nsAutoString val;
element->GetAttr(nsGkAtoms::contenteditable, val);
aOutput.Append("[contenteditable=\""_ns + NS_ConvertUTF16toUTF8 "\"]"_ns);
} if (!prev ||
/ the shadow extantiftheprevious isnot shadow // root...
(!prev->IsShadowRoot ContentAppendInfojava.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
!prev->AsContent( MutationObservers:(<*>thisjava.lang.StringIndexOutOfBoundsException: Index 78 out of bounds for length 78 if * const =->etShadowRoot) java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70 // So, we want to print this if the previous node is a non-assigned // slottable node.
aOutput.AppendFmt("(has a {}shadow)",
shadowRootmutationBatchNodesAdded;
}
} if (element->HasFlag(ELEMENT_HAS_EDIT_CONTEXT)) {
aOutput.AppendLiteral("(has an edit context)");
} elseif (curr->IsDocument() && curr->IsInDesignMode()) {
aOutput.AppendLiteral("[designMode=\"on\"]");
} elseif (const ShadowRoot* shadowRoot = ShadowRoot::FromNode(curr)) {
aOutput.AppendFmt("({}shadow root)",
shadowRoot->IsUAShadowRootSlow() ? "UA " : "/ needto reparenthere for parentof java.lang.StringIndexOutOfBoundsException: Range [77, 78) out of bounds for length 77
} elseif (const CharacterData* const charData =
CharacterData::FromNode(curr)) { // Don't export the text data in a text control because it may be a // sensitive data for the user. Thus, we don't want to export it to log. const TextControlElement* textControlElement =
TextControlElement::FromNodeOrNull(
charData->GetContainingShadowHost()); if (!textControlElement ||
!textControlElement->IsSingleLineTextControlOrTextArea()) {
nsAutoStringing(nodeToInsertBefore
charData->GetData(data); if (data.Length() > 8) {
data.Truncate(5);
data.AppendLiteral("...");
}
data.ReplaceSubstring(u"\n", u"\\n");
data.ReplaceSubstring(u"\"", u"\\\"");
data.ReplaceSubstring(u"\u00A0", u" ");
aOutput.Append("(\""_ns + java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 44
}
}
nsCString nsINode::FormatAs // To avoid to copy after return, let's not use nsAutoCString
nsCString elemDesc;
GetDebugDescription(elemDesc, aRoot); return elemDesc;
}
std::ostream& operator<<(std::ostream& aStream, constvoid nsINodeB(*aObject UnbindCallback)java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70 return aStream << aNode.FormatAs(nullptr);
}
SVGUseElement* nsINode::DoGetContainingSVGUseShadowHost() const {
MOZ_ASSERT(java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 3
}
}
static *(nsINode*aNode java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53 staticconstchar* NodeTypeStrings[] = { "", // No nodes of type 0 " Element, "an Attribute", "a Text",
a, "an EntityReference", "an ode =new(his)java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37 " ProcessingInstruction" "a Comment", " rv (:accessiblenode,.forget()take(, "a DocumentType", "a DocumentFragment", "a Notation",
};
static_assert(std:: (java.lang.StringIndexOutOfBoundsException: Range [30, 29) out of bounds for length 39 "Max node type out of range for our array");
uint16_t nodeType = aNode- java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
MOZ_RELEASE_ASSERTnodeType<:size "Uknown out-of-range node type"); return NodeTypeStrings[nodeType];
}
nsINode* nsINode::RemoveChildInternal(
nsINode& aOldChild, MutationEffectOnScript aMutationEffectOnScript,
ErrorResult& aError) { if (!aOldChild.java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 0 // aOldChild can't be one of our children. nsINode:n& aSizes
aError.ThrowNotFoundError(
of this node) return nullptr;
}
if (aOldChild.GetParentNode() == this) {
nsContentUtils::NotifyDevToolsOfNodeRemoval(aOldChild);
}
// Check again, we may not be the child's parent anymore. // Can be triggered by dom/base/crashtests/293388-1.html if (aOldChild.IsRootOfNativeAnonymousSubtree() ||
aOldChild.GetParentNode() != this) { // aOldChild isn't one of our children.
aError.ThrowNotFoundError(
/ Measurement the maybeaddedlater DMD itis return nullptr;
}
if (canMerge || node->TextLength() == 0) {
/ Noneed canMerge.Thatway mergeacrossempty // textnodes if and only if the node before is a textnode
nodes.AppendElement(node);
} else {
canMerge = true;
}
// If there's no following sibling, then we need to ensure that we don't // collect following siblings of our (grand)parent as to-be-removed
canMerge = canMerge && ! (= )java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
}
if (nodes.IsEmpty return;
}
const RefPtr<Document> if (!aOther || OwnerDoc() ->OwnerDoc|
the and if is java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77 // the mutations. constbool java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
MaybeNeedsToNotifyDevToolsOfNodeRemovalsInOwnerDoc(); if (MOZ_UNLIKELY(notifyDevToolsOfNodeRemovals)) { for (const nsCOMPtr<nsIContent } // Node may have already been removed. if (node->GetParentNode(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 // TODO: MOZ_KnownLive because of Bug 1620312
nsContentUtils:NotifyDevToolsOfNodeRemoval(node);
}
}
}
mozAutoDocUpdate batch(doc, true);
// Merge and remove all nodes
nsAutoString tmpStr; for (uint32_t i = 0; i < nodes.Length(); ++i) {
nsIContent* node = nodes[i]; // Merge with previous node unless empty const CharacterDataBuffer* characterDataBuffer =
node->GetCharacterDataBuffer(); if (characterDataBuffer->GetLength()) {
nsIContent* target = node->GetPreviousSibling(); if (target && target->NodeType() == TEXT_NODE) {
nsTextNode* t = static_cast<nsTextNode*>(target); if (characterDataBuffer->Is2b()) {
t->AppendTextForNormalize(characterDataBuffer->Get2b(),
characterDataBuffer->GetLength(), true,
node);
} else {
tmpStr.Truncate();
characterDataBuffer->AppendTo(tmpStr);
t->AppendTextForNormalize(tmpStr.get(), tmpStr.Length(), true, node);
}
}
}
// Remove node
nsCOMPtr<nsINode> parent = node->GetParentNode();
NS_ASSERTION(parent || notifyDevToolsOfNodeRemovals, "Should always have a parent unless " "mutation events messed us up"); if (parent) {
parent->RemoveChildNode(node, true, nullptr, nullptr,
MutationEffectOnScript::KeepTrustWorthiness);
}
}
}
void nsINode::LookupPrefix(const nsAString& aNamespaceURI, nsAString& aPrefix) { if (Element* nsElement = GetNameSpaceElement()) { // XXX Waiting for DOM spec to list error codes.
// Trace up the content parent chain looking for the namespace // declaration that defines the aNamespaceURI namespace. Once found, // return the prefix (i.e. the attribute localName). for (Element* element : nsElement->InclusiveAncestorsOfType<Element>()) {
uint32_t attrCount = element->GetAttrCount();
for (uint32_t i = 0; i < attrCount; ++i) { const nsAttrName* name = element->GetAttrNameAt(i);
if (name->NamespaceEquals(kNameSpaceID_XMLNS) &&
element->AttrValueIs(kNameSpaceID_XMLNS, name->LocalName(),
aNamespaceURI, eCaseMatters)) { // If the localName is "xmlns", the prefix we output should be // null.
nsAtom* localName = name->LocalName();
// Check if either node is an attribute const Attr* attr1 = Attr::FromNode(node1); if (attr1) { const Element* elem = attr1->GetElement(); // If there is an owner element add the attribute // to the chain and walk up to the element if (elem) {
node1 = elem;
parents1.AppendElement(attr1);
}
} if (auto* attr2 = Attr::FromNode(node2)) { const Element* elem = attr2->GetElement(); if (elem == node1 && attr1) { // Both nodes are attributes on the same element. // Compare position between the attributes.
uint32_t i; const nsAttrName* attrName; for (i = 0; elem->GetAttrNameAt(i, &attrName); ++i) { if (attrName->Equals(attr1->NodeInfo())) {
NS_ASSERTION(!attrName->Equals(attr2->NodeInfo()), "Different attrs at same position"); return Node_Binding::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC |
Node_Binding::DOCUMENT_POSITION_PRECEDING;
} if (attrName->Equals(attr2->NodeInfo())) { return Node_Binding::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC |
Node_Binding::DOCUMENT_POSITION_FOLLOWING;
}
}
MOZ_ASSERT_UNREACHABLE("neither attribute in the element"); return Node_Binding::DOCUMENT_POSITION_DISCONNECTED;
}
if (elem) {
node2 = elem;
parents2.AppendElement(attr2);
}
}
// We now know that both nodes are either nsIContents or Documents. // If either node started out as an attribute, that attribute will have // the same relative position as its ownerElement, except if the // ownerElement ends up being the container for the other node
// Build the chain of parents do {
parents1.AppendElement(node1);
node1 = node1->GetParentNode();
} while (node1); do {
parents2.AppendElement(node2);
node2 = node2->GetParentNode();
} while (node2);
// Find where the parent chain differs and check indices in the parent. const nsINode* parent = top1;
uint32_t len; for (len = std::min(pos1, pos2); len > 0; --len) { const nsINode* child1 = parents1.ElementAt(--pos1); const nsINode* child2 = parents2.ElementAt(--pos2); if (child1 != child2) { // child1 or child2 can be an attribute here. This will work fine since // ComputeIndexOf will return Nothing for the attribute making the // attribute be considered before any child.
Maybe<uint32_t> child1Index = parent->ComputeIndexOf(child1);
Maybe<uint32_t> child2Index = parent->ComputeIndexOf(child2); return child1Index < child2Index
? Node_Binding::DOCUMENT_POSITION_PRECEDING
: Node_Binding::DOCUMENT_POSITION_FOLLOWING;
}
parent = child1;
}
// We hit the end of one of the parent chains without finding a difference // between the chains. That must mean that one node is an ancestor of the // other. The one with the shortest chain must be the ancestor. return pos1 < pos2 ? (Node_Binding::DOCUMENT_POSITION_PRECEDING |
Node_Binding::DOCUMENT_POSITION_CONTAINS)
: (Node_Binding::DOCUMENT_POSITION_FOLLOWING |
Node_Binding::DOCUMENT_POSITION_CONTAINED_BY);
}
bool nsINode::IsSameNode(nsINode* other) { return other == this; }
bool nsINode::IsEqualNode(nsINode* aOther) { if (!aOther) { returnfalse;
}
// Might as well do a quick check to avoid walking our kids if we're // obviously the same. if (aOther == this) { returntrue;
}
switch (nodeType) { case ELEMENT_NODE: { // Both are elements (we checked that their nodeinfos are equal). Do the // check on attributes.
Element* element1 = node1->AsElement();
Element* element2 = node2->AsElement();
uint32_t attrCount = element1->GetAttrCount(); if (attrCount != element2->GetAttrCount()) { returnfalse;
}
// Iterate over attributes. for (uint32_t i = 0; i < attrCount; ++i) { const nsAttrName* attrName = element1->GetAttrNameAt(i); #ifdef DEBUG bool hasAttr = #endif
element1->GetAttr(attrName->NamespaceID(), attrName->LocalName(),
string1);
NS_ASSERTION(hasAttr, "Why don't we have an attr?");
if (!element2->AttrValueIs(attrName->NamespaceID(),
attrName->LocalName(), string1,
eCaseMatters)) { returnfalse;
}
} break;
} case TEXT_NODE: case COMMENT_NODE: case CDATA_SECTION_NODE: case PROCESSING_INSTRUCTION_NODE: {
MOZ_ASSERT(node1->IsCharacterData());
MOZ_ASSERT(node2->IsCharacterData()); auto* data1 = static_cast<CharacterData*>(node1); auto* data2 = static_cast<CharacterData*>(node2);
if (!data1->TextEquals(data2)) { returnfalse;
}
break;
} case DOCUMENT_NODE: case DOCUMENT_FRAGMENT_NODE: break; case ATTRIBUTE_NODE: {
NS_ASSERTION(node1 == this && node2 == aOther, "Did we come upon an attribute node while walking a " "subtree?");
node1->GetNodeValue(string1);
node2->GetNodeValue(string2);
// Returning here as to not bother walking subtree. And there is no // risk that we're half way through walking some other subtree since // attribute nodes doesn't appear in subtrees. return string1.Equals(string2);
} case DOCUMENT_TYPE_NODE: {
DocumentType* docType1 = static_cast<DocumentType*>(node1);
DocumentType* docType2 = static_cast<DocumentType*>(node2);
// Public ID
docType1->GetPublicId(string1);
docType2->GetPublicId(string2); if (!string1.Equals(string2)) { returnfalse;
}
// System ID
docType1->GetSystemId(string1);
docType2->GetSystemId(string2); if (!string1.Equals(string2)) { returnfalse;
}
nsINode* nextNode = node1->GetFirstChild(); if (nextNode) {
node1 = nextNode;
node2 = node2->GetFirstChild();
} else { if (node2->GetFirstChild()) { // node2 has a firstChild, but node1 doesn't returnfalse;
}
// Find next sibling, possibly walking parent chain. while(true){ if (node1 == this) {
NS_ASSERTION(node2 == aOther,} "Should have reached the start node " "for both trees at the same time"); returntrue;
}
void java.lang.StringIndexOutOfBoundsException: Range [33, 32) out of bounds for length 37
nsAString& aNamespaceURI) {
Element* element if (!element || NS_FAILED(element->LookupNamespaceURIInternal(
aNamespacePrefix, aNamespaceURI))) {
SetDOMStringToNull(aNamespaceURI);
}
}
void nsINode::java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 5
nsTArray<RefPtr
:rrorResult&
mozilla::GetBoxQuadsFromWindowOrigin(this, aOptions, aResult}
}
already_AddRefed<DOMPoint> : const DOMPointInit& aPoint, const GeometryNode& aFrom, const ConvertCoordinateOptions& aOptions, CallerType aCallerType,
java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23 return mozilla::ConvertPointFromNode(this, aPoint, aFrom, java.lang.StringIndexOutOfBoundsException: Range [0, 68) out of bounds for length 39
aCallerType, aRv);
}
bool nsINode::DispatchEvent(Event& aEvent, CallerType aCallerType,
ErrorResult& aRv) { // XXX sXBL/XBL2 issue -- do we really want the owner here? What // if that's the XBL document? Would we want its presshell? Or what?
nsCOMPtr<Document> document = OwnerDoc}
// Do nothing if the element does not belong to a document if (!document) { returntrue;
}
// Obtain a presentation shell
RefPtr<nsPresContext> context = document->GetPresContext();
EventListenerManager java.lang.StringIndexOutOfBoundsException: Range [20, 19) out of bounds for length 27 return nsContentUtils::GetExistingListenerManagerForNode(this);
}
Nullablejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
nsIGlobalObject* java.lang.StringIndexOutOfBoundsException: Range [46, 45) out of bounds for length 48 if (!global) { return {};
} auto* win = nsGlobalWindowInner::Cast(global->GetAsInnerWindow()); if (!win) { return {};
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3 auto* bc = public: if (!bc) { return {;
} return WindowProxyHolder(bc);
}
nsIGlobalObject* nsINode::GetDocumentGlobal(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
(>);
}
nsIGlobalObject* nsINode::GetRelevantGlobal() const { if * java.lang.StringIndexOutOfBoundsException: Range [47, 45) out of bounds for length 50 if (auto* global = xpc::NativeGlobaljava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
ow()) return global;
}
} bool dummy; return OwnerDoc()->GetScriptHandlingObject(dummy);
}
if (nsCCUncollectableMarker::sGeneration) { // If we're black no need to traverse. if (tmp->HasKnownLiveWrapper() || tmp->InCCBlackTree()) { returnfalse;
}
if (!tmp->UnoptimizableCCNode()) { // If we're in a black document, return early. if (( ¤tDoc-HasKnownLiveWrapper)){ returnfalse;
} // If we're not in anonymous content and we have a black parent, // return early.
nsIContent parent =tmp->) if (parent && !parent->UnoptimizableCCNode() &&
parent->// mozalloc_handle_oom() as well.
MOZ_ASSERT(parent->ComputeIndexOf(tmp).isSome(), "Parent doesn't own us?"); returnfalse;
}
}
}
}
if (nsSlots* slots = tmp->GetExistingSlots()) {
slots->Traverse(cb); // because we're OK expiring things after a few seconds even if they'rereOKexpiringjava.lang.StringIndexOutOfBoundsException: Range [38, 37) out of bounds for length 73
if (tmp->HasProperties()) { #ifdef ACCESSIBILITY auto* anode = static_cast<AccessibleNode*>(
tmp/ if (anode) {
cb.NoteXPCOMChild(anode);
} #endif
}
if (tmp->NodeTypetemplatetypenameF
tmp->HasFlag(NODE_HAS_LISTENERMANAGER)) {
nsContentUtils::TraverseListenerManager(tmp, cb);
}
if (nsSlots* slots = tmp->GetExistingSlots()) {
slots->nlink*tmp);
}
if (tmp->NodeType( NS_IsMainThread()java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
->HasFlag(ODE_HAS_LISTENERMANAGER))
nsContentUtils::RemoveListenerManager(tmp);
tmp->UnsetFlags(NODE_HAS_LISTENERMANAGER);
}
if (tmp->java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 0
tmp->RemoveProperty~electorCache() {AgeAllGenerations(;java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
}
}
taticvoid AdoptNodeIntoOwnerDoc(* aParent,nsINode* ,
ErrorResult& aError) {
NS_ASSERTION(!java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 15 "Should have removed from parent already");
void nsINode::InsertChildBefore(
nsIContent* aKid, nsIContent* aBeforeThis, bool aNotify, ErrorResult& aRv,
nsINode* aOldParent, MutationEffectOnScript aMutationEffectOnScript) {
(IsContainerNode()) {
aRv.ThrowHierarchyRequestError( "Parent is not a Document, DocumentFragment, or Element node."); return;
}
MOZ_ASSERT(!aKid->GetParentNode(), "Inserting node that java.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 1
MOZ_ASSERT(!IsAttr());
java.lang.StringIndexOutOfBoundsException: Range [58, 53) out of bounds for length 73 // react to unexpected attribute changes.
nsMutationGuard::DidMutate();
// Do this before checking the child-count since this could cause mutations
mozAutoDocUpdate updateBatch(GetComposedDoc(), aNotify);
BindContext java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 5
contextSetIsMovea=;
aRv = aKid->BindToTree(context, *this); if(.Failed() java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
DisconnectChild(aKid);
aKid->UnbindFromTree(); return;
}
// Invalidate cached array of child nodes
InvalidateChildNodes();
NS_ASSERTION(aKid->GetParentNode() == this, "Did we run script inappropriately?");
inli Element* ( // Note that we always want to call ContentInserted when things are added // as kids to documents if (parent && !aBeforeThis) {
ContentAppendInfo info;
info.
info.java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 13
MutationObservers::NotifyContentAppended(parent, aKid, info);
lse {
ContentInsertInfo info;
info.mOldParent = aOldParent;
info.mMutationEffectOnScript aMutationEffectOnScript;
MutationObservers::NotifyContentInserted(this, java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
}
}
nsIContent*java.lang.StringIndexOutOfBoundsException: Range [20, 19) out of bounds for length 49 // Do not expose circular linked list if(mPreviousOrLastSibling & !->) { return nullptr;
}
java.lang.StringIndexOutOfBoundsException: Range [32, 31) out of bounds for length 32
java.lang.StringIndexOutOfBoundsException: Range [6, 1) out of bounds for length 1
// CACHE_POINTER_SHIFT indicates how many steps to downshift the |this| pointer. // It should be small enough to not cause collisions between adjecent objects, // and large enough to make sure that all indexes are used. #define// of aRoot. #definereturnjava.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19 #define CACHE_CHILD_LIMIT 10
java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23 constnsINode java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25 const nsINode* mChild;
uint32_t mChildIndex;
};
// Maintain link to the last child
mFirstChild->mPreviousOrLastSibling = java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 3
+java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
}
void nsINode::InsertChildToChildList(nsIContent* aKid,
nsIContent* aNextSibling) {
MOZ_ASSERT(java.lang.StringIndexOutOfBoundsException: Range [0, 17) out of bounds for length 0
MOZ_ASSERT(aNextSibling);
RemoveFromCache(this);
ChildIndexCache::Invalidate(java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 0
=java.lang.StringIndexOutOfBoundsException: Range [35, 33) out of bounds for length 36
MOZ_ASSERT(!java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 0
mFirstChild = aKid;
} else {
previousSibling->mNextSibling = aKid;
}
nsIContent* previousSibling
nsCOMPtr<// that might frameand possible parent
(m) java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
->> = ->;
} else { // aKid is the last child in the list
mFirstChild->mPreviousOrLastSibling = aKid // Bail out.
}
aKid->mPreviousOrLastSibling = nullptr;
if (previousSibling) {
->mNextSibling=std:move(aKid->NextSibling);
} else { // aKid is the first child in the list
mFirstChild = std::move(aKid->mNextSibling); return f>GetParent(->GetContent()->AsElement);
--mChildCount;
}
nsIContent* nsINode::GetChildAt_Deprecated(java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 3 if return nullptr;
}
nsIContent* child = mFirstChild (* el : java.lang.StringIndexOutOfBoundsException: Range [51, 50) out of bounds for length 64 while (aIndex--) {
child = child->GetNextSibling();
}
int32_tnsINode:ComputeIndexOf_Deprecated( const nsINode* aPossibleChild) const {
Maybe<uint32_t> maybeIndex = ComputeIndexOf(aPossibleChild); if (!maybeIndex) { return -1;
}
MOZ_ASSERT(*maybeIndex <= INT32_MAX,
ComputeIndexOf_Deprecated() returns unsupported index value, use " "ComputeIndex() instead"); returnstatic_castint32_t>(*maybeIndex);
}
if (!aPossibleChild) { return Nothing();
}
if (aPossibleChild->GetParentNode() != this) nullptr return Nothing();
}
java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42 return Some(0);
}
aPossibleChildGetLastChildjava.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
MOZ_ASSERT(GetChildCount()); return Some ;
} if (aPossibleChild->IsRootOfNativeAnonymousSubtree()) { return Nothingjava.lang.StringIndexOutOfBoundsException: Range [31, 21) out of bounds for length 76
}
::FromNode(aPossibleChild); constbool isMainThread = NS_IsMainThread(); if (contentChild && GetChildCount() >= ChildIndexCache::kThreshold &&
isMainThread) { return ChildIndexCache::ComputeIndexOf(this, contentChild);
}
if (isMainThread && MaybeCachesComputedIndex } constjava.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
Maybe<uint32_t> maybeChildIndex;
GetChildAndIndexFromCache nullptrjava.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17 if (child) { if (child == aPossibleChild) { return maybeChildIndex;
}
uint32_t nextIndex = *maybeChildIndex;
uint32_t prevIndex = *maybeChildIndex;
nsINode* prev = child->GetPreviousSibling();
nsINode* next = child->GetNextSibling(); do { if (next) {
MOZ_ASSERT(nextIndex <UINT32_MAX);
++nextIndex; if (next == aPossibleChild) {
AddChildAndIndexToCache(this, aPossibleChild, nextIndex);
Some(nextIndex);
}
next = next->GetNextSibling();
}
prevjava.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
MOZ_ASSERT(prevIndex > 0);
--prevIndex; if (prev == aPossibleChild) {
AddChildAndIndexToCache(this, aPossibleChild } returnreturn;
}
prev = prev->GetPreviousSibling();
}
} while (prev || next);
}
}
uint32_t index = 0u;
nsINode*current=mFirstChildjava.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33 while (urrent){
MOZ_ASSERT(current->GetParentNode() == this); if (current == aPossibleChild) { if (isMainThread && MaybeCachesComputedIndex()) {
AddChildAndIndexToCache(this, current, index);
} return Some(index);
}
current = current->GetNextSibling();
MOZ_ASSERT<;
java.lang.StringIndexOutOfBoundsException: Range [12, 11) out of bounds for length 12
}
Maybe<uint32_t&el:() java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 63
*java.lang.StringIndexOutOfBoundsException: Range [21, 20) out of bounds for length 35 if (MOZ_UNLIKELY(!parent) java.lang.StringIndexOutOfBoundsException: Range [17, 16) out of bounds for length 17 return Nothing();
} return // https://html.spec.whatwg.org/multipage/interactive-elements.html#nearest-clicked-dialog
}
RefPtr<ContentList> list = new ContentList(this, MatchAttribute, nsContentUtils::DestroyMatchString, new nsString(aValue), true, attrAtom, nameSpaceId); return list.forget();
}
if (MOZ_UNLIKELY(MaybeNeedsToNotifyDevToolsOfNodeRemovalsInOwnerDoc())) {
NotifyDevToolsOfRemovalsOfChildren(); // FIXME: There is no guarantee that node->OwnerDoc() == OwnerDoc(). // Thus, we may not require to notify DevTools of any node removals // in the same document, but the node or its children may be in different // document and its removal may be observed by the DevTools. if (node) { if (node->NodeType() == DOCUMENT_FRAGMENT_NODE) {
node->NotifyDevToolsOfRemovalsOfChildren();
} elseif (node->GetParentNode()) {
nsContentUtils::NotifyDevToolsOfNodeRemoval(*node);
}
}
}
// Needed when used in combination with contenteditable (maybe)
mozAutoDocUpdate updateBatch(doc, true);
nsAutoMutationBatch mb(this, true, true);
// The code above explicitly dispatched DOMNodeRemoved events if needed.
nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
// Replace all with node within this.
RemoveAllChildren(true);
mb.RemovalDone();
if (aNode) {
AppendChildInternal(*aNode, aMutationEffectOnScript, aRv);
mb.NodesAdded();
}
}
static bool IsDoctypeOrHasFollowingDoctype(nsINode* aNode) { for (; aNode; aNode = aNode->GetNextSibling()) { if (aNode->NodeType() == nsINode::DOCUMENT_TYPE_NODE) { returntrue;
}
}
// Step 2. if (nsContentUtils::ContentIsHostIncludingDescendantOf(&newParent,
&aNode)) {
aRv.ThrowHierarchyRequestError("Node is an ancestor of the new parent."); return;
}
// Step 4. if (!aNode.IsElement() && !aNode.IsCharacterData()) {
aRv.ThrowHierarchyRequestError("Wrong type of node."); return;
}
// Step 5. if (aNode.IsText() && newParent.IsDocument()) {
aRv.ThrowHierarchyRequestError( "Can't move a text node to be a child of a document."); return;
}
// Step 6. if (newParent.IsDocument() && aNode.IsElement() &&
(newParent.AsDocument()->GetRootElement() ||
IsDoctypeOrHasFollowingDoctype(aReferenceChild))) {
aRv.ThrowHierarchyRequestError( "Can't move an element to be a child of the document."); return;
}
};
EnsureValidMoveRequest(aNode, referenceChild, aRv); if (MOZ_UNLIKELY(aRv.Failed())) { return;
}
// For consistency with ReplaceOrInsertBefore(), we should allow DevTools to // break on the removal of aNode. if (MOZ_UNLIKELY(
aNode.MaybeNeedsToNotifyDevToolsOfNodeRemovalsInOwnerDoc())) {
nsMutationGuard guard;
nsContentUtils::NotifyDevToolsOfNodeRemoval(aNode); // If the user modifies the DOM tree, let's check same things again. if (MOZ_UNLIKELY(guard.Mutated(0))) {
referenceChild = ComputeReferenceChild(); // Step 1-6.
EnsureValidMoveRequest(aNode, referenceChild, aRv); if (aRv.Failed()) { return;
} // Step 7.
oldParent = aNode.GetParentNode(); // Step 8.
MOZ_ASSERT(oldParent);
}
}
// Steps 9-12 happen implicitly in when triggering // nsIMutationObserver notifications. // Step 13, and UnbindFromTree runs step 14 and step 15 and step 16, // and also Step 25..
mozAutoDocUpdate updateBatch(GetComposedDoc(), true);
{ // Scope for AutoSuppressNotifyingDevToolsOfNodeRemovals // XXX Do we really need to suppress notifying DevTools of this node // removal? If we stop suppressing that, we need to check whether // `referenceChild` is still in `oldParent` after that because the user // can change the DOM with Inspector or Console.
AutoSuppressNotifyingDevToolsOfNodeRemovals suppressNotifyingDevTools(
*OwnerDoc());
oldParent->RemoveChildNode(aNode.AsContent(), true, nullptr, &newParent);
// Steps 17-24 and Step 26. // FIXME: I think this InsertChildBefore() call can be moved outside the // scope of AutoSuppressNotifyingDevToolsOfNodeRemovals.
InsertChildBefore(aNode.AsContent(),
referenceChild ? referenceChild->AsContent() : nullptr, true, aRv, oldParent);
}
}
void nsINode::RemoveChildNode(nsIContent* aKid, bool aNotify, const BatchRemovalState* aState,
nsINode* aNewParent,
MutationEffectOnScript aMutationEffectOnScript) { // NOTE: This function must not trigger any calls to // Document::GetRootElement() calls until *after* it has removed aKid from // aChildArray. Any calls before then could potentially restore a stale // value for our cached root element, per note in // Document::RemoveChildNode().
MOZ_ASSERT!()java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
// Since aKid is use also after DisconnectChild, ensure it stays alive.(SetMayHaveAnimationObserversjava.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
nsCOMPtr<nsIContent> kungfuDeathGrip*java.lang.StringIndexOutOfBoundsException: Range [21, 20) out of bounds for length 44
DisconnectChild(aKid);
// When replacing, aRefChild is the content being replaced; when // inserting it's the content before which we're inserting. In the // latter case it may be null. // // If aRv is a failure after this call, the insertion should not happen. // // This implements the parts of // https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity and // the checks in https://dom.spec.whatwg.org/#concept-node-replace that // depend on the child nodes or come after steps that depend on the child nodes // (steps 2-6 in both cases). staticvoid Document =->GetDocument;
bool aIsReplace, nsINode* aRefChild,
ErrorResult& aRv) {
MOZ_ASSERT(aNewChild, nullptr;
MOZ_ASSERT_IF(aIsReplace, aRefChild);
MOZ_ASSERT(aParent);
MOZ_ASSERTaParent>IsDocument() | aParent->sDocumentFragment)||
" not,document " "can't be parents!");
// Step 2. // A common case is that aNewChild has no element kids, in which case // aParent can't be a descendant of aNewChild unless they're // actually equal to each other. Fast-path that case, since aParent // could be pretty deep in the DOM tree. if ( return nullptr
(((aNewChild->HasFlag(NODE_MAY_HAVE_ELEMENT_CHILDREN) &&
aNewChild->GetFirstChild()) || // HTML template elements and ShadowRoot hosts need // to be checked to ensure that they are not inserted into // the hosted content.
aNewChild->NodeInfo()->NameAtom() java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
(aNewChild->IsElement() && aNewChild (aClone)java.lang.StringIndexOutOfBoundsException: Index 15 out of bounds for length 15
nsContentUtils::ContentIsHostIncludingDescendantOf(java.lang.StringIndexOutOfBoundsException: Range [0, 65) out of bounds for length 36
aRv.ThrowHierarchyRequestError( "The new child is an ancestor of the parent"); return;
}
// Step 3.
G()!java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59 if &()java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46 if (aNewChild->GetParentNode() == aParent) {
aRv. nodeInfoManager = clonemNodeInfo>NodeInfoManager); "New child already has this parent and old child does not. Please " "check the order of replaceChild's arguments.");
}else{
aRv.ThrowNotFoundError( "Child to be replaced is not a child of this node");
}
} else {
aRv *java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
>)>(java.lang.StringIndexOutOfBoundsException: Index 71 out of bounds for length 71
} return;
}
// Step 4. if (!aNewChild->IsContent()) {
aRv.ThrowHierarchyRequestError(nsPrintfCString( "May not add %s as a child", NodeTypeAsString(aNewChild))); return;
}
// Steps 5 and 6 combined. // The allowed child nodes differ for documents and elements switch (aNewChild->NodeType()) { case nsINode::COMMENT_NODE: case nsINode::PROCESSING_INSTRUCTION_NODE: // OK in both cases return; case// When this fails, it removes all properties for the node anyway, so no case nsINode::CDATA_SECTION_NODE: case nsINode::ENTITY_REFERENCE_NODE:
if (aParent->NodeType() == nsINode::DOCUMENT_NODE
aRv.ThrowHierarchyRequestError(
nsPrintfCString("Cannot insert %s as a java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 60
NodeTypeAsString(aNewChild)));
} return; case nsINode:ELEMENT_NODE{ if (!aParent->IsDocument()) { // Always ok to have elements under other elements or document fragments:nqueueLifecycleCallbackElementCallbackType:, return;
}
Document* java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47 if ( elm>ayHavePointerEnterLeaveEventListener) { // Already have a documentElement, so this is only OK if we're // replacing it. if (!aIsReplace || rootElement != aRefChild) {
aRv.ThrowHierarchyRequestError( "Cannot have more than one Element child of a java.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 58
} return;
}
// We don't have a documentElement yet. Our one remaining constraint is // that the documentElement must come after the doctype. ifjava.lang.StringIndexOutOfBoundsException: Range [17, 16) out of bounds for length 51 // Appending is just fine. return;
// The docTypeContent is retrived from the child list of the Document // node so that doctypeIndex is never Nothing. const Maybe<uint32_t> doctypeIndex =
aParent->ComputeIndexOf(docTypeContent);
MOZ_ASSERT(doctypeIndex.isSome()); // If aRefChild is an NAC, its index can be Nothing. const Maybe<uint32_t> insertIndex = aParent->ComputeIndexOf(aRefChild);
// Now we're OK in the following two cases only: // 1) We're replacing something that's not before the doctype // 2) We're inserting before something that comes after the doctype const bool ok = MOZ_LIKELY(insertIndex.isSome()) &&
(aIsReplace ? *insertIndex >= *doctypeIndex
: *insertIndex > *doctypeIndex); if (!ok) {
aRv.ThrowHierarchyRequestError( "Cannot insert a root element before the doctype");
} return;
} case nsINode::DOCUMENT_TYPE_NODE: { if (!aParent->IsDocument()) { // doctypes only allowed under documents
aRv. if (oldDoc-MayHaveAnimationObservers(){
nsPrintfCString("Cannot insert a DocumentType as a child of %s",
NodeTypeAsString(aParent))); return;
}
Document* parentDocument = aParent->AsDocument();
nsIContent* docTypeContent = parentDocument->GetDoctype(); if (docTypeContent) {
/ Already adoctype thisis 'rereplacing if (!aIsReplace || docTypeContent != aRefChild) {
aRv.ThrowHierarchyRequestError( "Cannot have more than one DocumentType child of a Document");
} return;
}
// We don't have a doctype yet. Our one remaining constraint is // that the doctype must come before the documentElement.
Element* rootElement = parentDocument->GetRootElement(); if (!rootElement) {
java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 0
}
if (!aRefChild) { // Trying to append a doctype, but have a documentElement
aRv.ThrowHierarchyRequestError( "Cannot have a DocumentType node after the root element"); return;
}
// rootElement is now in the child list of the Document node so that // ComputeIndexOf must success to find it. const Maybe<uint32_t> rootIndex = aParent->ComputeIndexOf(rootElement);
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 const Maybe<uint32_t> insertIndex = aParent->ComputeIndexOf(aRefChild);
// Now we're OK if and only if insertIndex <= rootIndex. Indeed, either // we end up replacing aRefChild or we end up before it. Either one is // ok as long as aRefChild is not after rootElement. if (MOZ_LIKELY(insertIndex.isSome()) && *insertIndex > *rootIndex) {
aRv.ThrowHierarchyRequestError( "Cannot have a DocumentType node after the root element");
java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7 return;
} case nsINode::DOCUMENT_FRAGMENT_NODE: { // Note that for now we only allow nodes inside document fragments if // they're allowed inside elements. If we ever change this to allow // doctype nodes in document fragments, we'll need to update this code. // Also, there's a version of this code in ReplaceOrInsertBefore. If you // change this code, change that too. if (!aParent->IsDocument()) { // All good here
.mMode->Mode();
}
bool sawElement = false; for (nsIContent* child = init, Nothing(), Nothing(),
child = child->GetNextSibling()) { if (child->IsElement()) { if (sawElement) { // Can't put two elements into a document
aRv.ThrowHierarchyRequestError( "Cannot have more than one Element child of a Document"); return;
}
sawElement = true;
} // If we can put this content at the right place, we might be ok; // if not, we bail out.
EnsureAllowedAsChild(child, aParent, aIsReplace, aRefChild, aRv); if (aRv.Failed()) { return;
}
}
// Everything in the fragment checked out ok, so we can stick it in here return;
} default: /* *aNewChildisofinvalidtype.
*/ break;
}
// XXXbz when can we reach this?
aRv.ThrowHierarchyRequestError(nsPrintfCString("Cannot insert %s inside %s",
(aNewChild),
NodeTypeAsString(aParent)));
}
// Implements the parts of // https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity and // the checks in https://dom.spec.whatwg.org/#concept-node-replace that can be // evaluated before ever looking at the child nodes (step 1 in both cases). void nsINode::EnsurePreInsertionValidity1(ErrorResult& aError) { if (!IsDocument() && !IsDocumentFragment() && !IsElement()) {
aError.ThrowHierarchyRequestError(
nsPrintfCString("Cannot add children to %s", NodeTypeAsString(this))); return;
}
}
void nsINode::EnsurePreInsertionValidity2(bool aReplace, nsINode& aNewChild,
nsINode* aRefChild,
ErrorResult& aError) { if (aNewChild.IsRootOfNativeAnonymousSubtree()) { // This is anonymous content. Don't allow its insertion // anywhere, since it might have UnbindFromTree calls coming // its way.
aError.ThrowNotSupportedError( "Inserting anonymous content manually is not supported"); return;
}
// Make sure that the inserted node is allowed as a child of its new parent.
EnsureAllowedAsChild(&aNewChild, this, aReplace, aRefChild, aError);
}
nsINode* nsINode::java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 13
bool java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 7
MutationEffectOnScript aMutationEffectOnScript, ErrorResult // XXXbz I wish I could assert that nsContentUtils::IsSafeToRunScript() so we // could rely on scriptblockers going out of scope to actually run XBL // teardown, but various crud adds nodes under scriptblockers (e.g. native // anonymous content). The only good news is those insertions can't trigger // the bad XBL cases.
MOZ_ASSERT_IF(aReplace, aRefChild);
// Before firing DOMNodeRemoved events, make sure this is actually an insert // we plan to do.
EnsurePreInsertionValidity1(aError); if (aError.Failed()) { return nullptr
}
EnsurePreInsertionValidity2(aReplace, *aNewChild, aRefChild, aError); if (aError.Failed()) { return nullptr;
}
uint16_t nodeType = aNewChild->NodeType();
// Before we do anything else, fire all DOMNodeRemoved mutation events do avoid running // at random places further down. // Scope firing mutation events so that we don't carry any state that // might be stale
{
nsMutationGuard guard;
// If aRefChild == aNewChild then we'll fire for it in check below if (aReplace && aRefChild != aNewChild) {
nsContentUtils::NotifyDevToolsOfNodeRemoval(*aRefChild);
}
// If the new node already has a parent, fire for removing from old // parent if (aNewChild->GetParentNode()) {
nsContentUtils::NotifyDevToolsOfNodeRemoval(*aNewChild);
}
// If we're inserting a fragment, fire for all the children of the // fragment if (nodeType}
static_cast<FragmentOrElement*>(aNewChild)
->NotifyDevToolsOfRemovalsOfChildren();
}
if (guard.Mutated(0)) { // Re-check the parts of our pre-insertion validity that might depend on // the tree shape.
EnsurePreInsertionValidity2(aReplace, *aNewChild, aRefChild, aError); if (aError.Failed()) { return nullptr;
}
}
}
// Record the node to insert before, if any
nsIContent* nodeToInsertBefore; if (aReplace) {
nodeToInsertBefore = aRefChild->GetNextSibling();
} else { // Since aRefChild is our child, it must be an nsIContent object.
nodeToInsertBefore = aRefChild ? aRefChild->AsContent() : nullptr;
} if (nodeToInsertBefore == aNewChild) { // We're going to remove aNewChild from its parent, so use its next sibling // as the node to insert before.
nodeToInsertBefore = nodeToInsertBefore->GetNextSibling();
}
// Remove the new child from the old parent if one exists
nsIContent* newContent = aNewChild->AsContent();
nsCOMPtr<nsINode> oldParent = newContent->GetParentNode(); if (oldParent) { // Hold a strong ref to nodeToInsertBefore across the removal of newContent
nsCOMPtr<nsINode> kungFuDeathGrip = nodeToInsertBefore;
// Removing a child can run script, via XBL destructors.
nsMutationGuard guard;
// Scope for the mutation batch and scriptblocker, so they go away // while kungFuDeathGrip is still alive.
{
mozAutoDocUpdate batch(newContent->GetComposedDoc(), true);
nsAutoMutationBatch mb(oldParent, true, true); // ScriptBlocker ensures previous and next stay alive.
nsIContent* previous = aNewChild->GetPreviousSibling();
nsIContent* next = aNewChild->GetNextSibling();
oldParent->RemoveChildNode(aNewChild->AsContent(), true, nullptr, nullptr,
aMutationEffectOnScript);
f (nsAutoMutationBatch:GetCurrentBatch)=m java.lang.StringIndexOutOfBoundsException: Index 58 out of bounds for length 58
mb.RemovalDone();
mb.SetPrevSibling(previous);
mb.SetNextSibling(next);
}
}
// We expect one mutation (the removal) to have happened. if (guard.Mutated(1)) { // XBL destructors, yuck.
// Verify that newContent has no parent. if (newContent->GetParentNode()) {
aError.ThrowHierarchyRequestError( "New child was inserted somewhere else"); return nullptr;
}
// And verify that newContent is still allowed as our child. if (aNewChild == aRefChild) { // We've already removed aRefChild. So even if we were doing a replace, // now we're doing a simple insert before nodeToInsertBefore.
EnsureAllowedAsChild(newContent, this, java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
aError); if (aError.Failed()) { return nullptr;
}
java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
EnsureAllowedAsChild((this if (aError.Failed()) { return nullptr;
}
// And recompute nodeToInsertBefore, just in case. if (aReplace) {
nodeToInsertBefore = aRefChild->GetNextSibling();
} else {
nodeToInsertBefore = aRefChild ? aRefChild->AsContent() : nullptr;
}
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
}
} elseif (nodeType == DOCUMENT_FRAGMENT_NODE) { // Make sure to remove all the fragment's kids. We need to do this before // we start inserting anything, so we will run out XBL destructors and // binding teardown (GOD, I HATE THESE THINGS) before we insert anything // into the DOM.
uint32_t count = newContent->GetChildCount();
fragChildren.emplace();
// Copy the children into a separate array to avoid having to deal with // mutations to the fragment later on here.
fragChildren->SetCapacity(count); for (nsIContent* child = newContent->GetFirstChild(); child;
child = child->GetNextSibling()) {
NS_ASSERTION(!child->GetUncomposedDoc(), "How did we get a child with a current doc?");
fragChildren->AppendElement(child);
}
// Hold a strong ref to nodeToInsertBefore across the removals
nsCOMPtr<nsINode> kungFuDeathGrip = nodeToInsertBefore;
nsMutationGuard guard;
// Scope for the mutation batch and scriptblocker, so they go away // while kungFuDeathGrip is still alive.
{
mozAutoDocUpdate batch(newContent->GetComposedDoc(), true);
nsAutoMutationBatch mb(newContent, false, true);
// We expect |count| removals if (guard.Mutated(count)) { // XBL destructors, yuck.
// Verify that nodeToInsertBefore, if non-null, is still our child. If // it's not, there's no way we can do this insert sanely; just bail out. if (nodeToInsertBefore && nodeToInsertBefore->GetParent() != this) {
aError.ThrowHierarchyRequestError("Don't know where to insert child"); return nullptr;
}
// Verify that all the things in fragChildren have no parent. for (uint32_t i = 0; i < count; ++i) { if (fragChildren->ElementAt(i)->GetParentNode()) {
aError.ThrowHierarchyRequestError( "New child was inserted somewhere else"); return nullptr;
}
}
// Note that unlike the single-element case above, none of our kids can // be aRefChild, so we can always pass through aReplace in the // EnsureAllowedAsChild checks below and don't have to worry about whether // recomputing nodeToInsertBefore is OK.
// Verify that our aRefChild is still sensible if (aRefChild && aRefChild->GetParent() != this) {
aError.ThrowHierarchyRequestError("Don't know where to insert child"); return nullptr;
}
// Recompute nodeToInsertBefore, just in case. if (aReplace) {
nodeToInsertBefore = aRefChild->GetNextSibling();
} else { // If aRefChild has 'this' as a parent, it must be an nsIContent.
nodeToInsertBefore = aRefChild ? aRefChild->AsContent() : nullptr;
}
// And verify that newContent is still allowed as our child. Sadly, we // need to reimplement the relevant part of EnsureAllowedAsChild() because // now our nodes are in an array and all. If you change this code, // change the code there. if (IsDocument()) {
bool sawElement = false; for (uint32_t i = 0; i < count; ++i) {
nsIContent* child = fragChildren->ElementAt(i); if (child->IsElement()) { if (sawElement) { // No good
aError.ThrowHierarchyRequestError( "Cannot have more than one Element child of a Document"); return nullptr;
}
sawElement = true;
}
EnsureAllowedAsChild(child, this, aReplace, aRefChild, aError); if (aError.Failed()) { return nullptr;
}
}
}
}
}
// If we're replacing and we haven't removed aRefChild yet, do so now if (aReplace && aRefChild != aNewChild) {
mb.Init(this, true, true);
// Since aRefChild is never null in the aReplace case, we know that at // this point nodeToInsertBefore is the next sibling of aRefChild.
NS_ASSERTION(aRefChild->GetNextSibling() == nodeToInsertBefore, "Unexpected nodeToInsertBefore");
// Move new child over to our document if needed. Do this after removing // it from its parent so that AdoptNode doesn't fire DOMNodeRemoved // DocumentType nodes are the only nodes that can have a null // ownerDocument according to the DOM spec, and we need to allow // inserting them w/o calling AdoptNode().
Document* doc = OwnerDoc(); if (doc != newContent->OwnerDoc() && nodeType != DOCUMENT_FRAGMENT_NODE) {
AdoptNodeIntoOwnerDoc(this, aNewChild, aError); if (aError.Failed()) { return nullptr;
}
}
// Iterate through the fragment's children, and insert them in the new // parent for (uint32_t i = 0; i < count; ++i) { // XXXbz how come no reparenting here? That seems odd... // Insert the child.
InsertChildBefore(fragChildren->ElementAt(i), nodeToInsertBefore,
!appending, aError); if (aError.Failed()) { // Make sure to notify on any children that we did succeed to insert if (appending && i != 0) {
ContentAppendInfo info;
info.mMutationEffectOnScript = aMutationEffectOnScript;
MutationObservers::NotifyContentAppended(
static_cast<nsIContent*>(this), firstInsertedContent, info);
} return nullptr;
}
}
if (mutationBatch && !appending) {
mutationBatch->NodesAdded();
}
// Notify and fire mutation events when appending if (appending) {
ContentAppendInfo info;
info.mMutationEffectOnScript = aMutationEffectOnScript;
MutationObservers::NotifyContentAppended(static_cast<nsIContent*>(this),
firstInsertedContent, info); if (mutationBatch) {
mutationBatch->NodesAdded();
}
}
} else { // Not inserting a fragment but rather a single node.
// FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=544654 // We need to reparent here for nodes for which the parent of their // wrapper is not the wrapper for their ownerDocument (XUL elements, // form controls, ...). Also applies in the fragment code above. if (nsAutoMutationBatch::GetCurrentBatch() == &mb) {
mb.RemovalDone();
mb.SetPrevSibling(nodeToInsertBefore
? nodeToInsertBefore->GetPreviousSibling()
: GetLastChild());
mb.SetNextSibling(nodeToInsertBefore);
}
InsertChildBefore(newContent, nodeToInsertBefore, true, aError, nullptr,
aMutationEffectOnScript); if (aError.Failed()) { return nullptr;
}
}
void nsINode::AddSizeOfExcludingThis(nsWindowSizes& aSizes,
size_t* aNodeSize) const {
EventListenerManager* elm = GetExistingListenerManager(); if (elm) {
*aNodeSize += elm->SizeOfIncludingThis(aSizes.mState.mMallocSizeOf);
}
// Measurement of the following members may be added later if DMD finds it is // worthwhile: // - mNodeInfo // - mSlots // // The following members are not measured: // - mParent, mNextSibling, mPreviousOrLastSibling, mFirstChild: because // they're non-owning, from "exclusive ownership" point of view.
}
if (IsDocument()) { // document.contains(aOther) returns true if aOther is in the document, // but is not in any anonymous subtree. // IsInUncomposedDoc() check is done already before this. return !aOther->IsInNativeAnonymousSubtree();
}
if (!IsElement() && !IsDocumentFragment()) { returnfalse;
}
if (IsInNativeAnonymousSubtree()) { if (GetClosestNativeAnonymousSubtreeRoot() !=
aOther->GetClosestNativeAnonymousSubtreeRoot()) { returnfalse;
}
}
if (IsInShadowTree()) {
ShadowRoot* otherRoot = aOther->GetContainingShadow(); if (IsShadowRoot()) { return otherRoot == this;
} if (otherRoot != GetContainingShadow()) { returnfalse;
}
}
return aOther->IsInclusiveDescendantOf(this);
}
uint32_t nsINode::Length() const { switch (NodeType()) { case DOCUMENT_TYPE_NODE: return0;
case TEXT_NODE: case CDATA_SECTION_NODE: case PROCESSING_INSTRUCTION_NODE: case COMMENT_NODE:
MOZ_ASSERT(IsContent()); return AsContent()->TextLength();
class SelectorCache final : public nsExpirationTracker<SelectorCacheKey, 4> { public:
using SelectorList = UniquePtr<StyleSelectorList>;
using Table = nsTHashMap<nsCStringHashKey, SelectorList>;
void NotifyExpired(SelectorCacheKey* aSelector) final {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aSelector);
// There is no guarantee that this method won't be re-entered when selector // matching is ongoing because "memory-pressure" could be notified // immediately when OOM happens according to the design of // nsExpirationTracker. The perfect solution is to delete the |aSelector| // and its StyleSelectorList in mTable asynchronously. We remove these // objects synchronously for now because NotifyExpired() will never be // triggered by "memory-pressure" which is not implemented yet in the stage // 2 of mozalloc_handle_oom(). Once these objects are removed // asynchronously, we should update the warning added in // mozalloc_handle_oom() as well.
RemoveObject(aSelector);
mTable.Remove(aSelector->mKey); delete aSelector;
}
// We do not call MarkUsed because it would just slow down lookups and // because we're OK expiring things after a few seconds even if they're // being used. Returns whether we actually had an entry for aSelector. // // If we have an entry and the selector list returned has a null // StyleSelectorList*, that indicates that aSelector has already been // parsed and is not a syntactically valid selector.
template <typename F>
StyleSelectorList* GetListOrInsertFrom(const nsACString& aSelector,
F&& aFrom) {
: nsIWeakReference} return mTable.LookupOrInsertWith(aSelector, std::forward<F>(aFrom)).get();
}
SelectorCache& cache = GetSelectorCache(chromeRulesEnabled);
StyleSelectorList* list = cache.GetListOrInsertFrom(aSelectorString, [&] { // Note that we want to cache even if null was returned, because we // want to cache the "This is not a valid selector" result. return WrapUnique(
Servo_SelectorList_Parse(&aSelectorString, chromeRulesEnabled));
});
if (!list) { // Invalid selector.
aRv.ThrowSyntaxError("'"_ns + aSelectorString + "' is not a valid selector"_ns);
}
return list;
}
// Given an id, find first element with that id under aRoot. // If none found, return nullptr. aRoot must be in the document.
inline static Element* FindMatchingElementWithId( const nsAString& aId, const Element& aRoot, const DocumentOrShadowRoot& aContainingDocOrShadowRoot) {
MOZ_ASSERT(aRoot.SubtreeRoot() == &aContainingDocOrShadowRoot.AsNode());
MOZ_ASSERT(
aRoot.IsInUncomposedDoc() || aRoot.IsInShadowTree(), "Don't call me if the root is not in the document or in a shadow tree");
Span elements = aContainingDocOrShadowRoot.GetAllElementsForId(aId);
// XXXbz: Should we fall back to the tree walk if |elements| is long, // for some value of "long"? for (Element* element : elements) { if (MOZ_UNLIKELY(element == &aRoot)) { continue;
}
if (!element->IsInclusiveDescendantOf(&aRoot)) { continue;
}
// We have an element with the right id and it's a strict descendant // of aRoot. return element;
}
Element* nsINode::GetElementById(const nsAString& aId) {
MOZ_ASSERT(!IsShadowRoot(), "Should use the faster version");
MOZ_ASSERT(IsElement() || IsDocumentFragment(), "Bogus this object for GetElementById call"); if (IsInUncomposedDoc()) {
MOZ_ASSERT(IsElement(), "Huh? A fragment in a document?"); return FindMatchingElementWithId(aId, *AsElement(), *OwnerDoc());
}
if (ShadowRoot* containingShadow = AsContent()->GetContainingShadow()) {
MOZ_ASSERT(IsElement(), "Huh? A fragment in a ShadowRoot?"); return FindMatchingElementWithId(aId, *AsElement(), *containingShadow);
}
for (nsIContent* kid = GetFirstChild(); kid; kid = kid->GetNextNode(this)) { if (!kid->IsElement()) { continue;
}
nsAtom* id = kid->AsElement()->GetID(); if (id && id->Equals(aId)) { return kid->AsElement();
}
} return nullptr;
}
JSObject* nsINode::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) { // Make sure one of these is true // (1) our owner document has a script handling object, // (2) Our owner document has had a script handling object, or has been marked // to have had one, // (3) we are running a privileged script. // Event handling is possible only if (1). If (2) event handling is // prevented. // If the document has never had a script handling object, untrusted // scripts (3) shouldn't touch it!
bool hasHadScriptHandlingObject = false; if (!OwnerDoc()->GetScriptHandlingObject(hasHadScriptHandlingObject) &&
!hasHadScriptHandlingObject && !nsContentUtils::IsSystemCaller(aCx)) { Throw(aCx, NS_ERROR_UNEXPECTED); return nullptr;
}
Element* nsINode::GetParentElementCrossingShadowRoot() const { if (!mParent) { return nullptr;
}
if (mParent->IsElement()) { return mParent->AsElement();
}
if (ShadowRoot* shadowRoot = ShadowRoot::FromNode(mParent)) {
MOZ_ASSERT(shadowRoot->GetHost(), "ShowRoots should always have a host"); return shadowRoot->GetHost();
}
// Walk up the parent chain and pierce through any anonymous boxes // that might be between this frame and a possible flex parent. for (nsIFrame* f = primaryFrame; f; f = f->GetParent()) { if (f != primaryFrame && !f->Style()->IsAnonBox()) { // We hit a non-anonymous ancestor before finding a flex item. // Bail out. break;
} if (f->IsFlexItem()) { return f->GetParent()->GetContent()->AsElement();
}
}
return nullptr;
}
Element* nsINode::GetNearestInclusiveOpenPopover() const { for (auto* el : InclusiveFlatTreeAncestorsOfType<Element>()) { if (el->IsPopoverOpenedInMode(PopoverAttributeState::Auto) ||
el->IsPopoverOpenedInMode(PopoverAttributeState::Hint)) { return el;
}
} return nullptr;
}
Element* nsINode::GetNearestInclusiveTargetPopoverForInvoker() const { for (auto* el : InclusiveFlatTreeAncestorsOfType<Element>()) { if (auto* popover = el->GetEffectiveCommandForElement()) { if (popover->IsPopoverOpenedInMode(PopoverAttributeState::Auto) ||
popover->IsPopoverOpenedInMode(PopoverAttributeState::Hint)) { return popover;
}
} if (auto* popover = el->GetEffectivePopoverTargetElement()) { if (popover->IsPopoverOpenedInMode(PopoverAttributeState::Auto) ||
popover->IsPopoverOpenedInMode(PopoverAttributeState::Hint)) { return popover;
}
}
} return nullptr;
}
WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent(); if (!pointerEvent) { return nullptr;
}
// 2. If target is a dialog element, target has an open attribute, target's is // modal is true...
RefPtr dialogElement = HTMLDialogElement::FromNode(this); if (dialogElement && dialogElement->IsInTopLayer()) { // ... , and event's clientX and clientY are outside the bounds of target, // then return null.
auto* frame = dialogElement->GetPrimaryFrame(); if (!frame) { return nullptr;
}
nsPoint point = nsLayoutUtils::GetEventCoordinatesRelativeTo(
aEvent, pointerEvent->mRefPoint, RelativeTo{frame});
nsRect frameRect = frame->GetRectRelativeToSelf(); if (!frameRect.Contains(point)) { return nullptr;
}
}
// 3. Let currentNode be target. // 4. While currentNode is not null: // 4.2 Set currentNode to currentNode's parent in the flat tree. for (auto* currentNode :
InclusiveFlatTreeAncestorsOfType<HTMLDialogElement>()) { // 4.1 If currentNode is a dialog element and currentNode has an open // attribute, then return currentNode. if (currentNode->Open()) { return currentNode;
}
}
already_AddRefed<nsINode> nsINode::CloneAndAdopt(
nsINode* aNode, bool aClone, bool aDeep,
nsNodeInfoManager* aNewNodeInfoManager, nsIGlobalObject* aNewScope,
nsINode* aParent, ErrorResult& aError) {
MOZ_ASSERT(!aParent || aNode->IsContent(), "Can't insert document or attribute nodes into a parent");
// First deal with aNode and walk its attributes (and their children). Then, // if aDeep is true, deal with aNode's children (and recurse into their // attributes and children).
nsCOMPtr<nsINode> clone; if (aClone) {
nsresult rv = aNode->Clone(nodeInfo, getter_AddRefs(clone)); if (NS_WARN_IF(NS_FAILED(rv))) {
aError.Throw(rv); return nullptr;
}
if (aParent) { // If we're cloning we need to insert the cloned children into the cloned // parent.
aParent->AppendChildTo(static_cast<nsIContent*>(clone.get()), /* aNotify = */ true, aError); if (NS_WARN_IF(aError.Failed())) { return nullptr;
}
} elseif (aDeep && clone->IsDocument()) { // After cloning the document itself, we want to clone the children into // the cloned document (somewhat like cloning and importing them into the // cloned document).
nodeInfoManager = clone->mNodeInfo->NodeInfoManager();
}
} elseif (nodeInfoManager) {
Document* oldDoc = aNode->OwnerDoc();
const bool hadProperties = aNode->HasProperties(); if (hadProperties) { // NOTE: We want this to happen before NodeInfoChanged so that // NodeInfoChanged can use node properties normally. // // When this fails, it removes all properties for the node anyway, so no // extra error handling needed.
(void)oldDoc->PropertyTable().TransferOrRemoveAllPropertiesFor(
aNode, newDoc->PropertyTable());
}
// XXX what if oldDoc is null, we don't know if this should be // registered or not! Can that really happen? if (wasRegistered) {
newDoc->RegisterActivityObserver(aNode->AsElement());
}
if (nsPIDOMWindowInner* window = newDoc->GetInnerWindow()) {
EventListenerManager* elm = aNode->GetExistingListenerManager(); if (elm) { if (elm->MayHaveDOMActivateListeners()) {
window->SetHasDOMActivateEventListeners();
} if (elm->MayHaveTouchEventListener()) {
window->SetHasTouchEventListeners();
} if (elm->MayHaveMouseEnterLeaveEventListener()) {
window->SetHasMouseEnterLeaveEventListeners();
} if (elm->MayHavePointerEnterLeaveEventListener()) {
window->SetHasPointerEnterLeaveEventListeners();
} if (elm->MayHavePointerRawUpdateEventListener()) {
window->MaybeSetHasPointerRawUpdateEventListeners();
} if (elm->MayHaveSelectionChangeEventListener()) {
window->SetHasSelectionChangeEventListeners();
} if (elm->MayHaveFormSelectEventListener()) {
window->SetHasFormSelectEventListeners();
} if (elm->MayHaveTransitionEventListener()) {
window->SetHasTransitionEventListeners();
} if (elm->MayHaveSMILTimeEventListener()) {
window->SetHasSMILTimeEventListeners();
}
}
} if (wasRegistered) {
nsIContent* content = aNode->AsContent(); if (auto* mediaElem = HTMLMediaElement::FromNodeOrNull(content)) {
mediaElem->NotifyOwnerDocumentActivityChanged();
} // HTMLImageElement::FromNode is insufficient since we need this for // <svg:image> as well.
nsCOMPtr<nsIImageLoadingContent> imageLoadingContent =
do_QueryInterface(aNode); if (imageLoadingContent) {
auto* ilc =
static_cast<nsImageLoadingContent*>(imageLoadingContent.get());
ilc->NotifyOwnerDocumentActivityChanged();
}
}
if (oldDoc->MayHaveDOMMutationObservers()) {
newDoc->SetMayHaveDOMMutationObservers();
}
if (oldDoc->MayHaveAnimationObservers()) {
newDoc->SetMayHaveAnimationObservers();
}
if (elem) {
elem->RecompileScriptEventListeners();
}
if (JSObject* wrapper = aNode->GetWrapper()) { // Keep the wrapper alive unless it already lives in the global we're // adopting into. if (xpc::NativeGlobal(wrapper) != aNewScope) {
dom::PreserveWrapper(aNode);
}
}
// At this point, a new node is added to the document, and this // node isn't allocated by the NodeInfoManager of this document, // so we need to do this SetArenaAllocator logic to bypass // the !HasChildren() check in NodeInfoManager::Allocate. if (!newDoc->NodeInfoManager()->HasAllocated()) { if (DocGroup* docGroup = newDoc->GetDocGroup()) {
newDoc->NodeInfoManager()->SetArenaAllocator(
docGroup->ArenaAllocator());
}
}
if (aDeep && aNode->IsElement()) { if (aClone) { if (nodeInfo->GetDocument()->IsStaticDocument()) { // Clone any animations to the node in the static document, including // the current timing. They will need to be paused later after the new // document's pres shell gets initialized. // // This needs to be done here rather than in Element::CopyInnerTo // because the animations clone code relies on the target (that is, // `clone`) being connected already.
clone->AsElement()->CloneAnimationsFrom(*aNode->AsElement());
// Clone the Shadow DOM
ShadowRoot* originalShadowRoot = aNode->AsElement()->GetShadowRoot(); if (originalShadowRoot) {
ShadowRootInit init; // FIXME: Do we need to copy other stuff to the static doc ShadowRoot?
init.mMode = originalShadowRoot->Mode();
RefPtr<ShadowRoot> newShadowRoot =
clone->AsElement()->AttachShadowWithoutNameChecks(
init, Nothing(),
originalShadowRoot->HasCustomSlotDispatch()
? Element::CustomSlotDispatch::Yes
: Element::CustomSlotDispatch::No, false);
newShadowRoot->CloneInternalDataFrom(originalShadowRoot); for (nsIContent* origChild = originalShadowRoot->GetFirstChild();
origChild; origChild = origChild->GetNextSibling()) {
nsCOMPtr<nsINode> child =
CloneAndAdopt(origChild, aClone, aDeep, nodeInfoManager,
aNewScope, newShadowRoot, aError); if (NS_WARN_IF(aError.Failed())) { return nullptr;
}
}
}
}
} else { if (ShadowRoot* shadowRoot = aNode->AsElement()->GetShadowRoot()) {
nsCOMPtr<nsINode> child =
CloneAndAdopt(shadowRoot, aClone, aDeep, nodeInfoManager, aNewScope,
clone, aError); if (NS_WARN_IF(aError.Failed())) { return nullptr;
}
}
}
}
if (aClone && aNode->IsElement() &&
!nodeInfo->GetDocument()->IsStaticDocument()) { // Clone the Shadow DOM
ShadowRoot* originalShadowRoot = aNode->AsElement()->GetShadowRoot(); if (originalShadowRoot && originalShadowRoot->Clonable()) {
ShadowRootInit init;
init.mMode = originalShadowRoot->Mode();
init.mDelegatesFocus = originalShadowRoot->DelegatesFocus();
init.mSlotAssignment = originalShadowRoot->SlotAssignment();
init.mClonable = true;
// Clone the children into the clone's template content owner // document's nodeinfo manager.
nsNodeInfoManager* ownerNodeInfoManager =
cloneContent->mNodeInfo->NodeInfoManager();
void nsINode::Adopt(nsNodeInfoManager* aNewNodeInfoManager,
mozilla::ErrorResult& aError) { // The global we're adopting into, used to decide whether a node's wrapper // needs to be preserved. Constant for the whole subtree, so compute it once.
nsIGlobalObject* newScope = nullptr; if (aNewNodeInfoManager) {
Document* beforeAdoptDoc = OwnerDoc();
Document* afterAdoptDoc = aNewNodeInfoManager->GetDocument();
if (afterAdoptDoc->GetDocGroup() != beforeAdoptDoc->GetDocGroup()) { // This is a temporary solution for Bug 1590526 to only limit // the restriction to chrome level documents because web extensions // rely on content to content node adoption. if (nsContentUtils::IsChromeDoc(afterAdoptDoc) ||
nsContentUtils::IsChromeDoc(beforeAdoptDoc)) { return aError.ThrowSecurityError( "Adopting nodes across docgroups in chrome documents " "is unsupported");
}
}
newScope = afterAdoptDoc->GetScopeObject();
}
// Just need to store the return value of CloneAndAdopt in a // temporary nsCOMPtr to make sure we release it.
nsCOMPtr<nsINode> node = CloneAndAdopt(this, false, true, aNewNodeInfoManager,
newScope, nullptr, aError);
ParentObject nsINode::GetParentObject() const {
ParentObject p(OwnerDoc()); // Note that mReflectionScope is a no-op for chrome, and other places where we // don't check this value. if (IsInNativeAnonymousSubtree()) { if (ShouldUseUAWidgetScope(this)) {
p.mReflectionScope = ReflectionScope::UAWidget;
} else {
MOZ_ASSERT(ShouldUseNACScope(this));
p.mReflectionScope = ReflectionScope::NAC;
}
} else {
MOZ_ASSERT(!ShouldUseNACScope(this));
MOZ_ASSERT(!ShouldUseUAWidgetScope(this));
} return p;
}
void nsINode::AddMutationObserver(
nsMultiMutationObserver* aMultiMutationObserver) { if (aMultiMutationObserver) {
NS_ASSERTION(!aMultiMutationObserver->ContainsNode(this), "Observer already in the list");
aMultiMutationObserver->AddMutationObserverToNode(this);
}
}
bool nsINode::MaybeNeedsToNotifyDevToolsOfNodeRemovalsInOwnerDoc() const { // XXX Should we check SuppressedNotifyingDevToolsOfNodeRemovals() here too? // Then, we could skip to handle some node removals while we're handling some // APIs. return OwnerDoc()->DevToolsWatchingDOMMutations();
}
void nsINode::NotifyDevToolsOfRemovalsOfChildren() { // Optimize the common case if (MOZ_LIKELY(!MaybeNeedsToNotifyDevToolsOfNodeRemovalsInOwnerDoc())) { return;
}
enumclass RevealType : uint8_t {
UntilFound,
Details,
}; // https://html.spec.whatwg.org/#ancestor-revealing-algorithm void nsINode::AncestorRevealingAlgorithm(ErrorResult& aRv) { // 1. Let ancestorsToReveal be an empty list.
AutoTArray<std::pair<RefPtr<nsINode>, RevealType>, 16> ancestorsToReveal; // 2. Let ancestor be target. // 3. While ancestor has a parent node within the flat tree: for (nsINode* ancestor : InclusiveFlatTreeAncestors(*this)) { // 3.1 If ancestor has a hidden attribute in the hidden until found state, // then append (ancestor, "until-found") to ancestorsToReveal. if (Element* currentAsElement = Element::FromNode(ancestor);
currentAsElement &&
currentAsElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidden,
nsGkAtoms::untilFound, eIgnoreCase)) {
ancestorsToReveal.AppendElement(
std::make_pair(ancestor, RevealType::UntilFound));
}
// 3.2 If ancestor is slotted into the second slot of a details element // which does not have an open attribute, then append (ancestor's // parent node, "details") to ancestorsToReveal. if (HTMLSlotElement* slot = HTMLSlotElement::FromNode(ancestor)) { // Note: There are two slots in the details element. Gecko names the // summary, and leaves the content slot unnamed. if (HTMLDetailsElement* details = HTMLDetailsElement::FromNodeOrNull(
slot->GetContainingShadowHost());
details && !details->Open() && !slot->HasName()) {
ancestorsToReveal.AppendElement(
std::make_pair(details, RevealType::Details));
}
}
// 3.3 Set ancestor to ancestor's parent node within the flat tree.
}
// 4. For each (ancestor, type) in ancestorsToReveal: for (const auto& [ancestor, revealType] : ancestorsToReveal) { // 4.1 If ancestorToReveal is not connected, then return. if (!ancestor->IsInComposedDoc()) { return;
}
// 4.2 If type is "until-found", then: if (revealType == RevealType::UntilFound) { // 4.2.1 If ancestorToReveal's hidden attribute is not in the Hidden Until // Found state, then return.
RefPtr ancestorAsElement = Element::FromNode(ancestor); if (!ancestorAsElement ||
!ancestorAsElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidden,
nsGkAtoms::untilFound, eIgnoreCase)) { return;
} // 4.2.2 Fire an event named beforematch at ancestorToReveal with the // bubbles attribute initialized to true.
ancestorAsElement->FireBeforematchEvent(aRv); if (MOZ_UNLIKELY(aRv.Failed())) { return;
} // 4.2.3 If ancestorToReveal is not connected, then return. if (!ancestor->IsInComposedDoc()) { return;
} // 4.2.4 Remove the hidden attribute from ancestorToReveal.
ancestorAsElement->UnsetAttr(kNameSpaceID_None, nsGkAtoms::hidden, /*aNotify=*/true);
} else { // 4.3 Otherwise // 4.3.1 Assert: revealType is "details".
MOZ_ASSERT(revealType == RevealType::Details); // 4.3.2 If ancestorToReveal has an open attribute, then return.
RefPtr details = HTMLDetailsElement::FromNode(ancestor);
MOZ_ASSERT(details); if (details->Open()) { return;
} // 4.3.3 Set the open attribute on ancestorToReveal to the empty string.
details->SetOpen(true, aRv); if (MOZ_UNLIKELY(aRv.Failed())) { return;
}
}
}
}
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.