Bug 1453196: Fix MathML reframing code when the root is a MathML element. r?bz
MozReview-Commit-ID: CPd40oHIT5w
new file mode 100644
--- /dev/null
+++ b/layout/base/crashtests/1453196.html
@@ -0,0 +1,15 @@
+<html>
+ <head>
+ <script>
+ function start () {
+ try { o1 = document.createElementNS('http://www.w3.org/1998/Math/MathML', 'mtable') } catch (e) {}
+ try { o2 = document.createTextNode("\u202D") } catch (e) {}
+ try { document.documentElement.appendChild(o2) } catch (e) {}
+ try { o1.insertBefore(document.documentElement, o1.childNodes[0]) } catch (e) {}
+ try { document.appendChild(o1) } catch (e) {}
+ try { document.append(o2, undefined) } catch (e) {}
+ }
+ document.addEventListener('DOMContentLoaded', start)
+ </script>
+ </head>
+</html>
\ No newline at end of file
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -524,8 +524,9 @@ load 1429962.html
pref(dom.webcomponents.shadowdom.enabled,true) load 1439016.html
load 1442506.html
load 1437155.html
load 1443027-1.html
load 1448841-1.html
load 1452839.html
load 1453702.html
load 1453342.html
+load 1453196.html
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -9085,16 +9085,37 @@ nsCSSFrameConstructor::UpdateTableCellSp
// longer be a table cell.
NS_WARNING_ASSERTION(cellFrame, "Hint should only be posted on table cells!");
if (cellFrame) {
cellFrame->GetTableFrame()->RowOrColSpanChanged(cellFrame);
}
}
+static nsIContent*
+GetTopmostMathMLElement(nsIContent* aMathMLContent)
+{
+ MOZ_ASSERT(aMathMLContent->IsMathMLElement());
+ MOZ_ASSERT(aMathMLContent->GetPrimaryFrame());
+ MOZ_ASSERT(aMathMLContent->GetPrimaryFrame()->IsFrameOfType(nsIFrame::eMathML));
+ nsIContent* root = aMathMLContent;
+
+ for (nsIContent* parent = aMathMLContent->GetFlattenedTreeParent();
+ parent;
+ parent = parent->GetFlattenedTreeParent()) {
+ nsIFrame* frame = parent->GetPrimaryFrame();
+ if (!frame || !frame->IsFrameOfType(nsIFrame::eMathML)) {
+ break;
+ }
+ root = parent;
+ }
+
+ return root;
+}
+
void
nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent,
InsertionKind aInsertionKind)
{
MOZ_ASSERT(aContent);
// If there is no document, we don't want to recreate frames for it. (You
// shouldn't generally be giving this method content without a document
@@ -9110,25 +9131,19 @@ nsCSSFrameConstructor::RecreateFramesFor
// content (which would otherwise result in *two* nested reframe
// containing block from ContentRemoved() and ContentInserted(),
// below!). We'd really like to optimize away one of those
// containing block reframes, hence the code here.
nsIFrame* frame = aContent->GetPrimaryFrame();
if (frame && frame->IsFrameOfType(nsIFrame::eMathML)) {
// Reframe the topmost MathML element to prevent exponential blowup
- // (see bug 397518)
- while (true) {
- nsIContent* parentContent = aContent->GetParent();
- nsIFrame* parentContentFrame = parentContent->GetPrimaryFrame();
- if (!parentContentFrame || !parentContentFrame->IsFrameOfType(nsIFrame::eMathML))
- break;
- aContent = parentContent;
- frame = parentContentFrame;
- }
+ // (see bug 397518).
+ aContent = GetTopmostMathMLElement(aContent);
+ frame = aContent->GetPrimaryFrame();
}
if (frame) {
nsIFrame* nonGeneratedAncestor = nsLayoutUtils::GetNonGeneratedAncestor(frame);
if (nonGeneratedAncestor->GetContent() != aContent) {
return RecreateFramesForContent(nonGeneratedAncestor->GetContent(),
InsertionKind::Async);
}