Backed out changeset 961d90be2ba8 from bug 364315 due to random crashes in
authorDave Townsend <dtownsend@oxymoronical.com>
Tue, 30 Sep 2008 13:08:20 +0100
changeset 19915 996d2802d3f2762122f9cb25a4b2302d2facbb8f
parent 19898 961d90be2ba80d1ecafb00edc027908beca1e733
child 19916 d00d64c5b4d9702accf1b09855ceefe3ccfb2f4b
push idunknown
push userunknown
push dateunknown
bugs364315
milestone1.9.1b1pre
backs out961d90be2ba80d1ecafb00edc027908beca1e733
Backed out changeset 961d90be2ba8 from bug 364315 due to random crashes in tests.
content/base/src/nsScriptLoader.cpp
content/base/src/nsScriptLoader.h
parser/htmlparser/src/CParserContext.cpp
parser/htmlparser/src/CParserContext.h
parser/htmlparser/src/nsParser.cpp
parser/htmlparser/src/nsParser.h
parser/htmlparser/src/nsScanner.cpp
parser/htmlparser/src/nsScanner.h
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -91,21 +91,16 @@ public:
   {
     mElement->ScriptAvailable(aResult, mElement, mIsInline, mURI, mLineNo);
   }
   void FireScriptEvaluated(nsresult aResult)
   {
     mElement->ScriptEvaluated(aResult, mElement, mIsInline);
   }
 
-  PRBool IsPreload()
-  {
-    return mElement == nsnull;
-  }
-
   nsCOMPtr<nsIScriptElement> mElement;
   PRPackedBool mLoading;             // Are we still waiting for a load to complete?
   PRPackedBool mDefer;               // Is execution defered?
   PRPackedBool mIsInline;            // Is the script inline or loaded?
   nsString mScriptText;              // Holds script for loaded scripts
   PRUint32 mJSVersion;
   nsCOMPtr<nsIURI> mURI;
   PRInt32 mLineNo;
@@ -190,82 +185,16 @@ IsScriptEventHandler(nsIScriptElement *a
 
     return PR_TRUE;
   }
 
   return PR_FALSE;
 }
 
 nsresult
-nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType)
-{
-  // Check that the containing page is allowed to load this URI.
-  nsresult rv = nsContentUtils::GetSecurityManager()->
-    CheckLoadURIWithPrincipal(mDocument->NodePrincipal(), aRequest->mURI,
-                              nsIScriptSecurityManager::ALLOW_CHROME);
-
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // After the security manager, the content-policy stuff gets a veto
-  PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
-  rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_SCRIPT,
-                                 aRequest->mURI,
-                                 mDocument->NodePrincipal(),
-                                 aRequest->mElement,
-                                 NS_LossyConvertUTF16toASCII(aType),
-                                 nsnull,    //extra
-                                 &shouldLoad,
-                                 nsContentUtils::GetContentPolicy(),
-                                 nsContentUtils::GetSecurityManager());
-  if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
-    if (NS_FAILED(rv) || shouldLoad != nsIContentPolicy::REJECT_TYPE) {
-      return NS_ERROR_CONTENT_BLOCKED;
-    }
-    return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
-  }
-
-  nsCOMPtr<nsILoadGroup> loadGroup = mDocument->GetDocumentLoadGroup();
-  nsCOMPtr<nsIStreamLoader> loader;
-
-  nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mDocument->GetScriptGlobalObject()));
-  nsIDocShell *docshell = window->GetDocShell();
-
-  nsCOMPtr<nsIInterfaceRequestor> prompter(do_QueryInterface(docshell));
-
-  nsCOMPtr<nsIChannel> channel;
-  rv = NS_NewChannel(getter_AddRefs(channel),
-                     aRequest->mURI, nsnull, loadGroup,
-                     prompter, nsIRequest::LOAD_NORMAL);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
-  if (httpChannel) {
-    // HTTP content negotation has little value in this context.
-    httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
-                                  NS_LITERAL_CSTRING("*/*"),
-                                  PR_FALSE);
-    httpChannel->SetReferrer(mDocument->GetDocumentURI());
-  }
-
-  rv = NS_NewStreamLoader(getter_AddRefs(loader), this);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return channel->AsyncOpen(loader, aRequest);
-}
-
-PRBool
-nsScriptLoader::PreloadURIComparator::Equals(const PreloadInfo &aPi,
-                                             nsIURI * const &aURI) const
-{
-  PRBool same;
-  return NS_SUCCEEDED(aPi.mRequest->mURI->Equals(aURI, &same)) &&
-         same;
-}
-
-nsresult
 nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
 {
   // We need a document to evaluate scripts.
   NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE);
 
   // Check to see if scripts has been turned off.
   if (!mEnabled || !mDocument->IsScriptEnabled()) {
     return NS_ERROR_NOT_AVAILABLE;
@@ -442,65 +371,84 @@ nsScriptLoader::ProcessScriptElement(nsI
       !nsContentUtils::IsChromeDoc(mDocument)) {
     NS_WARNING("Untrusted language called from non-chrome - ignored");
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   nsCOMPtr<nsIContent> eltContent(do_QueryInterface(aElement));
   eltContent->SetScriptTypeID(typeID);
 
-  PRBool hadPendingRequests = !!GetFirstPendingRequest();
-
-  // Did we preload this request?
-  nsCOMPtr<nsIURI> scriptURI = aElement->GetScriptURI();
-  nsRefPtr<nsScriptLoadRequest> request;
-  if (scriptURI) {
-    nsTArray<PreloadInfo>::index_type i =
-      mPreloads.IndexOf(scriptURI.get(), 0, PreloadURIComparator());
-    if (i != nsTArray<PreloadInfo>::NoIndex) {
-      request = mPreloads[i].mRequest;
-      request->mElement = aElement;
-      request->mJSVersion = version;
-      request->mDefer = mDeferEnabled && aElement->GetScriptDeferred();
-      mPreloads.RemoveElementAt(i);
-
-      if (!request->mLoading && !request->mDefer && !hadPendingRequests &&
-            ReadyToExecuteScripts() && nsContentUtils::IsSafeToRunScript()) {
-        return ProcessRequest(request);
-      }
-
-      // Not done loading yet. Move into the real requests queue and wait.
-      mRequests.AppendObject(request);
-
-      if (!request->mLoading && !hadPendingRequests && ReadyToExecuteScripts() &&
-          !request->mDefer) {
-        nsContentUtils::AddScriptRunner(new nsRunnableMethod<nsScriptLoader>(this,
-          &nsScriptLoader::ProcessPendingRequests));
-      }
-
-      return request->mDefer ? NS_OK : NS_ERROR_HTMLPARSER_BLOCK;
-    }
-  }
-
   // Create a request object for this script
-  request = new nsScriptLoadRequest(aElement, version);
+  nsRefPtr<nsScriptLoadRequest> request = new nsScriptLoadRequest(aElement, version);
   NS_ENSURE_TRUE(request, NS_ERROR_OUT_OF_MEMORY);
 
   request->mDefer = mDeferEnabled && aElement->GetScriptDeferred();
 
+  PRBool hadPendingRequests = !!GetFirstPendingRequest();
+
   // First check to see if this is an external script
+  nsCOMPtr<nsIURI> scriptURI = aElement->GetScriptURI();
   if (scriptURI) {
+    // Check that the containing page is allowed to load this URI.
+    rv = nsContentUtils::GetSecurityManager()->
+      CheckLoadURIWithPrincipal(mDocument->NodePrincipal(), scriptURI,
+                                nsIScriptSecurityManager::ALLOW_CHROME);
+
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    // After the security manager, the content-policy stuff gets a veto
+    PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
+    rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_SCRIPT,
+                                   scriptURI,
+                                   mDocument->NodePrincipal(),
+                                   aElement,
+                                   NS_LossyConvertUTF16toASCII(type),
+                                   nsnull,    //extra
+                                   &shouldLoad,
+                                   nsContentUtils::GetContentPolicy(),
+                                   nsContentUtils::GetSecurityManager());
+    if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
+      if (NS_FAILED(rv) || shouldLoad != nsIContentPolicy::REJECT_TYPE) {
+        return NS_ERROR_CONTENT_BLOCKED;
+      }
+      return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
+    }
+
     request->mURI = scriptURI;
     request->mIsInline = PR_FALSE;
     request->mLoading = PR_TRUE;
 
-    rv = StartLoad(request, type);
-    if (NS_FAILED(rv)) {
-      return rv;
+    nsCOMPtr<nsILoadGroup> loadGroup = mDocument->GetDocumentLoadGroup();
+    nsCOMPtr<nsIStreamLoader> loader;
+
+    nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(globalObject));
+    nsIDocShell *docshell = window->GetDocShell();
+
+    nsCOMPtr<nsIInterfaceRequestor> prompter(do_QueryInterface(docshell));
+
+    nsCOMPtr<nsIChannel> channel;
+    rv = NS_NewChannel(getter_AddRefs(channel),
+                       scriptURI, nsnull, loadGroup,
+                       prompter, nsIRequest::LOAD_NORMAL);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
+    if (httpChannel) {
+      // HTTP content negotation has little value in this context.
+      httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
+                                    NS_LITERAL_CSTRING("*/*"),
+                                    PR_FALSE);
+      httpChannel->SetReferrer(mDocument->GetDocumentURI());
     }
