Bug 715739 - Make document.write from inside a script-created parser not add to the wyciwyg channel. r=smaug.
authorHenri Sivonen <hsivonen@iki.fi>
Fri, 20 Jan 2012 13:16:27 +0200
changeset 86209 3a9d1729cd5c4676a21ec4e858a3fe1b4d8daa01
parent 86208 f2b68e3ab05ae3c6d759745e30ac334517a5db6b
child 86210 7f662941aca675c6a9318ba4919be4f1ca83aeba
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs715739
milestone12.0a1
Bug 715739 - Make document.write from inside a script-created parser not add to the wyciwyg channel. r=smaug.
content/html/document/src/nsHTMLDocument.cpp
parser/html/nsHtml5Parser.cpp
parser/html/nsHtml5Parser.h
parser/htmlparser/public/nsIParser.h
parser/htmlparser/src/nsParser.cpp
parser/htmlparser/src/nsParser.h
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -1623,17 +1623,17 @@ nsHTMLDocument::Close()
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
   if (!mParser || !mParser->IsScriptCreated()) {
     return NS_OK;
   }
 
   ++mWriteLevel;
-  nsresult rv = mParser->Parse(EmptyString(), mParser->GetRootContextKey(),
+  nsresult rv = mParser->Parse(EmptyString(), nsnull,
                                GetContentTypeInternal(), true);
   --mWriteLevel;
 
   // XXX Make sure that all the document.written content is
   // reflowed.  We should remove this call once we change
   // nsHTMLDocument::OpenCommon() so that it completely destroys the
   // earlier document's content and frame hierarchy.  Right now, it
   // re-uses the earlier document's root content object and
@@ -1725,18 +1725,18 @@ nsHTMLDocument::WriteCommon(JSContext *c
       return rv;
     }
     NS_ABORT_IF_FALSE(!JS_IsExceptionPending(cx),
                       "Open() succeeded but JS exception is pending");
   }
 
   static NS_NAMED_LITERAL_STRING(new_line, "\n");
 
-  // Save the data in cache
-  if (mWyciwygChannel) {
+  // Save the data in cache if the write isn't from within the doc
+  if (mWyciwygChannel && !key) {
     if (!aText.IsEmpty()) {
       mWyciwygChannel->WriteToCacheEntry(aText);
     }
 
     if (aNewlineTerminate) {
       mWyciwygChannel->WriteToCacheEntry(new_line);
     }
   }
@@ -2251,17 +2251,17 @@ nsHTMLDocument::GenerateParserKey(void)
   if (nsHtml5Module::sEnabled) {
     nsIScriptElement* script = mScriptLoader->GetCurrentParserInsertedScript();
     if (script && mParser && mParser->IsScriptCreated()) {
       nsCOMPtr<nsIParser> creatorParser = script->GetCreatorParser();
       if (creatorParser != mParser) {
         // Make scripts that aren't inserted by the active parser of this document
         // participate in the context of the script that document.open()ed 
         // this document.
-        return mParser->GetRootContextKey();
+        return nsnull;
       }
     }
     return script;
   } else {
     return mScriptLoader->GetCurrentScript();
   }
 }
 
