Bug 1364361 - Part 2: Make AllChildIterator find NAC created by all of an element's anon boxes. r=bz draft
authorCameron McCormack <cam@mcc.id.au>
Fri, 16 Jun 2017 17:22:34 +0800
changeset 595500 10222d2d0a542b5cfb5a874024a07a96880d6de0
parent 595499 0ddd0301684dfcccdacec0d42ff5eb23c7bc5c04
child 595501 407b85beadc0e0b3a8b21c20c8aaf713abbd23c8
push id64328
push userbmo:cam@mcc.id.au
push dateFri, 16 Jun 2017 09:23:01 +0000
reviewersbz
bugs1364361
milestone56.0a1
Bug 1364361 - Part 2: Make AllChildIterator find NAC created by all of an element's anon boxes. r=bz MozReview-Commit-ID: IfTLBhhG1Ya
dom/base/ChildIterator.cpp
js/src/devtools/rootAnalysis/analyzeHeapWrites.js
--- a/dom/base/ChildIterator.cpp
+++ b/dom/base/ChildIterator.cpp
@@ -365,17 +365,28 @@ AllChildrenIterator::Seek(nsIContent* aC
   } while (child && child != aChildToFind);
 
   return child == aChildToFind;
 }
 
 void
 AllChildrenIterator::AppendNativeAnonymousChildren()
 {
-  AppendNativeAnonymousChildrenFromFrame(mOriginalContent->GetPrimaryFrame());
+  if (nsIFrame* primaryFrame = mOriginalContent->GetPrimaryFrame()) {
+    // NAC created by the element's primary frame.
+    AppendNativeAnonymousChildrenFromFrame(primaryFrame);
+
+    // NAC created by any other non-primary frames for the element.
+    AutoTArray<nsIFrame::OwnedAnonBox,8> ownedAnonBoxes;
+    primaryFrame->AppendOwnedAnonBoxes(ownedAnonBoxes);
+    for (nsIFrame::OwnedAnonBox& box : ownedAnonBoxes) {
+      MOZ_ASSERT(box.mAnonBoxFrame->GetContent() == mOriginalContent);
+      AppendNativeAnonymousChildrenFromFrame(box.mAnonBoxFrame);
+    }
+  }
 
   // The root scroll frame is not the primary frame of the root element.
   // Detect and handle this case.
   if (!(mFlags & nsIContent::eSkipDocumentLevelNativeAnonymousContent) &&
       mOriginalContent == mOriginalContent->OwnerDoc()->GetRootElement()) {
     nsContentUtils::AppendDocumentLevelNativeAnonymousContentTo(
         mOriginalContent->OwnerDoc(), mAnonKids);
   }
--- a/js/src/devtools/rootAnalysis/analyzeHeapWrites.js
+++ b/js/src/devtools/rootAnalysis/analyzeHeapWrites.js
@@ -241,17 +241,17 @@ function checkFieldWrite(entry, location
         // The analysis is having some trouble keeping track of whether
         // already_AddRefed and nsCOMPtr structures are safe to access.
         // Hopefully these will be thread local, but it would be better to
         // improve the analysis to handle these.
         if (/already_AddRefed.*?.mRawPtr/.test(field))
             return;
         if (/nsCOMPtr<.*?>.mRawPtr/.test(field))
             return;
-}
+    }
 
     var str = "";
     for (var field of fields)
         str += " " + field;
     dumpError(entry, location, "Field write" + str);
 }
 
 function checkDereferenceWrite(entry, location, variable)
@@ -318,16 +318,24 @@ function ignoreCallEdge(entry, callee)
     // the analysis.
     if (/nsCSSValue::Array::AddRef/.test(callee) &&
         /nsStyleContentData::SetCounters/.test(name) &&
         entry.isSafeArgument(2))
     {
         return true;
     }
 
+    // AllChildrenIterator asks AppendOwnedAnonBoxes to append into an nsTArray
+    // local variable.
+    if (/nsIFrame::AppendOwnedAnonBoxes/.test(callee) &&
+        /AllChildrenIterator::AppendNativeAnonymousChildren/.test(name))
+    {
+        return true;
+    }
+
     // Runnables are created and named on one thread, then dispatched
     // (possibly to another). Writes on the origin thread are ok.
     if (/::SetName/.test(callee) &&
         /::UnlabeledDispatch/.test(name))
     {
         return true;
     }