+
+    rv = NS_NewStreamLoader(getter_AddRefs(loader), this);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = channel->AsyncOpen(loader, request);
+    NS_ENSURE_SUCCESS(rv, rv);
   } else {
     request->mLoading = PR_FALSE;
     request->mIsInline = PR_TRUE;
     request->mURI = mDocument->GetDocumentURI();
 
     request->mLineNo = aElement->GetScriptLineNumber();
 
     // If we've got existing pending requests, add ourselves
@@ -861,21 +809,18 @@ nsScriptLoader::OnStreamComplete(nsIStre
 {
   nsScriptLoadRequest* request = static_cast<nsScriptLoadRequest*>(aContext);
   NS_ASSERTION(request, "null request in stream complete handler");
   NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
 
   nsresult rv = PrepareLoadedRequest(request, aLoader, aStatus, aStringLen,
                                      aString);
   if (NS_FAILED(rv)) {
-    if (!mRequests.RemoveObject(request)) {
-      mPreloads.RemoveElement(request, PreloadRequestComparator());
-    } else {
-      FireScriptAvailable(rv, request);
-    }
+    mRequests.RemoveObject(request);
+    FireScriptAvailable(rv, request);
   }
 
   // Process our request and/or any pending ones
   ProcessPendingRequests();
 
   return NS_OK;
 }
 
@@ -910,40 +855,32 @@ nsScriptLoader::PrepareLoadedRequest(nsS
       return NS_ERROR_NOT_AVAILABLE;
     }
   }
 
   nsCOMPtr<nsIChannel> channel = do_QueryInterface(req);
   if (aStringLen) {
     // Check the charset attribute to determine script charset.
     nsAutoString hintCharset;
-    if (!aRequest->IsPreload()) {
-      aRequest->mElement->GetScriptCharset(hintCharset);
-    } else {
-      nsTArray<PreloadInfo>::index_type i =
-        mPreloads.IndexOf(aRequest, 0, PreloadRequestComparator());
-      NS_ASSERTION(i != mPreloads.NoIndex, "Incorrect preload bookkeeping");
-      hintCharset = mPreloads[i].mCharset;
-    }
+    aRequest->mElement->GetScriptCharset(hintCharset);
     rv = ConvertToUTF16(channel, aString, aStringLen, hintCharset, mDocument,
                         aRequest->mScriptText);
 
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (!ShouldExecuteScript(mDocument, channel)) {
       return NS_ERROR_NOT_AVAILABLE;
     }
   }
 
   // This assertion could fire errorously if we ran out of memory when
   // inserting the request in the array. However it's an unlikely case
   // so if you see this assertion it is likely something else that is
   // wrong, especially if you see it more than once.
-  NS_ASSERTION(mRequests.IndexOf(aRequest) >= 0 ||
-               mPreloads.Contains(aRequest, PreloadRequestComparator()),
+  NS_ASSERTION(mRequests.IndexOf(aRequest) >= 0,
                "aRequest should be pending!");
 
   // Mark this as loaded
   aRequest->mLoading = PR_FALSE;
 
   return NS_OK;
 }
 
@@ -976,38 +913,14 @@ nsScriptLoader::ShouldExecuteScript(nsID
   rv = channelPrincipal->Subsumes(docPrincipal, &subsumes);
   return NS_SUCCEEDED(rv) && subsumes;
 }
 
 void
 nsScriptLoader::EndDeferringScripts()
 {
   mDeferEnabled = PR_FALSE;
-  for (PRUint32 i = 0; i < (PRUint32)mRequests.Count(); ++i) {
+  for (PRUint32 i = 0; i < mRequests.Count(); ++i) {
     mRequests[i]->mDefer = PR_FALSE;
   }
 
   ProcessPendingRequests();
 }
-
-void
-nsScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
-                           const nsAString &aType)
-{
-  nsRefPtr<nsScriptLoadRequest> request = new nsScriptLoadRequest(nsnull, 0);
-  if (!request) {
-    return;
-  }
-
-  request->mURI = aURI;
-  request->mIsInline = PR_FALSE;
-  request->mLoading = PR_TRUE;
-  request->mDefer = PR_FALSE; // This is computed later when we go to execute the
-                              // script.
-  nsresult rv = StartLoad(request, aType);
-  if (NS_FAILED(rv)) {
-    return;
-  }
-
-  PreloadInfo *pi = mPreloads.AppendElement();
-  pi->mRequest = request;
-  pi->mCharset = aCharset;
-}
--- a/content/base/src/nsScriptLoader.h
+++ b/content/base/src/nsScriptLoader.h
@@ -200,33 +200,18 @@ public:
    * Stops defering scripts and immediately processes the mDeferredRequests
    * queue.
    *
    * WARNING: This function will syncronously execute content scripts, so be
    * prepared that the world might change around you.
    */
   void EndDeferringScripts();
 
-  /**
-   * Adds aURI to the preload list and starts loading it.
-   *
-   * @param aURI The URI of the external script.
-   * @param aCharset The charset parameter for the script.
-   * @param aType The type parameter for the script.
-   */
-  virtual void PreloadURI(nsIURI *aURI, const nsAString &aCharset,
-                          const nsAString &aType);
-
 protected:
   /**
-   * Start a load for aRequest's URI.
-   */
-  nsresult StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType);
-
-  /**
    * Process any pending requests asyncronously (i.e. off an event) if there
    * are any. Note that this is a no-op if there aren't any currently pending
    * requests.
    */
   virtual void ProcessPendingRequestsAsync();
 
   /**
    * If true, the loader is ready to execute scripts, and so are all its
@@ -263,35 +248,16 @@ protected:
                                 const PRUint8* aString);
 
   // Returns the first pending (non deferred) request
   nsScriptLoadRequest* GetFirstPendingRequest();
 
   nsIDocument* mDocument;                   // [WEAK]
   nsCOMArray<nsIScriptLoaderObserver> mObservers;
   nsCOMArray<nsScriptLoadRequest> mRequests;
-
-  // In mRequests, the additional information here is stored by the element.
-  struct PreloadInfo {
-    nsRefPtr<nsScriptLoadRequest> mRequest;
-    nsString mCharset;
-  };
-
-  struct PreloadRequestComparator {
-    PRBool Equals(const PreloadInfo &aPi, nsScriptLoadRequest * const &aRequest)
-        const
-    {
-      return aRequest == aPi.mRequest;
-    }
-  };
-  struct PreloadURIComparator {
-    PRBool Equals(const PreloadInfo &aPi, nsIURI * const &aURI) const;
-  };
-  nsTArray<PreloadInfo> mPreloads;
-
   nsCOMPtr<nsIScriptElement> mCurrentScript;
   // XXXbz do we want to cycle-collect these or something?  Not sure.
   nsTArray< nsRefPtr<nsScriptLoader> > mPendingChildLoaders;
   PRUint32 mBlockerCount;
   PRPackedBool mEnabled;
   PRPackedBool mDeferEnabled;
 };
 
--- a/parser/htmlparser/src/CParserContext.cpp
+++ b/parser/htmlparser/src/CParserContext.cpp
@@ -58,17 +58,17 @@ CParserContext::CParserContext(nsScanner
     mScanner(aScanner),
     mDTDMode(eDTDMode_unknown),
     mStreamListenerState(eNone),
     mContextType(eCTNone),
     mAutoDetectStatus(aStatus),
     mParserCommand(aCommand),
     mMultipart(PR_TRUE),
     mCopyUnused(aCopyUnused),
-    mNumConsumed(0)
+    mTransferBufferSize(eTransferBufferSize)
 { 
   MOZ_COUNT_CTOR(CParserContext); 
 } 
 
 CParserContext::~CParserContext()
 {
   // It's ok to simply ingore the PrevContext.
   MOZ_COUNT_DTOR(CParserContext);
--- a/parser/htmlparser/src/CParserContext.h
+++ b/parser/htmlparser/src/CParserContext.h
@@ -55,51 +55,54 @@
 #include "nsAutoPtr.h"
 
 /**
  * Note that the parser is given FULL access to all
  * data in a parsercontext. Hey, that what it's for!
  */
 
 class CParserContext {
+
 public:
-   enum eContextType {eCTNone,eCTURL,eCTString,eCTStream};
+
+    enum {eTransferBufferSize=4096};
+    enum eContextType {eCTNone,eCTURL,eCTString,eCTStream};
 
-   CParserContext(nsScanner* aScanner,
-                  void* aKey = 0,
-                  eParserCommands aCommand = eViewNormal,
-                  nsIRequestObserver* aListener = 0,
-                  nsIDTD* aDTD = 0,
-                  eAutoDetectResult aStatus = eUnknownDetect,
-                  PRBool aCopyUnused = PR_FALSE);
-
+   CParserContext(  nsScanner* aScanner,
+                    void* aKey=0, 
+                    eParserCommands aCommand=eViewNormal,
+                    nsIRequestObserver* aListener=0, 
+                    nsIDTD *aDTD=0, 
+                    eAutoDetectResult aStatus=eUnknownDetect, 
+                    PRBool aCopyUnused=PR_FALSE); 
+    
     ~CParserContext();
 
     nsresult GetTokenizer(PRInt32 aType,
                           nsIContentSink* aSink,
                           nsITokenizer*& aTokenizer);
     void  SetMimeType(const nsACString& aMimeType);
 
     nsCOMPtr<nsIRequest> mRequest; // provided by necko to differnciate different input streams
                                    // why is mRequest strongly referenced? see bug 102376.
-    nsCOMPtr<nsIDTD>     mDTD;
+    nsCOMPtr<nsIDTD>	 mDTD;
     nsCOMPtr<nsIRequestObserver> mListener;
+    nsAutoArrayPtr<char> mTransferBuffer;
     void*                mKey;
     nsCOMPtr<nsITokenizer> mTokenizer;
     CParserContext*      mPrevContext;
     nsAutoPtr<nsScanner> mScanner;
-
+    
     nsCString            mMimeType;
     nsDTDMode            mDTDMode;
-
+    
     eParserDocType       mDocType;
-    eStreamState         mStreamListenerState;
+    eStreamState         mStreamListenerState; //this is really only here for debug purposes.
     eContextType         mContextType;
     eAutoDetectResult    mAutoDetectStatus;
-    eParserCommands      mParserCommand;
+    eParserCommands      mParserCommand;   //tells us to viewcontent/viewsource/viewerrors...
 
     PRPackedBool         mMultipart;
     PRPackedBool         mCopyUnused;
-
-    PRUint32             mNumConsumed;
+    PRUint32             mTransferBufferSize;
 };
 
 #endif