--- a/parser/html/nsHtml5Parser.cpp
+++ b/parser/html/nsHtml5Parser.cpp
@@ -209,32 +209,31 @@ NS_IMETHODIMP_(bool)
 nsHtml5Parser::IsComplete()
 {
   return mExecutor->IsComplete();
 }
 
 NS_IMETHODIMP
 nsHtml5Parser::Parse(nsIURI* aURL,
                      nsIRequestObserver* aObserver,
-                     void* aKey,
+                     void* aKey, // legacy; ignored
                      nsDTDMode aMode) // legacy; ignored
 {
   /*
    * Do NOT cause WillBuildModel to be called synchronously from here!
    * The document won't be ready for it until OnStartRequest!
    */
   NS_PRECONDITION(!mExecutor->HasStarted(), 
                   "Tried to start parse without initializing the parser.");
   NS_PRECONDITION(mStreamParser, 
                   "Can't call this Parse() variant on script-created parser");
   mStreamParser->SetObserver(aObserver);
   mStreamParser->SetViewSourceTitle(aURL); // In case we're viewing source
   mExecutor->SetStreamParser(mStreamParser);
   mExecutor->SetParser(this);
-  mRootContextKey = aKey;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHtml5Parser::Parse(const nsAString& aSourceBuffer,
                      void* aKey,
                      const nsACString& aContentType,
                      bool aLastCall,
@@ -279,17 +278,17 @@ nsHtml5Parser::Parse(const nsAString& aS
     mExecutor->WillBuildModel(eDTDMode_unknown);
   }
 
   // Return early if the parser has processed EOF
   if (mExecutor->IsComplete()) {
     return NS_OK;
   }
 
-  if (aLastCall && aSourceBuffer.IsEmpty() && aKey == GetRootContextKey()) {
+  if (aLastCall && aSourceBuffer.IsEmpty() && !aKey) {
     // document.close()
     NS_ASSERTION(!mStreamParser,
                  "Had stream parser but got document.close().");
     if (mDocumentClosed) {
       // already closed
       return NS_OK;
     }
     mDocumentClosed = true;
@@ -401,17 +400,17 @@ nsHtml5Parser::Parse(const nsAString& aS
 
   nsHtml5DependentUTF16Buffer stackBuffer(aSourceBuffer);
 
   while (!mBlocked && stackBuffer.hasMore()) {
     stackBuffer.adjust(mLastWasCR);
     mLastWasCR = false;
     if (stackBuffer.hasMore()) {
       PRInt32 lineNumberSave;
-      bool inRootContext = (!mStreamParser && (aKey == mRootContextKey));
+      bool inRootContext = (!mStreamParser && !aKey);
       if (inRootContext) {
         mTokenizer->setLineNumber(mRootContextLineNumber);
       } else {
         // we aren't the root context, so save the line number on the
         // *stack* so that we can restore it.
         lineNumberSave = mTokenizer->getLineNumber();
       }
 
@@ -528,25 +527,16 @@ nsHtml5Parser::Parse(const nsAString& aS
     mDocWriteSpeculativeTreeBuilder->Flush();
     mDocWriteSpeculativeTreeBuilder->DropHandles();
     mExecutor->FlushSpeculativeLoads();
   }
 
   return NS_OK;
 }
 
-/**
- * This magic value is passed to the previous method on document.close()
- */
-NS_IMETHODIMP_(void *)
-nsHtml5Parser::GetRootContextKey()
-{
-  return mRootContextKey;
-}
-
 NS_IMETHODIMP
 nsHtml5Parser::Terminate()
 {
   // We should only call DidBuildModel once, so don't do anything if this is
   // the second time that Terminate has been called.
   if (mExecutor->IsComplete()) {
     return NS_OK;
   }
@@ -662,17 +652,16 @@ nsHtml5Parser::Reset()
                   "Reset called on a non-fragment parser.");
   mExecutor->Reset();
   mLastWasCR = false;
   UnblockParser();
   mDocumentClosed = false;
   mStreamParser = nsnull;
   mRootContextLineNumber = 1;
   mParserInsertedScriptsBeingEvaluated = 0;
-  mRootContextKey = nsnull;
   mAtomTable.Clear(); // should be already cleared in the fragment case anyway
   // Portable parser objects
   mFirstBuffer->next = nsnull;
   mFirstBuffer->setStart(0);
   mFirstBuffer->setEnd(0);
   mLastBuffer = mFirstBuffer;
 }
 
@@ -799,18 +788,17 @@ nsHtml5Parser::ParseUntilBlocked()
     if (mBlocked || mExecutor->IsComplete()) {
       return;
     }
 
     // now we have a non-empty buffer
     mFirstBuffer->adjust(mLastWasCR);
     mLastWasCR = false;
     if (mFirstBuffer->hasMore()) {
-      bool inRootContext = (!mStreamParser &&
-                              (mFirstBuffer->key == mRootContextKey));
+      bool inRootContext = (!mStreamParser && !mFirstBuffer->key);
       if (inRootContext) {
         mTokenizer->setLineNumber(mRootContextLineNumber);
       }
       mLastWasCR = mTokenizer->tokenizeBuffer(mFirstBuffer);
       if (inRootContext) {
         mRootContextLineNumber = mTokenizer->getLineNumber();
       }
       if (mTreeBuilder->HasScript()) {
--- a/parser/html/nsHtml5Parser.h
+++ b/parser/html/nsHtml5Parser.h
@@ -182,21 +182,16 @@ class nsHtml5Parser : public nsIParser,
      */
     NS_IMETHOD Parse(const nsAString& aSourceBuffer,
                      void* aKey,
                      const nsACString& aContentType,
                      bool aLastCall,
                      nsDTDMode aMode = eDTDMode_autodetect);
 
     /**
-     * Gets the key passed to initial Parse()
-     */
-    NS_IMETHOD_(void *) GetRootContextKey();
-
-    /**
      * Stops the parser prematurely
      */
     NS_IMETHOD Terminate();
 
     /**
      * Don't call. For interface backwards compat only.
      */
     NS_IMETHOD ParseFragment(const nsAString& aSourceBuffer,
--- a/parser/htmlparser/public/nsIParser.h
+++ b/parser/htmlparser/public/nsIParser.h
@@ -50,18 +50,18 @@
 #include "nsISupports.h"
 #include "nsIStreamListener.h"
 #include "nsIDTD.h"
 #include "nsStringGlue.h"
 #include "nsTArray.h"
 #include "nsIAtom.h"
 
 #define NS_IPARSER_IID \
-{ 0x0c8c3998, 0x9959, 0x496e, \
-  { 0xbd, 0xd9, 0x0b, 0x6f, 0xc4, 0x1c, 0x3b, 0x87 } }
+{ 0x30ffba62, 0x0928, 0x4503, \
+  { 0xa8, 0x95, 0xd1, 0x32, 0x76, 0x40, 0x2a, 0x2a } }
 
 // {41421C60-310A-11d4-816F-000064657374}
 #define NS_IDEBUG_DUMP_CONTENT_IID \
 { 0x41421c60, 0x310a, 0x11d4, \
 { 0x81, 0x6f, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
 
 class nsIContentSink;
 class nsIRequestObserver;
@@ -227,20 +227,16 @@ class nsIParser : public nsISupports {
                      void* aKey = 0,
                      nsDTDMode aMode = eDTDMode_autodetect) = 0;
     NS_IMETHOD Parse(const nsAString& aSourceBuffer,
                      void* aKey,
                      const nsACString& aMimeType,
                      bool aLastCall,
                      nsDTDMode aMode = eDTDMode_autodetect) = 0;
 
-    // Return a key, suitable for passing into one of the Parse methods above,
-    // that will cause this parser to use the root context.
-    NS_IMETHOD_(void *) GetRootContextKey() = 0;
-    
     NS_IMETHOD Terminate(void) = 0;
 
     /**
      * This method gets called when you want to parse a fragment of HTML or XML
      * surrounded by the context |aTagStack|. It requires that the parser have
      * been given a fragment content sink.
      *
      * @param aSourceBuffer The XML or HTML that hasn't been parsed yet.
--- a/parser/htmlparser/src/nsParser.cpp
+++ b/parser/htmlparser/src/nsParser.cpp
@@ -1070,31 +1070,16 @@ nsParser::PopContext()
  *  @return  current state
  */
 void
 nsParser::SetUnusedInput(nsString& aBuffer)
 {
   mUnusedInput = aBuffer;
 }
 
-NS_IMETHODIMP_(void *)
-nsParser::GetRootContextKey()
-{
-  CParserContext* pc = mParserContext;
-  if (!pc) {
-    return nsnull;
-  }
-
-  while (pc->mPrevContext) {
-    pc = pc->mPrevContext;
-  }
-
-  return pc->mKey;
-}
-
 /**
  *  Call this when you want to *force* the parser to terminate the
  *  parsing process altogether. This is binary -- so once you terminate
  *  you can't resume without restarting altogether.
  */
 NS_IMETHODIMP
 nsParser::Terminate(void)
 {
--- a/parser/htmlparser/src/nsParser.h
+++ b/parser/htmlparser/src/nsParser.h
@@ -194,18 +194,16 @@ class nsParser : public nsIParser,
      * @return  TRUE if all went well -- FALSE otherwise
      */
     NS_IMETHOD Parse(const nsAString& aSourceBuffer,
                      void* aKey,
                      const nsACString& aContentType,
                      bool aLastCall,
                      nsDTDMode aMode = eDTDMode_autodetect);
 
-    NS_IMETHOD_(void *) GetRootContextKey();
-
     /**
      * This method needs documentation
      */
     NS_IMETHOD ParseFragment(const nsAString& aSourceBuffer,
                              nsTArray<nsString>& aTagStack);
                              
     /**
      * This method gets called when the tokens have been consumed, and it's time