Attachment #8917291: Patch 1 (v2): Invalidate cached child array when nsAttrAndChildArray::TakeChildAt/RemoveChildAt is called for bug #1406395

View | Details | Raw Unified | Return to bug 1406395
Collapse All | Expand All

(-)a/dom/base/FragmentOrElement.cpp (+2 lines)
Line     Link Here 
 Lines 1436-1441   public: Link Here 
1436
    FragmentOrElement* container = static_cast<FragmentOrElement*>(aNode);
1436
    FragmentOrElement* container = static_cast<FragmentOrElement*>(aNode);
1437
    uint32_t childCount = container->mAttrsAndChildren.ChildCount();
1437
    uint32_t childCount = container->mAttrsAndChildren.ChildCount();
1438
    if (childCount) {
1438
    if (childCount) {
1439
      container->InvalidateChildNodes();
1439
      while (childCount-- > 0) {
1440
      while (childCount-- > 0) {
1440
        // Hold a strong ref to the node when we remove it, because we may be
1441
        // Hold a strong ref to the node when we remove it, because we may be
1441
        // the last reference to it.  We need to call TakeChildAt() and
1442
        // the last reference to it.  We need to call TakeChildAt() and
 Lines 1556-1561   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Fr Link Here 
1556
    if (childCount) {
1557
    if (childCount) {
1557
      // Don't allow script to run while we're unbinding everything.
1558
      // Don't allow script to run while we're unbinding everything.
1558
      nsAutoScriptBlocker scriptBlocker;
1559
      nsAutoScriptBlocker scriptBlocker;
1560
      tmp->InvalidateChildNodes();
1559
      while (childCount-- > 0) {
1561
      while (childCount-- > 0) {
1560
        // Hold a strong ref to the node when we remove it, because we may be
1562
        // Hold a strong ref to the node when we remove it, because we may be
1561
        // the last reference to it.  We need to call TakeChildAt() and
1563
        // the last reference to it.  We need to call TakeChildAt() and
(-)a/dom/base/nsDocument.cpp (+3 lines)
Line     Link Here 
 Lines 1808-1813   nsDocument::~nsDocument() Link Here 
1808
1808
1809
  nsAutoScriptBlocker scriptBlocker;
1809
  nsAutoScriptBlocker scriptBlocker;
1810
1810
1811
  InvalidateChildNodes();
1811
  for (uint32_t indx = mChildren.ChildCount(); indx-- != 0; ) {
1812
  for (uint32_t indx = mChildren.ChildCount(); indx-- != 0; ) {
1812
    mChildren.ChildAt(indx)->UnbindFromTree();
1813
    mChildren.ChildAt(indx)->UnbindFromTree();
1813
    mChildren.RemoveChildAt(indx);
1814
    mChildren.RemoveChildAt(indx);
 Lines 2106-2111   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns Link Here 
2106
  // Unlink the mChildren nsAttrAndChildArray.
2107
  // Unlink the mChildren nsAttrAndChildArray.
2107
  uint32_t childCount = tmp->mChildren.ChildCount();
2108
  uint32_t childCount = tmp->mChildren.ChildCount();
2108
  if (childCount) {
2109
  if (childCount) {
2110
    tmp->InvalidateChildNodes();
2109
    while (childCount-- > 0) {
2111
    while (childCount-- > 0) {
2110
      // Hold a strong ref to the node when we remove it, because we may be
2112
      // Hold a strong ref to the node when we remove it, because we may be
2111
      // the last reference to it.  We need to call TakeChildAt() and
2113
      // the last reference to it.  We need to call TakeChildAt() and
 Lines 2362-2367   nsDocument::ResetToURI(nsIURI *aURI, nsI Link Here 
2362
  uint32_t count = mChildren.ChildCount();
2364
  uint32_t count = mChildren.ChildCount();
2363
  { // Scope for update
2365
  { // Scope for update
2364
    MOZ_AUTO_DOC_UPDATE(this, UPDATE_CONTENT_MODEL, true);
2366
    MOZ_AUTO_DOC_UPDATE(this, UPDATE_CONTENT_MODEL, true);
2367
    InvalidateChildNodes();
2365
    for (int32_t i = int32_t(count) - 1; i >= 0; i--) {
2368
    for (int32_t i = int32_t(count) - 1; i >= 0; i--) {
2366
      nsCOMPtr<nsIContent> content = mChildren.ChildAt(i);
2369
      nsCOMPtr<nsIContent> content = mChildren.ChildAt(i);
2367
2370
(-)a/dom/base/nsINode.cpp (-12 / +17 lines)
Line     Link Here 
 Lines 420-425   nsINode::ChildNodes() Link Here 
420
}
420
}
421
421
422
void
422
void
423
nsINode::InvalidateChildNodes()
424
{
425
  MOZ_ASSERT(IsElement() || !IsNodeOfType(nsINode::eATTRIBUTE));
426
427
  nsSlots* slots = GetExistingSlots();
428
  if (!slots || !slots->mChildNodes) {
429
    return;
430
  }
431
432
  auto childNodes =
433
    static_cast<nsParentNodeChildContentList*>(slots->mChildNodes.get());
434
  childNodes->InvalidateCache();
435
}
436
437
void
423
nsINode::GetTextContentInternal(nsAString& aTextContent, OOMReporter& aError)
438
nsINode::GetTextContentInternal(nsAString& aTextContent, OOMReporter& aError)
424
{
439
{
425
  SetDOMStringToNull(aTextContent);
440
  SetDOMStringToNull(aTextContent);
 Lines 1602-1613   nsINode::doInsertChildAt(nsIContent* aKi Link Here 
1602
  }
1617
  }
1603
1618
1604
  // Invalidate cached array of child nodes
1619
  // Invalidate cached array of child nodes
1605
  nsSlots* slots = GetExistingSlots();
1620
  InvalidateChildNodes();
1606
  if (slots && slots->mChildNodes) {
1607
    auto childNodes =
1608
      static_cast<nsParentNodeChildContentList*>(slots->mChildNodes.get());
1609
    childNodes->InvalidateCache();
1610
  }
1611
1621
1612
  nsIContent* parent =
1622
  nsIContent* parent =
1613
    IsNodeOfType(eDOCUMENT) ? nullptr : static_cast<nsIContent*>(this);
1623
    IsNodeOfType(eDOCUMENT) ? nullptr : static_cast<nsIContent*>(this);
 Lines 1931-1942   nsINode::doRemoveChildAt(uint32_t aIndex Link Here 
1931
  aChildArray.RemoveChildAt(aIndex);
1941
  aChildArray.RemoveChildAt(aIndex);
1932
1942
1933
  // Invalidate cached array of child nodes
1943
  // Invalidate cached array of child nodes
1934
  nsSlots* slots = GetExistingSlots();
1944
  InvalidateChildNodes();
1935
  if (slots && slots->mChildNodes) {
1936
    auto childNodes =
1937
      static_cast<nsParentNodeChildContentList*>(slots->mChildNodes.get());
1938
    childNodes->InvalidateCache();
1939
  }
1940
1945
1941
  if (aNotify) {
1946
  if (aNotify) {
1942
    nsNodeUtils::ContentRemoved(this, aKid, previousSibling);
1947
    nsNodeUtils::ContentRemoved(this, aKid, previousSibling);
(-)a/dom/base/nsINode.h (+1 lines)
Line     Link Here 
 Lines 1278-1283   public: Link Here 
1278
  nsIContent* GetSelectionRootContent(nsIPresShell* aPresShell);
1278
  nsIContent* GetSelectionRootContent(nsIPresShell* aPresShell);
1279
1279
1280
  virtual nsINodeList* ChildNodes();
1280
  virtual nsINodeList* ChildNodes();
1281
  void InvalidateChildNodes();
1281
  nsIContent* GetFirstChild() const { return mFirstChild; }
1282
  nsIContent* GetFirstChild() const { return mFirstChild; }
1282
  nsIContent* GetLastChild() const
1283
  nsIContent* GetLastChild() const
1283
  {
1284
  {

Return to bug 1406395