--- a/parser/htmlparser/src/nsParser.cpp
+++ b/parser/htmlparser/src/nsParser.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set sw=2 ts=2 et tw=79: */
+/* vim: set sw=2 ts=2 et tw=78: */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -47,33 +47,25 @@
 #include "nsIChannel.h"
 #include "nsICachingChannel.h"
 #include "nsICacheEntryDescriptor.h"
 #include "nsICharsetAlias.h"
 #include "nsICharsetConverterManager.h"
 #include "nsIInputStream.h"
 #include "CNavDTD.h"
 #include "prenv.h"
-#include "prlock.h"
-#include "prcvar.h"
-#include "nsAutoLock.h"
 #include "nsParserCIID.h"
 #include "nsReadableUtils.h"
 #include "nsCOMPtr.h"
 #include "nsExpatDriver.h"
 #include "nsIServiceManager.h"
 #include "nsICategoryManager.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIFragmentContentSink.h"
 #include "nsStreamUtils.h"
-#include "nsHTMLTokenizer.h"
-#include "nsIDocument.h"
-#include "nsNetUtil.h"
-#include "nsScriptLoader.h"
-#include "nsDataHashtable.h"
 
 #ifdef MOZ_VIEW_SOURCE
 #include "nsViewSourceHTML.h"
 #endif
 
 #define NS_PARSER_FLAG_PARSER_ENABLED         0x00000002
 #define NS_PARSER_FLAG_OBSERVERS_ENABLED      0x00000004
 #define NS_PARSER_FLAG_PENDING_CONTINUE_EVENT 0x00000008
