diff --git a/docshell/test/navigation/test_bug386782.html b/docshell/test/navigation/test_bug386782.html index 89797d06b35..b1890cfd919 100644 --- a/docshell/test/navigation/test_bug386782.html +++ b/docshell/test/navigation/test_bug386782.html @@ -20,12 +20,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=386782 //var test.window = null; - var testInterval = 2000; + var testInterval = 3000; var gTests = [ { //

designModeDocument

- url: 'data:text/html;charset=utf-8;base64,PGh0bWw%2BPGJvZHkgb25sb2FkPSJkb2N1bWVudC5kZXNpZ25Nb2RlPSdvbiciPjxwPmRlc2lnbk1vZGVEb2N1bWVudDwvcD48L2JvZHk%2BPC9odG1sPg0K', + url: "data:text/html;charset=utf-8,

designModeDocument

", name: 'designModeNavigate', expectedBodyBeforeEdit: '

designModeDocument

', expectedBodyAfterEdit: '

EDITED designModeDocument

', @@ -33,7 +33,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=386782 }, { //

contentEditable

- url: 'data:text/html;charset=utf-8;base64,PGh0bWw%2BPGJvZHkgY29udGVudEVkaXRhYmxlPSJ0cnVlIj48cD5jb250ZW50RWRpdGFibGU8L3A%2BPC9ib2R5PjwvaHRtbD4NCg0KDQo%3D', + url: 'data:text/html;charset=utf-8,

contentEditable

', name: 'contentEditableNavigate', expectedBodyBeforeEdit: '

contentEditable

', expectedBodyAfterEdit: 'EDITED

contentEditable

', diff --git a/parser/html/nsHtml5TreeBuilderCppSupplement.h b/parser/html/nsHtml5TreeBuilderCppSupplement.h index 482514cf049..c22f00f105f 100644 --- a/parser/html/nsHtml5TreeBuilderCppSupplement.h +++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h @@ -471,6 +471,18 @@ nsHtml5TreeBuilder::appendDoctypeToDocument(nsIAtom* aName, nsString* aPublicId, void nsHtml5TreeBuilder::elementPushed(PRInt32 aNamespace, nsIAtom* aName, nsIContent** aElement) { + NS_ASSERTION(aNamespace == kNameSpaceID_XHTML || aNamespace == kNameSpaceID_SVG || aNamespace == kNameSpaceID_MathML, "Element isn't HTML, SVG or MathML!"); + NS_ASSERTION(aName, "Element doesn't have local name!"); + NS_ASSERTION(aElement, "No element!"); + if (aNamespace != kNameSpaceID_XHTML) { + return; + } + if (aName == nsHtml5Atoms::body || aName == nsHtml5Atoms::frameset) { + nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); + NS_ASSERTION(treeOp, "Tree op allocation failed."); + treeOp->Init(eTreeOpStartLayout); + return; + } } void @@ -587,12 +599,6 @@ nsHtml5TreeBuilder::elementPopped(PRInt32 aNamespace, nsIAtom* aName, nsIContent treeOp->Init(eTreeOpProcessMeta, aElement); return; } - if (aName == nsHtml5Atoms::head) { - nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); - NS_ASSERTION(treeOp, "Tree op allocation failed."); - treeOp->Init(eTreeOpStartLayout); - return; - } return; } diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp index 3f8af77aae0..9a6de3de14f 100644 --- a/parser/html/nsHtml5TreeOpExecutor.cpp +++ b/parser/html/nsHtml5TreeOpExecutor.cpp @@ -150,10 +150,29 @@ nsHtml5TreeOpExecutor::DidBuildModel(PRBool aTerminated) static_cast (mParser.get())->DropStreamParser(); - // This is comes from nsXMLContentSink + // This is comes from nsXMLContentSink and nsHTMLContentSink DidBuildModelImpl(aTerminated); - mDocument->ScriptLoader()->RemoveObserver(this); + + if (!mLayoutStarted) { + // We never saw the body, and layout never got started. Force + // layout *now*, to get an initial reflow. + + // NOTE: only force the layout if we are NOT destroying the + // docshell. If we are destroying it, then starting layout will + // likely cause us to crash, or at best waste a lot of time as we + // are just going to tear it down anyway. + PRBool destroying = PR_TRUE; + if (mDocShell) { + mDocShell->IsBeingDestroyed(&destroying); + } + + if (!destroying) { + nsContentSink::StartLayout(PR_FALSE); + } + } + ScrollToRef(); + mDocument->ScriptLoader()->RemoveObserver(this); mDocument->RemoveObserver(this); if (!mParser) { // DidBuildModelImpl may cause mParser to be nulled out @@ -526,6 +545,24 @@ nsHtml5TreeOpExecutor::DocumentMode(nsHtml5DocumentMode m) htmlDocument->SetCompatibilityMode(mode); } +void +nsHtml5TreeOpExecutor::StartLayout() { + if (mLayoutStarted || !mDocument) { + return; + } + + EndDocUpdate(); + + if(NS_UNLIKELY(!mParser)) { + // got terminate + return; + } + + nsContentSink::StartLayout(PR_FALSE); + + BeginDocUpdate(); +} + /** * The reason why this code is here and not in the tree builder even in the * main-thread case is to allow the control to return from the tokenizer diff --git a/parser/html/nsHtml5TreeOpExecutor.h b/parser/html/nsHtml5TreeOpExecutor.h index 6e80b811c02..d74aae297df 100644 --- a/parser/html/nsHtml5TreeOpExecutor.h +++ b/parser/html/nsHtml5TreeOpExecutor.h @@ -310,13 +310,7 @@ class nsHtml5TreeOpExecutor : public nsContentSink, } } - void StartLayout() { - nsIDocument* doc = GetDocument(); - if (doc) { - FlushPendingAppendNotifications(); - nsContentSink::StartLayout(PR_FALSE); - } - } + void StartLayout(); void DocumentMode(nsHtml5DocumentMode m); diff --git a/parser/html/nsHtml5TreeOperation.cpp b/parser/html/nsHtml5TreeOperation.cpp index 5ae3857bfb7..13f8736587c 100644 --- a/parser/html/nsHtml5TreeOperation.cpp +++ b/parser/html/nsHtml5TreeOperation.cpp @@ -424,6 +424,14 @@ nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder, newContent->AppendChildTo(optionElt, PR_FALSE); newContent->DoneAddingChildren(PR_FALSE); } + } else if (name == nsHtml5Atoms::frameset && ns == kNameSpaceID_XHTML) { + nsIDocument* doc = aBuilder->GetDocument(); + nsCOMPtr htmlDocument = do_QueryInterface(doc); + if (htmlDocument) { + // It seems harmless to call this multiple times, since this + // is a simple field setter + htmlDocument->SetIsFrameset(PR_TRUE); + } } if (!attributes) {