Bug 608373 - Do not call document.close() when stopping a script-created document load; flush tree ops when the parser exhausts the stream in the script-created case. r=bzbarsky, a=blocking2.0-betaN.
authorHenri Sivonen <hsivonen@iki.fi>
Tue, 16 Nov 2010 09:48:30 +0200
changeset 57562 8f5e0944335d02e89ac906fd80fc4c67b26fc5ac
parent 57561 9ce8d67eaccbc819e53adab462a93a844566e431
child 57563 0efe3900a38444dd70e57aca33268f73fea2a479
push idunknown
push userunknown
push dateunknown
reviewersbzbarsky, blocking2
bugs608373
milestone2.0b8pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 608373 - Do not call document.close() when stopping a script-created document load; flush tree ops when the parser exhausts the stream in the script-created case. r=bzbarsky, a=blocking2.0-betaN.
content/html/document/src/nsHTMLDocument.cpp
parser/html/nsHtml5Parser.cpp
parser/htmlparser/tests/reftest/bug608373-1-ref.html
parser/htmlparser/tests/reftest/bug608373-1.html
parser/htmlparser/tests/reftest/reftest.list
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -997,16 +997,39 @@ nsHTMLDocument::StartDocumentLoad(const 
   }
 
   return rv;
 }
 
 void
 nsHTMLDocument::StopDocumentLoad()
 {
+  if (nsHtml5Module::sEnabled) {
+    BlockOnload();
+    if (mWriteState == eDocumentOpened) {
+      NS_ASSERTION(IsHTML(), "document.open()ed doc is not HTML?");
+
+      // Marking the document as closed, since pending scripts will be
+      // stopped by nsDocument::StopDocumentLoad() below
+      mWriteState = eDocumentClosed;
+
+      // Remove the wyciwyg channel request from the document load group
+      // that we added in OpenCommon().
+      NS_ASSERTION(mWyciwygChannel, "nsHTMLDocument::StopDocumentLoad(): "
+                   "Trying to remove nonexistent wyciwyg channel!");
+      RemoveWyciwygChannel();
+      NS_ASSERTION(!mWyciwygChannel, "nsHTMLDocument::StopDocumentLoad(): "
+                   "nsIWyciwygChannel could not be removed!");
+    }
+    nsDocument::StopDocumentLoad();
+    UnblockOnload(PR_FALSE);
+    return;
+  }
+  // Code for the old parser:
+
   // If we're writing (i.e., there's been a document.open call), then
   // nsDocument::StopDocumentLoad will do the wrong thing and simply terminate
   // our parser.
   if (mWriteState != eNotWriting) {
     Close();
   } else {
     nsDocument::StopDocumentLoad();
   }
--- a/parser/html/nsHtml5Parser.cpp
+++ b/parser/html/nsHtml5Parser.cpp
@@ -608,23 +608,32 @@ nsHtml5Parser::ParseUntilBlocked()
           mTreeBuilder->Flush();
           mExecutor->FlushDocumentWrite();
           mTokenizer->end();
           return;            
         }
         // never release the last buffer.
         NS_ASSERTION(!mLastBuffer->getStart() && !mLastBuffer->getEnd(),
                      "Sentinel buffer had its indeces changed.");
-        if (mStreamParser && mReturnToStreamParserPermitted
-            && !mExecutor->IsScriptExecuting()) {
+        if (mStreamParser) {
+          if (mReturnToStreamParserPermitted &&
+              !mExecutor->IsScriptExecuting()) {
+            mTreeBuilder->Flush();
+            mReturnToStreamParserPermitted = PR_FALSE;
+            mStreamParser->ContinueAfterScripts(mTokenizer,
+                                                mTreeBuilder,
+                                                mLastWasCR);
+          }
+        } else {
+          // Script-created parser
           mTreeBuilder->Flush();
-          mReturnToStreamParserPermitted = PR_FALSE;
-          mStreamParser->ContinueAfterScripts(mTokenizer,
-                                              mTreeBuilder,
-                                              mLastWasCR);
+          // No need to flush the executor, because the executor is already
+          // in a flush
+          NS_ASSERTION(mExecutor->IsInFlushLoop(),
+              "How did we come here without being in the flush loop?");
         }
         return; // no more data for now but expecting more
       }
       mFirstBuffer = mFirstBuffer->next;
       continue;
     }
 
     if (mBlocked || mExecutor->IsComplete()) {
new file mode 100644
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug608373-1-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+  <iframe src="data:text/html,TEXT"></iframe>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug608373-1.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<head>
+<script>
+function write() {
+  document.getElementsByTagName("iframe")[0].contentDocument.write('\u003Cscript src="data:text/javascript,var i = 0;">\u003C\/script>TEXT\u003Cscript>parent.document.documentElement.removeAttribute("class");\u003c/script>');
+}
+</script>
+</head>
+<body onload="write();">
+  <iframe></iframe>
+</body>
+</html>
+
--- a/parser/htmlparser/tests/reftest/reftest.list
+++ b/parser/htmlparser/tests/reftest/reftest.list
@@ -1,5 +1,6 @@
 == bug566280-1.html bug566280-1-ref.html
 == bug577418-1.html bug577418-1-ref.html
 == bug582788-1.html bug582788-1-ref.html
 == bug582940-1.html bug582940-1-ref.html
 == bug592656-1.html bug592656-1-ref.html
+== bug608373-1.html bug608373-1-ref.html