@@ -158,488 +150,16 @@ public:
   {
     mParser->HandleParserContinueEvent(this);
     return NS_OK;
   }
 };
 
 //-------------- End ParseContinue Event Definition ------------------------
 
-template <class Type>
-class Holder {
-public:
-  typedef void (*Reaper)(Type *);
-
-  Holder(Reaper aReaper)
-    : mHoldee(nsnull), mReaper(aReaper)
-  {
-  }
-
-  ~Holder() {
-    if (mHoldee) {
-      mReaper(mHoldee);
-    }
-  }
-
-  Type *get() {
-    return mHoldee;
-  }
-  const Holder &operator =(Type *aHoldee) {
-    if (mHoldee && aHoldee != mHoldee) {
-      mReaper(mHoldee);
-    }
-    mHoldee = aHoldee;
-    return *this;
-  }
-
-private:
-  Type *mHoldee;
-  Reaper mReaper;
-};
-
-class nsSpeculativeScriptThread : public nsIRunnable {
-public:
-  nsSpeculativeScriptThread(nsTokenAllocator *aTokenAllocator)
-    : mLock(PR_DestroyLock),
-      mCVar(PR_DestroyCondVar),
-      mKeepParsing(0),
-      mCurrentlyParsing(0),
-      mNumURIs(0),
-      mNumConsumed(0),
-      mTokenAllocator(aTokenAllocator) {
-  }
-
-  ~nsSpeculativeScriptThread() {
-    if (mThread) {
-      mThread->Shutdown();
-    }
-  }
-
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIRUNNABLE
-
-  nsresult StartParsing(nsParser *aParser);
-  void StopParsing(PRBool aFromDocWrite);
-
-  enum PrefetchType { SCRIPT, STYLESHEET, IMAGE };
-  struct PrefetchEntry {
-    PrefetchType type;
-    nsString uri;
-    nsString charset;
-    nsString elementType;
-  };
-
-  nsIDocument *GetDocument() {
-    NS_ASSERTION(NS_IsMainThread(), "Potential threadsafety hazard");
-    return mDocument;
-  }
-
-  PRBool Parsing() {
-    return mCurrentlyParsing;
-  }
-
-  CParserContext *Context() {
-    return mContext;
-  }
-
-  typedef nsDataHashtable<nsCStringHashKey, PRBool> PreloadedType;
-  PreloadedType& GetPreloadedURIs() {
-    return mPreloadedURIs;
-  }
-
-private:
-
-  nsresult ProcessToken(CToken *aToken);
-
-  void AddToPrefetchList(const nsAString &src,
-                         const nsAString &charset,
-                         const nsAString &elementType,
-                         PrefetchType type);
-
-  // The following members are shared across the main thread and the
-  // speculatively parsing thread.
-  Holder<PRLock> mLock;
-  Holder<PRCondVar> mCVar;
-
-  PRUint32 mKeepParsing;
-  PRUint32 mCurrentlyParsing;
-  nsRefPtr<nsHTMLTokenizer> mTokenizer;
-  nsAutoPtr<nsScanner> mScanner;
-
-  enum { kBatchPrefetchURIs = 5 };
-  nsAutoTArray<PrefetchEntry, kBatchPrefetchURIs> mURIs;
-  PRUint16 mNumURIs;
-
-  // Number of characters consumed by the last speculative parse.
-  PRUint32 mNumConsumed;
-
-  // These members are only accessed on the main thread.
-  nsCOMPtr<nsIThread> mThread;
-  nsCOMPtr<nsIDocument> mDocument;
-  CParserContext *mContext;
-  PreloadedType mPreloadedURIs;
-
-  // These members are only accessed on the speculatively parsing thread.
-  nsTokenAllocator *mTokenAllocator;
-};
-
-class nsPreloadURIs : public nsIRunnable {
-public:
-  nsPreloadURIs(nsAutoTArray<nsSpeculativeScriptThread::PrefetchEntry, 5> &aURIs,
-                nsSpeculativeScriptThread *aScriptThread)
-    : mURIs(aURIs),
-      mScriptThread(aScriptThread) {
-  }
-
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIRUNNABLE
-
-  static void PreloadURIs(const nsAutoTArray<nsSpeculativeScriptThread::PrefetchEntry, 5> &aURIs,
-                          nsSpeculativeScriptThread *aScriptThread);
-
-private:
-  nsAutoTArray<nsSpeculativeScriptThread::PrefetchEntry, 5> mURIs;
-  nsRefPtr<nsSpeculativeScriptThread> mScriptThread;
-};
-
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsPreloadURIs, nsIRunnable)
-
-NS_IMETHODIMP
-nsPreloadURIs::Run()
-{
-  PreloadURIs(mURIs, mScriptThread);
-  return NS_OK;
-}
-
-void
-nsPreloadURIs::PreloadURIs(const nsAutoTArray<nsSpeculativeScriptThread::PrefetchEntry, 5> &aURIs,
-                           nsSpeculativeScriptThread *aScriptThread)
-{
-  NS_ASSERTION(NS_IsMainThread(), "Touching non-threadsafe objects off thread");
-
-  nsIDocument *doc = aScriptThread->GetDocument();
-  NS_ASSERTION(doc, "We shouldn't have started preloading without a document");
-
-  // Note: Per the code in the HTML content sink, we should be keeping track
-  // of each <base href> as it comes. However, because we do our speculative
-  // parsing off the main thread, this is hard to emulate. For now, just load
-  // the URIs using the document's base URI at the potential cost of being
-  // wrong and having to re-load a given relative URI later.
-  nsIURI *base = doc->GetBaseURI();
-  const nsCString &charset = doc->GetDocumentCharacterSet();
-  nsSpeculativeScriptThread::PreloadedType &alreadyPreloaded =
-    aScriptThread->GetPreloadedURIs();
-  for (PRUint32 i = 0, e = aURIs.Length(); i < e; ++i) {
-    const nsSpeculativeScriptThread::PrefetchEntry &pe = aURIs[i];
-    if (pe.type != nsSpeculativeScriptThread::SCRIPT) {
-      continue;
-    }
-
-    nsCOMPtr<nsIURI> uri;
-    nsresult rv = NS_NewURI(getter_AddRefs(uri), pe.uri, charset.get(), base);
-    if (NS_FAILED(rv)) {
-      NS_WARNING("Failed to create a URI");
-      continue;
-    }
-
-    nsCAutoString spec;
-    uri->GetSpec(spec);
-    PRBool answer;
-    if (alreadyPreloaded.Get(spec, &answer)) {
-      // Already preloaded. Don't preload again.
-      continue;
-    }
-
-    alreadyPreloaded.Put(spec, PR_TRUE);
-
-    doc->ScriptLoader()->PreloadURI(uri, pe.charset, pe.elementType);
-  }
-}
-
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsSpeculativeScriptThread, nsIRunnable)
-
-NS_IMETHODIMP
-nsSpeculativeScriptThread::Run()
-{
-  nsScannerIterator start;
-  mScanner->CurrentPosition(start);
-  mTokenizer->WillTokenize(PR_FALSE, mTokenAllocator);
-  while (mKeepParsing) {
-    PRBool flushTokens = PR_FALSE;
-    nsresult rv = mTokenizer->ConsumeToken(*mScanner, flushTokens);
-    if (rv == kEOF) {
-      break;
-    }
-
-    // TODO Don't pop the tokens.
-    CToken *token;
-    while (mKeepParsing && NS_SUCCEEDED(rv) && (token = mTokenizer->PopToken())) {
-      rv = ProcessToken(token);
-    }
-  }
-  mTokenizer->DidTokenize(PR_FALSE);
-
-  nsAutoLock al(mLock.get());
-
-  nsScannerIterator end;
-  mScanner->CurrentPosition(end);
-
-  mNumConsumed = Distance(start, end);
-
-  mCurrentlyParsing = 0;
-  PR_NotifyCondVar(mCVar.get());
-  return NS_OK;
-}
-
-nsresult
-nsSpeculativeScriptThread::StartParsing(nsParser *aParser)
-{
-  NS_ASSERTION(NS_IsMainThread(), "Called on the wrong thread");
-  NS_ASSERTION(!mCurrentlyParsing, "Bad race happening");
-
-  nsIContentSink *sink = aParser->GetContentSink();
-  if (!sink) {
-    return NS_OK;
-  }
-
-  nsCOMPtr<nsIDocument> doc = do_QueryInterface(sink->GetTarget());
-  if (!doc) {
-    return NS_OK;
-  }
-
-  nsAutoString toScan;
-  CParserContext *context = aParser->PeekContext();
-  if (!mThread) {
-    nsresult rv = NS_NewThread(getter_AddRefs(mThread), nsnull);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    mLock = PR_NewLock();
-    if (!mLock.get()) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-
-    mCVar = PR_NewCondVar(mLock.get());
-    if (!mCVar.get()) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-
-    if (!mPreloadedURIs.Init(15)) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-
-    mTokenizer = new nsHTMLTokenizer(context->mDTDMode, context->mDocType,
-                                     context->mParserCommand, 0);
-    if (!mTokenizer) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-    mTokenizer->CopyState(context->mTokenizer);
-    context->mScanner->CopyUnusedData(toScan);
-  } else if (context == mContext) {
-    // Don't parse the same part of the document twice.
-    nsScannerIterator end;
-    context->mScanner->EndReading(end);
-
-    nsScannerIterator start;
-    context->mScanner->CurrentPosition(start);
-
-    if (mNumConsumed > context->mNumConsumed) {
-      // We consumed more the last time we tried speculatively parsing than we
-      // did the last time we actually parsed. 
-      PRUint32 distance = Distance(start, end);
-      start.advance(PR_MIN(mNumConsumed - context->mNumConsumed, distance));
-    }
-
-    if (start == end) {
-      // We're at the end of this context's buffer, nothing else to do.
-      return NS_OK;
-    }
-
-    CopyUnicodeTo(start, end, toScan);
-  } else {
-    // Grab all of the context.
-    context->mScanner->CopyUnusedData(toScan);
-    if (toScan.IsEmpty()) {
-      // Nothing to parse, don't do anything.
-      return NS_OK;
-    }
-  }
-
-  nsCAutoString charset;
-  PRInt32 source;
-  aParser->GetDocumentCharset(charset, source);
-
-  mScanner = new nsScanner(toScan, charset, source);
-  if (!mScanner) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  mDocument.swap(doc);
-  mKeepParsing = 1;
-  mCurrentlyParsing = 1;
-  mContext = context;
-  return mThread->Dispatch(this, nsIEventTarget::DISPATCH_NORMAL);
-}
-
-void
-nsSpeculativeScriptThread::StopParsing(PRBool aFromDocWrite)
-{
-  NS_ASSERTION(NS_IsMainThread(), "Can't stop parsing from another thread");
-
-  if (!mThread) {
-    // If we bailed early out of StartParsing, don't do anything.
-    return;
-  }
-
-  {
-    nsAutoLock al(mLock.get());
-
-    mKeepParsing = 0;
-    if (mCurrentlyParsing) {
-      PR_WaitCondVar(mCVar.get(), PR_INTERVAL_NO_TIMEOUT);
-      NS_ASSERTION(!mCurrentlyParsing, "Didn't actually stop parsing?");
-    }
-  }
-
-  // The thread is now idle. It is now safe to touch mContext on the main
-  // thread.
-  if (mNumURIs) {
-    nsPreloadURIs::PreloadURIs(mURIs, this);
-    mNumURIs = 0;
-    mURIs.Clear();
-  }
-
-  // Note: Currently, we pop the tokens off (see the comment in Run) so this
-  // isn't a problem. If and when we actually use the tokens created
-  // off-thread, we'll need to use aFromDocWrite for real.
-  (void)aFromDocWrite;
-}
-
-nsresult
-nsSpeculativeScriptThread::ProcessToken(CToken *aToken)
-{
-  // Only called on the speculative script thread.
-
-  CHTMLToken *token = static_cast<CHTMLToken *>(aToken);
-  switch (static_cast<eHTMLTokenTypes>(token->GetTokenType())) {
-    case eToken_start: {
-        CStartToken *start = static_cast<CStartToken *>(aToken);
-        nsHTMLTag tag = static_cast<nsHTMLTag>(start->GetTypeID());
-        PRInt16 attrs = start->GetAttributeCount();
-        PRInt16 i = 0;
-        nsAutoString src;
-        nsAutoString elementType;
-        nsAutoString charset;
-        PrefetchType ptype;
-
-        switch (tag) {
-#if 0 // TODO Support stylesheet and image preloading.
-          case eHTMLTag_link: {
-            // If this is a <link rel=stylesheet> find the src.
-            PRBool isRelStylesheet = PR_FALSE;
-            for (; i < attrs; ++i) {
-              CAttributeToken *attr = static_cast<CAttributeToken *>(mTokenizer->PopToken());
-              NS_ASSERTION(attr->GetTokenType() == eToken_attribute, "Weird token");
-
-              if (attr->GetKey().EqualsLiteral("rel")) {
-                if (!attr->GetValue().EqualsLiteral("stylesheet")) {
-                  IF_FREE(attr, mTokenAllocator);
-                  break;
-                }
-                isRelStylesheet = PR_TRUE;
-              } else if (attr->GetKey().EqualsLiteral("src")) {
-                src.Assign(attr->GetValue());
-                if (isRelStylesheet) {
-                  IF_FREE(attr, mTokenAllocator);
-                  break;
-                }
-              }
-
-              IF_FREE(attr, mTokenAllocator);
-            }
-
-            if (isRelStylesheet && !src.IsEmpty()) {
-              AddToPrefetchList(src, STYLESHEET);
-            }
-            break;
-          }
-
-          case eHTMLTag_style:
-            ptype = STYLESHEET;
-          case eHTMLTag_img:
-            if (tag == eHTMLTag_img)
-              ptype = IMAGE;
-#endif
-          case eHTMLTag_script:
-            if (tag == eHTMLTag_script)
-              ptype = SCRIPT;
-
-            for (; i < attrs; ++i) {
-              CAttributeToken *attr = static_cast<CAttributeToken *>(mTokenizer->PopToken());
-              NS_ASSERTION(attr->GetTokenType() == eToken_attribute, "Weird token");
-
-              if (attr->GetKey().EqualsLiteral("src")) {
-                src.Assign(attr->GetValue());
-              } else if (attr->GetKey().EqualsLiteral("charset")) {
-                charset.Assign(attr->GetValue());
-              } else if (attr->GetKey().EqualsLiteral("type")) {
-                elementType.Assign(attr->GetValue());
-              }
-              IF_FREE(attr, mTokenAllocator);
-            }
-
-            if (!src.IsEmpty()) {
-              AddToPrefetchList(src, charset, elementType, ptype);
-            }
-            break;
-
-          default:
-            break;
-        }
-
-        for (; i < attrs; ++i) {
-          CToken *attr = mTokenizer->PopToken();
-          if (!attr) {
-            break;
-          }
-          NS_ASSERTION(attr->GetTokenType() == eToken_attribute, "Weird token");
-          IF_FREE(attr, mTokenAllocator);
-        }
-
-        break;
-      }
-
-    default:
-      break;
-  }
-
-  IF_FREE(aToken, mTokenAllocator);
-  return NS_OK;
-}
-
-void
-nsSpeculativeScriptThread::AddToPrefetchList(const nsAString &src,
-                                      const nsAString &charset,
-                                      const nsAString &elementType,
-                                      PrefetchType type)
-{
-  PrefetchEntry *pe = mURIs.InsertElementAt(mNumURIs++);
-  pe->type = type;
-  pe->uri = src;
-  pe->charset = charset;
-  pe->elementType = elementType;
-
-  if (mNumURIs == kBatchPrefetchURIs) {
-    nsCOMPtr<nsIRunnable> r = new nsPreloadURIs(mURIs, this);
-
-    mNumURIs = 0;
-    mURIs.Clear();
-    NS_DispatchToMainThread(r, NS_DISPATCH_NORMAL);
-  }
-}
-
 nsICharsetAlias* nsParser::sCharsetAliasService = nsnull;
 nsICharsetConverterManager* nsParser::sCharsetConverterManager = nsnull;
 
 /**
  *  This gets called when the htmlparser module is initialized.
  */
 // static
 nsresult
