Bug 1364361 - Part 2: Make AllChildIterator find NAC created by all of an element's anon boxes. r=bz
MozReview-Commit-ID: IfTLBhhG1Ya
--- 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;
}