Bug 1384661 - Part 3: Invalidate cached child array when list of children changes. r=smaug

This commit is contained in:
btian 2017-08-18 11:56:38 +08:00
Родитель 2683456670
Коммит 0610efa5fc
1 изменённых файлов: 28 добавлений и 6 удалений

Просмотреть файл

@ -409,7 +409,11 @@ nsINode::ChildNodes()
{
nsSlots* slots = Slots();
if (!slots->mChildNodes) {
slots->mChildNodes = new nsAttrChildContentList(this);
// Check |!IsElement()| first to catch the common case
// without virtual call |IsNodeOfType|
slots->mChildNodes = !IsElement() && IsNodeOfType(nsINode::eATTRIBUTE) ?
new nsAttrChildContentList(this) :
new nsParentNodeChildContentList(this);
}
return slots->mChildNodes;
@ -1562,8 +1566,9 @@ nsresult
nsINode::doInsertChildAt(nsIContent* aKid, uint32_t aIndex,
bool aNotify, nsAttrAndChildArray& aChildArray)
{
NS_PRECONDITION(!aKid->GetParentNode(),
"Inserting node that already has parent");
MOZ_ASSERT(!aKid->GetParentNode(), "Inserting node that already has parent");
MOZ_ASSERT(!IsNodeOfType(nsINode::eATTRIBUTE));
nsresult rv;
// The id-handling code, and in the future possibly other code, need to
@ -1592,6 +1597,14 @@ nsINode::doInsertChildAt(nsIContent* aKid, uint32_t aIndex,
mFirstChild = aKid;
}
// Invalidate cached array of child nodes
nsSlots* slots = GetExistingSlots();
if (slots && slots->mChildNodes) {
auto childNodes =
static_cast<nsParentNodeChildContentList*>(slots->mChildNodes.get());
childNodes->InvalidateCache();
}
nsIContent* parent =
IsNodeOfType(eDOCUMENT) ? nullptr : static_cast<nsIContent*>(this);
@ -1897,9 +1910,10 @@ nsINode::doRemoveChildAt(uint32_t aIndex, bool aNotify,
// nsIDocument::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 nsDocument::RemoveChildAt().
NS_PRECONDITION(aKid && aKid->GetParentNode() == this &&
aKid == GetChildAt(aIndex) &&
IndexOf(aKid) == (int32_t)aIndex, "Bogus aKid");
MOZ_ASSERT(aKid && aKid->GetParentNode() == this &&
aKid == GetChildAt(aIndex) &&
IndexOf(aKid) == (int32_t)aIndex, "Bogus aKid");
MOZ_ASSERT(!IsNodeOfType(nsINode::eATTRIBUTE));
nsMutationGuard::DidMutate();
mozAutoDocUpdate updateBatch(GetComposedDoc(), UPDATE_CONTENT_MODEL, aNotify);
@ -1912,6 +1926,14 @@ nsINode::doRemoveChildAt(uint32_t aIndex, bool aNotify,
aChildArray.RemoveChildAt(aIndex);
// Invalidate cached array of child nodes
nsSlots* slots = GetExistingSlots();
if (slots && slots->mChildNodes) {
auto childNodes =
static_cast<nsParentNodeChildContentList*>(slots->mChildNodes.get());
childNodes->InvalidateCache();
}
if (aNotify) {
nsNodeUtils::ContentRemoved(this, aKid, aIndex, previousSibling);
}