@@ -796,20 +316,16 @@ nsParser::Cleanup()
     delete mParserContext;
     mParserContext = pc;
   }
 
   // It should not be possible for this flag to be set when we are getting
   // destroyed since this flag implies a pending nsParserContinueEvent, which
   // has an owning reference to |this|.
   NS_ASSERTION(!(mFlags & NS_PARSER_FLAG_PENDING_CONTINUE_EVENT), "bad");
-  if (mSpeculativeScriptThread) {
-    mSpeculativeScriptThread->StopParsing(PR_FALSE);
-    mSpeculativeScriptThread = nsnull;
-  }
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsParser)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsParser)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSink)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mObserver)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@@ -1486,36 +1002,16 @@ nsParser::DidBuildModel(nsresult anError
       //Ref. to bug 61462.
       mParserContext->mRequest = 0;
     }
   }
 
   return result;
 }
 
-void
-nsParser::SpeculativelyParse()
-{
-  if (mParserContext->mParserCommand == eViewNormal &&
-      !mParserContext->mMimeType.EqualsLiteral("text/html")) {
-    return;
-  }
-
-  if (!mSpeculativeScriptThread) {
-    mSpeculativeScriptThread = new nsSpeculativeScriptThread(&mTokenAllocator);
-    if (!mSpeculativeScriptThread) {
-      return;
-    }
-  }
-
-  nsresult rv = mSpeculativeScriptThread->StartParsing(this);
-  if (NS_FAILED(rv)) {
-    mSpeculativeScriptThread = nsnull;
-  }
-}
 
 /**
  * This method adds a new parser context to the list,
  * pushing the current one to the next position.
  *
  * @param   ptr to new context
  */
 void
@@ -1606,19 +1102,16 @@ nsParser::Terminate(void)
   mInternalState = result = NS_ERROR_HTMLPARSER_STOPPARSING;
 
   // CancelParsingEvents must be called to avoid leaking the nsParser object
   // @see bug 108049
   // If NS_PARSER_FLAG_PENDING_CONTINUE_EVENT is set then CancelParsingEvents
   // will reset it so DidBuildModel will call DidBuildModel on the DTD. Note:
   // The IsComplete() call inside of DidBuildModel looks at the pendingContinueEvents flag.
   CancelParsingEvents();
-  if (mSpeculativeScriptThread) {
-    mSpeculativeScriptThread->StopParsing(PR_FALSE);
-  }
 
   // If we got interrupted in the middle of a document.write, then we might
   // have more than one parser context on our parsercontext stack. This has
   // the effect of making DidBuildModel a no-op, meaning that we never call
   // our sink's DidBuildModel and break the reference cycle, causing a leak.
   // Since we're getting terminated, we manually clean up our context stack.
   while (mParserContext && mParserContext->mPrevContext) {
     CParserContext *prev = mParserContext->mPrevContext;
@@ -1665,20 +1158,16 @@ nsParser::ContinueInterruptedParsing()
   nsCOMPtr<nsIParser> kungFuDeathGrip(this);
 
 #ifdef DEBUG
   if (!(mFlags & NS_PARSER_FLAG_PARSER_ENABLED)) {
     NS_WARNING("Don't call ContinueInterruptedParsing on a blocked parser.");
   }
 #endif
 
-  if (mSpeculativeScriptThread) {
-    mSpeculativeScriptThread->StopParsing(PR_FALSE);
-  }
-
   PRBool isFinalChunk = mParserContext &&
                         mParserContext->mStreamListenerState == eOnStop;
 
   result = ResumeParse(PR_TRUE, isFinalChunk); // Ref. bug 57999
 
   if (result != NS_OK) {
     result=mInternalState;
   }
@@ -1801,17 +1290,16 @@ nsParser::SetCanInterrupt(PRBool aCanInt
 NS_IMETHODIMP
 nsParser::Parse(nsIURI* aURL,
                 nsIRequestObserver* aListener,
                 void* aKey,
                 nsDTDMode aMode)
 {
 
   NS_PRECONDITION(aURL, "Error: Null URL given");
-  NS_ASSERTION(!mSpeculativeScriptThread, "Can't reuse a parser like this");
 
   nsresult result=kBadURL;
   mObserver = aListener;
 
   if (aURL) {
     nsCAutoString spec;
     nsresult rv = aURL->GetSpec(spec);
     if (rv != NS_OK) {
@@ -1869,20 +1357,16 @@ nsParser::Parse(const nsAString& aSource
     // Nothing is being passed to the parser so return
     // immediately. mUnusedInput will get processed when
     // some data is actually passed in.
     // But if this is the last call, make sure to finish up
     // stuff correctly.
     return result;
   }
 
-  if (mSpeculativeScriptThread) {
-    mSpeculativeScriptThread->StopParsing(PR_TRUE);
-  }
-
   // Hack to pass on to the dtd the caller's desire to
   // parse a fragment without worrying about containment rules
   if (aMode == eDTDMode_fragment)
     mCommand = eViewFragment;
 
   // Maintain a reference to ourselves so we don't go away
   // till we're completely done.
   nsCOMPtr<nsIParser> kungFuDeathGrip(this);
@@ -1993,18 +1477,16 @@ nsParser::ParseFragment(const nsAString&
   nsresult result = NS_OK;
   nsAutoString  theContext;
   PRUint32 theCount = aTagStack.Length();
   PRUint32 theIndex = 0;
 
   // Disable observers for fragments
   mFlags &= ~NS_PARSER_FLAG_OBSERVERS_ENABLED;
 
-  NS_ASSERTION(!mSpeculativeScriptThread, "Can't reuse a parser like this");
-
   for (theIndex = 0; theIndex < theCount; theIndex++) {
     theContext.AppendLiteral("<");
     theContext.Append(aTagStack[theCount - theIndex - 1]);
     theContext.AppendLiteral(">");
   }
 
   if (theCount == 0) {
     // Ensure that the buffer is not empty. Because none of the DTDs care
@@ -2135,18 +1617,16 @@ nsParser::ResumeParse(PRBool allowIterat
 {
   nsresult result = NS_OK;
 
   if ((mFlags & NS_PARSER_FLAG_PARSER_ENABLED) &&
       mInternalState != NS_ERROR_HTMLPARSER_STOPPARSING) {
     MOZ_TIMER_DEBUGLOG(("Start: Parse Time: nsParser::ResumeParse(), this=%p\n", this));
     MOZ_TIMER_START(mParseTime);
 
-    NS_ASSERTION(!mSpeculativeScriptThread || !mSpeculativeScriptThread->Parsing(), "Bad races happening");
-
     result = WillBuildModel(mParserContext->mScanner->GetFilename());
     if (NS_FAILED(result)) {
       mFlags &= ~NS_PARSER_FLAG_CAN_TOKENIZE;
       return result;
     }
 
     if (mParserContext->mDTD) {
       mParserContext->mDTD->WillResumeParse(mSink);
@@ -2186,17 +1666,16 @@ nsParser::ResumeParse(PRBool allowIterat
         // If we're told to block the parser, we disable all further parsing
         // (and cache any data coming in) until the parser is re-enabled.
         if (NS_ERROR_HTMLPARSER_BLOCK == result) {
           if (mParserContext->mDTD) {
             mParserContext->mDTD->WillInterruptParse(mSink);
           }
 
           BlockParser();
-          SpeculativelyParse();
           return NS_OK;
         }
         if (NS_ERROR_HTMLPARSER_STOPPARSING == result) {
           // Note: Parser Terminate() calls DidBuildModel.
           if (mInternalState != NS_ERROR_HTMLPARSER_STOPPARSING) {
             DidBuildModel(mStreamStatus);
             mInternalState = result;
           }
@@ -2776,21 +2255,16 @@ nsParser::OnDataAvailable(nsIRequest *re
 
   while (theContext && theContext->mRequest != request) {
     theContext = theContext->mPrevContext;
   }
 
   if (theContext) {
     theContext->mStreamListenerState = eOnDataAvail;
 
-    if ((mFlags & NS_PARSER_FLAG_PARSER_ENABLED) &&
-        mSpeculativeScriptThread) {
-      mSpeculativeScriptThread->StopParsing(PR_FALSE);
-    }
-
     if (eInvalidDetect == theContext->mAutoDetectStatus) {
       if (theContext->mScanner) {
         nsScannerIterator iter;
         theContext->mScanner->EndReading(iter);
         theContext->mScanner->SetPosition(iter, PR_TRUE);
       }
     }
 
@@ -2825,20 +2299,16 @@ nsParser::OnDataAvailable(nsIRequest *re
  *  has been collected from the net.
  */
 nsresult
 nsParser::OnStopRequest(nsIRequest *request, nsISupports* aContext,
                         nsresult status)
 {
   nsresult rv = NS_OK;
 
-  if (mSpeculativeScriptThread) {
-    mSpeculativeScriptThread->StopParsing(PR_FALSE);
-  }
-
   if (eOnStart == mParserContext->mStreamListenerState) {
     // If you're here, then OnDataAvailable() never got called.  Prior
     // to necko, we never dealt with this case, but the problem may
     // have existed.  Everybody can live with an empty input stream, so
     // just resume parsing.
     rv = ResumeParse(PR_TRUE, PR_TRUE);
   }
 
@@ -2942,38 +2412,36 @@ nsresult nsParser::Tokenize(PRBool aIsFi
       // Reset since the tokens have been flushed.
       mFlags &= ~NS_PARSER_FLAG_FLUSH_TOKENS;
     }
 
     PRBool flushTokens = PR_FALSE;
 
     MOZ_TIMER_START(mTokenizeTime);
 
-    mParserContext->mNumConsumed = 0;
-
     WillTokenize(aIsFinalChunk);
     while (NS_SUCCEEDED(result)) {
-      mParserContext->mNumConsumed += mParserContext->mScanner->Mark();
+      mParserContext->mScanner->Mark();
       result = theTokenizer->ConsumeToken(*mParserContext->mScanner,
                                           flushTokens);
       if (NS_FAILED(result)) {
         mParserContext->mScanner->RewindToMark();
         if (kEOF == result){
           break;
         }
         if (NS_ERROR_HTMLPARSER_STOPPARSING == result) {
           result = Terminate();
           break;
         }
       } else if (flushTokens && (mFlags & NS_PARSER_FLAG_OBSERVERS_ENABLED)) {
         // I added the extra test of NS_PARSER_FLAG_OBSERVERS_ENABLED to fix Bug# 23931.
         // Flush tokens on seeing </SCRIPT> -- Ref: Bug# 22485 --
         // Also remember to update the marked position.
         mFlags |= NS_PARSER_FLAG_FLUSH_TOKENS;
-        mParserContext->mNumConsumed += mParserContext->mScanner->Mark();
+        mParserContext->mScanner->Mark();
         break;
       }
     }
     DidTokenize(aIsFinalChunk);
 
     MOZ_TIMER_STOP(mTokenizeTime);
   } else {
     result = mInternalState = NS_ERROR_HTMLPARSER_BADTOKENIZER;
--- a/parser/htmlparser/src/nsParser.h
+++ b/parser/htmlparser/src/nsParser.h
@@ -90,17 +90,16 @@
 #include "nsIUnicharStreamListener.h"
 #include "nsCycleCollectionParticipant.h"
 
 class nsICharsetConverterManager;
 class nsICharsetAlias;
 class nsIDTD;
 class nsScanner;
 class nsIProgressEventSink;
-class nsSpeculativeScriptThread;
 
 #ifdef _MSC_VER
 #pragma warning( disable : 4275 )
 #endif
 
 
 class nsParser : public nsIParser,
                  public nsIStreamListener{
@@ -402,19 +401,17 @@ class nsParser : public nsIParser,
 
     /**
      * 
      * @update	gess5/18/98
      * @param 
      * @return
      */
     nsresult DidBuildModel(nsresult anErrorCode);
-
-    void SpeculativelyParse();
-
+    
 private:
 
     /*******************************************
       These are the tokenization methods...
      *******************************************/
 
     /**
      *  Part of the code sandwich, this gets called right before
@@ -455,17 +452,16 @@ protected:
     // And now, some data members...
     //*********************************************
     
       
     CParserContext*              mParserContext;
     nsCOMPtr<nsIRequestObserver> mObserver;
     nsCOMPtr<nsIContentSink>     mSink;
     nsIRunnable*                 mContinueEvent;  // weak ref
-    nsRefPtr<nsSpeculativeScriptThread> mSpeculativeScriptThread;
    
     nsCOMPtr<nsIParserFilter> mParserFilter;
     nsTokenAllocator          mTokenAllocator;
     
     eParserCommands     mCommand;
     nsresult            mInternalState;
     PRInt32             mStreamStatus;
     PRInt32             mCharsetSource;
--- a/parser/htmlparser/src/nsScanner.cpp
+++ b/parser/htmlparser/src/nsScanner.cpp
@@ -141,25 +141,26 @@ nsScanner::nsScanner(nsString& aFilename
   mFirstNonWhitespacePosition = -1;
   mCountRemaining = 0;
 
   mUnicodeDecoder = 0;
   mCharsetSource = kCharsetUninitialized;
   SetDocumentCharset(aCharset, aSource);
 }
 
-nsresult nsScanner::SetDocumentCharset(const nsACString& aCharset , PRInt32 aSource)
-{
-  if (aSource < mCharsetSource) // priority is lower the the current one , just
-    return NS_OK;
+nsresult nsScanner::SetDocumentCharset(const nsACString& aCharset , PRInt32 aSource) {
+
+  nsresult res = NS_OK;
+
+  if( aSource < mCharsetSource) // priority is lower the the current one , just
+    return res;
 
   nsICharsetAlias* calias = nsParser::GetCharsetAliasService();
   NS_ASSERTION(calias, "Must have the charset alias service!");
 
-  nsresult res = NS_OK;
   if (!mCharset.IsEmpty())
   {
     PRBool same;
     res = calias->Equals(aCharset, mCharset, &same);
     if(NS_SUCCEEDED(res) && same)
     {
       return NS_OK; // no difference, don't change it
     }
@@ -179,18 +180,27 @@ nsresult nsScanner::SetDocumentCharset(c
     mCharset.Assign(charsetName);
   }
 
   mCharsetSource = aSource;
 
   NS_ASSERTION(nsParser::GetCharsetConverterManager(),
                "Must have the charset converter manager!");
 
-  return nsParser::GetCharsetConverterManager()->
-    GetUnicodeDecoderRaw(mCharset.get(), getter_AddRefs(mUnicodeDecoder));
+  nsIUnicodeDecoder * decoder = nsnull;
+  res = nsParser::GetCharsetConverterManager()->
+    GetUnicodeDecoderRaw(mCharset.get(), &decoder);
+  if(NS_SUCCEEDED(res) && (nsnull != decoder))
+  {
+     NS_IF_RELEASE(mUnicodeDecoder);
+
+     mUnicodeDecoder = decoder;
+  }
+
+  return res;
 }
 
 
 /**
  *  default destructor
  *  
  *  @update  gess 3/25/98
  *  @param   
@@ -198,16 +208,18 @@ nsresult nsScanner::SetDocumentCharset(c
  */
 nsScanner::~nsScanner() {
 
   if (mSlidingBuffer) {
     delete mSlidingBuffer;
   }
 
   MOZ_COUNT_DTOR(nsScanner);
+
+  NS_IF_RELEASE(mUnicodeDecoder);
 }
 
 /**
  *  Resets current offset position of input stream to marked position. 
  *  This allows us to back up to this point if the need should arise, 
  *  such as when tokenization gets interrupted.
  *  NOTE: IT IS REALLY BAD FORM TO CALL RELEASE WITHOUT CALLING MARK FIRST!
  *
@@ -227,31 +239,24 @@ void nsScanner::RewindToMark(void){
  *  Records current offset position in input stream. This allows us
  *  to back up to this point if the need should arise, such as when
  *  tokenization gets interrupted.
  *
  *  @update  gess 7/29/98
  *  @param   
  *  @return  
  */
-PRInt32 nsScanner::Mark() {
-  PRInt32 distance = 0;
+void nsScanner::Mark() {
   if (mSlidingBuffer) {
-    nsScannerIterator oldStart;
-    mSlidingBuffer->BeginReading(oldStart);
-
-    distance = Distance(oldStart, mCurrentPosition);
-
     mSlidingBuffer->DiscardPrefix(mCurrentPosition);
     mSlidingBuffer->BeginReading(mCurrentPosition);
     mMarkPosition = mCurrentPosition;
   }
-
-  return distance;
 }
+ 
 
 /** 
  * Insert data to our underlying input buffer as
  * if it were read from an input stream.
  *
  * @update  harishd 01/12/99
  * @return  error code 
  */
--- a/parser/htmlparser/src/nsScanner.h
+++ b/parser/htmlparser/src/nsScanner.h
@@ -202,17 +202,17 @@ class nsScanner {
        *  Records current offset position in input stream. This allows us
        *  to back up to this point if the need should arise, such as when
        *  tokenization gets interrupted.
        *  
        *  @update  gess 5/12/98
        *  @param   
        *  @return  
        */
-      PRInt32 Mark(void);
+      void Mark(void);
 
       /**
        *  Resets current offset position of input stream to marked position. 
        *  This allows us to back up to this point if the need should arise, 
        *  such as when tokenization gets interrupted.
        *  NOTE: IT IS REALLY BAD FORM TO CALL RELEASE WITHOUT CALLING MARK FIRST!
        *  
        *  @update  gess 5/12/98
@@ -333,18 +333,15 @@ class nsScanner {
       nsScannerIterator            mEndPosition;     // The current end of the scanner buffer
       nsString        mFilename;
       PRUint32        mCountRemaining; // The number of bytes still to be read
                                        // from the scanner buffer
       PRPackedBool    mIncremental;
       PRInt32         mFirstNonWhitespacePosition;
       PRInt32         mCharsetSource;
       nsCString       mCharset;
-      nsCOMPtr<nsIUnicodeDecoder> mUnicodeDecoder;
+      nsIUnicodeDecoder *mUnicodeDecoder;
       nsParser        *mParser;
-
-  private:
-      nsScanner &operator =(const nsScanner &); // Not implemented.
 };
 
 #endif