Back out bug 591981 since it causes bug 599583. a=backout
authorJonas Sicking <jonas@sicking.cc>
Mon, 27 Sep 2010 16:23:33 -0700
changeset 54680 c0852588831bffe8db1d2c74a421d09784ae429a
parent 54679 faf497893b2816ee72b1416690c4f9d449815497
child 54681 e6165002d0490d0809f89b61e93ea46387d670ca
push idunknown
push userunknown
push dateunknown
reviewersbackout
bugs591981, 599583
milestone2.0b7pre
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
Back out bug 591981 since it causes bug 599583. a=backout
content/base/public/nsIScriptElement.h
content/base/src/nsContentSink.cpp
content/base/src/nsScriptElement.cpp
content/base/src/nsScriptElement.h
content/base/src/nsScriptLoader.cpp
content/base/src/nsScriptLoader.h
content/base/test/test_bug28293.html
content/base/test/test_bug28293.xhtml
content/html/content/src/nsHTMLScriptElement.cpp
content/html/content/test/test_bug300691-2.html
content/svg/content/src/nsSVGScriptElement.cpp
content/test/reftest/bug591981-1.html
content/test/reftest/bug591981-2.html
content/test/reftest/bug591981-ref.html
content/test/reftest/bug591981-script.js
content/test/reftest/reftest.list
dom/tests/mochitest/bugs/child_bug260264.html
dom/tests/mochitest/bugs/grandchild_bug260264.html
dom/tests/mochitest/bugs/test_bug260264.html
dom/tests/mochitest/bugs/utils_bug260264.js
--- a/content/base/public/nsIScriptElement.h
+++ b/content/base/public/nsIScriptElement.h
@@ -40,38 +40,36 @@
 #define nsIScriptElement_h___
 
 #include "nsISupports.h"
 #include "nsIURI.h"
 #include "nsCOMPtr.h"
 #include "nsIScriptLoaderObserver.h"
 #include "nsWeakPtr.h"
 #include "nsIParser.h"
-#include "nsContentCreatorFunctions.h"
 
 #define NS_ISCRIPTELEMENT_IID \
 { 0x6d625b30, 0xfac4, 0x11de, \
 { 0x8a, 0x39, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } }
 
 /**
  * Internal interface implemented by script elements
  */
 class nsIScriptElement : public nsIScriptLoaderObserver {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTELEMENT_IID)
 
-  nsIScriptElement(PRUint32 aFromParser)
+  nsIScriptElement()
     : mLineNumber(0),
-      mAlreadyStarted(PR_FALSE),
+      mIsEvaluated(PR_FALSE),
       mMalformed(PR_FALSE),
       mDoneAddingChildren(PR_TRUE),
       mFrozen(PR_FALSE),
       mDefer(PR_FALSE),
       mAsync(PR_FALSE),
-      mParserCreated((PRUint8)aFromParser),
       mCreatorParser(nsnull)
   {
   }
 
   /**
    * Content type identifying the scripting language. Can be empty, in
    * which case javascript will be assumed.
    */
@@ -114,25 +112,16 @@ public:
    * Is the script async. Currently only supported by HTML scripts.
    */
   PRBool GetScriptAsync()
   {
     NS_PRECONDITION(mFrozen, "Not ready for this call yet!");
     return mAsync;  
   }
 
-  /**
-   * Returns a constant defined in nsContentCreatorFunctions.h. Non-zero
-   * values mean parser-created and zero means not parser-created.
-   */
-  PRUint32 GetParserCreated()
-  {
-    return mParserCreated;
-  }
-
   void SetScriptLineNumber(PRUint32 aLineNumber)
   {
     mLineNumber = aLineNumber;
   }
   PRUint32 GetScriptLineNumber()
   {
     return mLineNumber;
   }
@@ -143,25 +132,17 @@ public:
   }
   PRBool IsMalformed()
   {
     return mMalformed;
   }
 
   void PreventExecution()
   {
-    mAlreadyStarted = PR_TRUE;
-  }
-
-  void LoseParserInsertedness()
-  {
-    mFrozen = PR_FALSE;
-    mUri = nsnull;
-    mCreatorParser = nsnull;
-    mParserCreated = NS_NOT_FROM_PARSER;
+    mIsEvaluated = PR_TRUE;
   }
 
   void SetCreatorParser(nsIParser* aParser)
   {
     mCreatorParser = getter_AddRefs(NS_GetWeakReference(aParser));
   }
 
   /**
@@ -199,17 +180,17 @@ protected:
   /**
    * The start line number of the script.
    */
   PRUint32 mLineNumber;
   
   /**
    * The "already started" flag per HTML5.
    */
-  PRPackedBool mAlreadyStarted;
+  PRPackedBool mIsEvaluated;
   
   /**
    * The script didn't have an end tag.
    */
   PRPackedBool mMalformed;
   
   /**
    * False if parser-inserted but the parser hasn't triggered running yet.
@@ -227,21 +208,16 @@ protected:
   PRPackedBool mDefer;
   
   /**
    * The effective asyncness.
    */
   PRPackedBool mAsync;
   
   /**
-   * Whether this element was parser-created.
-   */
-  PRUint8 mParserCreated;
-
-  /**
    * The effective src (or null if no src).
    */
   nsCOMPtr<nsIURI> mUri;
   
   /**
    * The creator parser of a non-defer, non-async parser-inserted script.
    */
   nsWeakPtr mCreatorParser;
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -361,18 +361,18 @@ nsContentSink::ScriptAvailable(nsresult 
                                nsIScriptElement *aElement,
                                PRBool aIsInline,
                                nsIURI *aURI,
                                PRInt32 aLineNo)
 {
   PRUint32 count = mScriptElements.Count();
 
   // aElement will not be in mScriptElements if a <script> was added
-  // using the DOM during loading or if DoneAddingChildren did not return
-  // NS_ERROR_HTMLPARSER_BLOCK.
+  // using the DOM during loading, or if the script was inline and thus
+  // never blocked.
   NS_ASSERTION(count == 0 ||
                mScriptElements.IndexOf(aElement) == PRInt32(count - 1) ||
                mScriptElements.IndexOf(aElement) == -1,
                "script found at unexpected position");
 
   // Check if this is the element we were waiting for
   if (count == 0 || aElement != mScriptElements[count - 1]) {
     return NS_OK;
--- a/content/base/src/nsScriptElement.cpp
+++ b/content/base/src/nsScriptElement.cpp
@@ -173,32 +173,32 @@ nsresult
 nsScriptElement::MaybeProcessScript()
 {
   nsCOMPtr<nsIContent> cont =
     do_QueryInterface((nsIScriptElement*) this);
 
   NS_ASSERTION(cont->DebugGetSlots()->mMutationObservers.Contains(this),
                "You forgot to add self as observer");
 
-  if (mAlreadyStarted || !mDoneAddingChildren || !cont->IsInDoc() ||
+  if (mIsEvaluated || !mDoneAddingChildren || !cont->IsInDoc() ||
       mMalformed || !HasScriptContent()) {
     return NS_OK;
   }
 
   FreezeUriAsyncDefer();
 
   if (InNonScriptingContainer(cont)) {
     // Make sure to flag ourselves as evaluated
-    mAlreadyStarted = PR_TRUE;
+    mIsEvaluated = PR_TRUE;
     return NS_OK;
   }
 
   nsresult scriptresult = NS_OK;
   nsRefPtr<nsScriptLoader> loader = cont->GetOwnerDoc()->ScriptLoader();
-  mAlreadyStarted = PR_TRUE;
+  mIsEvaluated = PR_TRUE;
   scriptresult = loader->ProcessScriptElement(this);
 
   // The only error we don't ignore is NS_ERROR_HTMLPARSER_BLOCK
   // However we don't want to override other success values
   // (such as NS_CONTENT_SCRIPT_IS_EVENTHANDLER)
   if (NS_FAILED(scriptresult) &&
       scriptresult != NS_ERROR_HTMLPARSER_BLOCK) {
     scriptresult = NS_OK;
--- a/content/base/src/nsScriptElement.h
+++ b/content/base/src/nsScriptElement.h
@@ -54,21 +54,16 @@ public:
   NS_DECL_NSISCRIPTLOADEROBSERVER
 
   // nsIMutationObserver
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
 
-  nsScriptElement(PRUint32 aFromParser)
-    : nsIScriptElement(aFromParser)
-  {
-  }
-
 protected:
   // Internal methods
 
   /**
    * Check if this element contains any script, linked or inline
    */
   virtual PRBool HasScriptContent() = 0;
 
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -70,17 +70,16 @@
 #include "nsIParser.h"
 #include "nsThreadUtils.h"
 #include "nsDocShellCID.h"
 #include "nsIContentSecurityPolicy.h"
 #include "prlog.h"
 #include "nsIChannelPolicy.h"
 #include "nsChannelPolicy.h"
 #include "nsCRT.h"
-#include "nsContentCreatorFunctions.h"
 
 #include "mozilla/FunctionTimer.h"
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gCspPRLog;
 #endif
 
 using namespace mozilla::dom;
@@ -113,16 +112,17 @@ public:
 
   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;
   nsCOMPtr<nsIURI> mFinalURI;
   PRInt32 mLineNo;
 };
 
@@ -135,35 +135,31 @@ NS_IMPL_THREADSAFE_ISUPPORTS0(nsScriptLo
 //
 //////////////////////////////////////////////////////////////
 
 nsScriptLoader::nsScriptLoader(nsIDocument *aDocument)
   : mDocument(aDocument),
     mBlockerCount(0),
     mEnabled(PR_TRUE),
     mDeferEnabled(PR_FALSE),
-    mDocumentParsingDone(PR_FALSE)
+    mUnblockOnloadWhenDoneProcessing(PR_FALSE)
 {
   // enable logging for CSP
 #ifdef PR_LOGGING
   if (!gCspPRLog)
     gCspPRLog = PR_NewLogModule("CSP");
 #endif
 }
 
 nsScriptLoader::~nsScriptLoader()
 {
   mObservers.Clear();
 
-  if (mParserBlockingRequest) {
-    mParserBlockingRequest->FireScriptAvailable(NS_ERROR_ABORT);
-  }
-
-  for (PRInt32 i = 0; i < mDeferRequests.Count(); i++) {
-    mDeferRequests[i]->FireScriptAvailable(NS_ERROR_ABORT);
+  for (PRInt32 i = 0; i < mRequests.Count(); i++) {
+    mRequests[i]->FireScriptAvailable(NS_ERROR_ABORT);
   }
 
   for (PRInt32 i = 0; i < mAsyncRequests.Count(); i++) {
     mAsyncRequests[i]->FireScriptAvailable(NS_ERROR_ABORT);
   }
 
   // Unblock the kids, in case any of them moved to a different document
   // subtree in the meantime and therefore aren't actually going away.
@@ -338,33 +334,16 @@ PRBool
 nsScriptLoader::PreloadURIComparator::Equals(const PreloadInfo &aPi,
                                              nsIURI * const &aURI) const
 {
   PRBool same;
   return NS_SUCCEEDED(aPi.mRequest->mURI->Equals(aURI, &same)) &&
          same;
 }
 
-class nsScriptRequestProcessor : public nsRunnable
-{
-private:
-  nsRefPtr<nsScriptLoader> mLoader;
-  nsRefPtr<nsScriptLoadRequest> mRequest;
-public:
-  nsScriptRequestProcessor(nsScriptLoader* aLoader,
-                           nsScriptLoadRequest* aRequest)
-    : mLoader(aLoader)
-    , mRequest(aRequest)
-  {}
-  NS_IMETHODIMP Run()
-  {
-    return mLoader->ProcessRequest(mRequest);
-  }
-};
-
 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()) {
@@ -531,153 +510,145 @@ 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);
 
-  // Step 9. in the HTML5 spec
+  PRBool hadPendingRequests = !!GetFirstPendingRequest();
 
+  // Did we preload this request?
   nsCOMPtr<nsIURI> scriptURI = aElement->GetScriptURI();
   nsRefPtr<nsScriptLoadRequest> request;
   if (scriptURI) {
-    // external script
     nsTArray<PreloadInfo>::index_type i =
       mPreloads.IndexOf(scriptURI.get(), 0, PreloadURIComparator());
     if (i != nsTArray<PreloadInfo>::NoIndex) {
-      // preloaded
-      // note that a script-inserted script can steal a preload!
       request = mPreloads[i].mRequest;
       request->mElement = aElement;
-      // XXX what if the charset attribute of the element and the charset
-      // of the preload don't match?
+      request->mJSVersion = version;
+      request->mDefer = mDeferEnabled && aElement->GetScriptDeferred() &&
+        !aElement->GetScriptAsync();
       mPreloads.RemoveElementAt(i);
+
       rv = CheckContentPolicy(mDocument, aElement, request->mURI, type);
-      NS_ENSURE_SUCCESS(rv, rv);
-    } else {
-      // not preloaded
-      request = new nsScriptLoadRequest(aElement, version);
-      NS_ENSURE_TRUE(request, NS_ERROR_OUT_OF_MEMORY);
-      request->mURI = scriptURI;
-      request->mIsInline = PR_FALSE;
-      request->mLoading = PR_TRUE;
-      rv = StartLoad(request, type);
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-
-    request->mJSVersion = version;
-
-    PRBool async = !aElement->GetParserCreated() || aElement->GetScriptAsync();
+      if (NS_FAILED(rv)) {
+        // Note, we're dropping our last ref to request here.
+        return rv;
+      }
 
-    // we now have a request that may or may not be still loading
-    if (!async && aElement->GetScriptDeferred()) {
-      // We don't want to run this yet.
-      // If we come here, the script is a parser-created script and it has
-      // the defer attribute but not the async attribute. Since a
-      // a parser-inserted script is being run, we came here by the parser
-      // running the script, which means the parser is still alive and the
-      // parse is ongoing.
-      NS_ASSERTION(mDocument->GetCurrentContentSink(),
-          "Defer script on a document without an active parser; bug 592366.");
-      mDeferRequests.AppendObject(request);
-      return NS_OK;
-    }
-    if (async) {
-      mAsyncRequests.AppendObject(request);
-      if (!request->mLoading) {
-        // The script is available already. Run it ASAP when the event
-        // loop gets a chance to spin.
-        ProcessPendingRequestsAsync();
-      }
-      return NS_OK;
-    }
-    if (!request->mLoading) {
-      // The request has already been loaded. If the script comes from the
-      // network stream, cheat for performance reasons and avoid a trip
-      // through the event loop.
-      if (aElement->GetParserCreated() == NS_FROM_PARSER_NETWORK) {
+      // Can we run the script now?
+      // This is true if we're done loading, the script isn't deferred and
+      // there are either no scripts or stylesheets to wait for, or the
+      // script is async
+      PRBool readyToRun =
+        !request->mLoading && !request->mDefer &&
+        ((!hadPendingRequests && ReadyToExecuteScripts()) ||
+         aElement->GetScriptAsync());
+
+      if (readyToRun && nsContentUtils::IsSafeToRunScript()) {
         return ProcessRequest(request);
       }
-      // Otherwise, we've got a document.written script, make a trip through
-      // the event loop to hide the preload effects from the scripts on the
-      // Web page.
-      NS_ASSERTION(!mParserBlockingRequest,
-          "There can be only one parser-blocking script at a time");
-      mParserBlockingRequest = request;
-      ProcessPendingRequestsAsync();
-      return NS_ERROR_HTMLPARSER_BLOCK;
-    }
-    // The script hasn't loaded yet and is parser-inserted and non-async.
-    // It'll be executed when it has loaded.
-    NS_ASSERTION(!mParserBlockingRequest,
-        "There can be only one parser-blocking script at a time");
-    mParserBlockingRequest = request;
-    return NS_ERROR_HTMLPARSER_BLOCK;
-  }
 
-  // inline script
-  nsCOMPtr<nsIContentSecurityPolicy> csp;
-  rv = mDocument->NodePrincipal()->GetCsp(getter_AddRefs(csp));
-  NS_ENSURE_SUCCESS(rv, rv);
+      // Not done loading yet. Move into the real requests queue and wait.
+      if (aElement->GetScriptAsync()) {
+        mAsyncRequests.AppendObject(request);
+      }
+      else {
+        mRequests.AppendObject(request);
+      }
 
-  if (csp) {
-    PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("New ScriptLoader i ****with CSP****"));
-    PRBool inlineOK;
-    // this call will send violation reports when necessary
-    rv = csp->GetAllowsInlineScript(&inlineOK);
-    NS_ENSURE_SUCCESS(rv, rv);
+      if (readyToRun) {
+        nsContentUtils::AddScriptRunner(NS_NewRunnableMethod(this,
+          &nsScriptLoader::ProcessPendingRequests));
+      }
 
-    if (!inlineOK) {
-      PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("CSP blocked inline scripts (2)"));
-      return NS_ERROR_FAILURE;
+      return request->mDefer || aElement->GetScriptAsync() ?
+        NS_OK : NS_ERROR_HTMLPARSER_BLOCK;
     }
   }
 
+  // Create a request object for this script
   request = new nsScriptLoadRequest(aElement, version);
   NS_ENSURE_TRUE(request, NS_ERROR_OUT_OF_MEMORY);
-  request->mJSVersion = version;
-  request->mLoading = PR_FALSE;
-  request->mIsInline = PR_TRUE;
-  request->mURI = mDocument->GetDocumentURI();
-  request->mLineNo = aElement->GetScriptLineNumber();
+
+  // First check to see if this is an external script
+  if (scriptURI) {
+    request->mDefer = mDeferEnabled && aElement->GetScriptDeferred() &&
+      !aElement->GetScriptAsync();
+    request->mURI = scriptURI;
+    request->mIsInline = PR_FALSE;
+    request->mLoading = PR_TRUE;
+
+    rv = StartLoad(request, type);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+  } else {
+    // in-line script
+    nsCOMPtr<nsIContentSecurityPolicy> csp;
+    nsresult rv = mDocument->NodePrincipal()->GetCsp(getter_AddRefs(csp));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    if (csp) {
+      PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("New ScriptLoader i ****with CSP****"));
+      PRBool inlineOK;
+      // this call will send violation reports when necessary
+      rv = csp->GetAllowsInlineScript(&inlineOK);
+      NS_ENSURE_SUCCESS(rv, rv);
 
-  if (aElement->GetParserCreated() == NS_NOT_FROM_PARSER) {
-    NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
-        "A script-inserted script is inserted without an update batch?");
-    nsContentUtils::AddScriptRunner(new nsScriptRequestProcessor(this,
-                                                                 request));
+      if (!inlineOK) {
+        PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("CSP blocked inline scripts (2)"));
+        return NS_ERROR_FAILURE;
+      }
+    }
+
+    request->mDefer = PR_FALSE;
+    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
+    // to this list.
+    if (!hadPendingRequests && ReadyToExecuteScripts() &&
+        nsContentUtils::IsSafeToRunScript()) {
+      return ProcessRequest(request);
+    }
+  }
+
+  // Add the request to our requests list
+  NS_ENSURE_TRUE(aElement->GetScriptAsync() ?
+                 mAsyncRequests.AppendObject(request) :
+                 mRequests.AppendObject(request),
+                 NS_ERROR_OUT_OF_MEMORY);
+
+  if (request->mDefer || aElement->GetScriptAsync()) {
     return NS_OK;
   }
-  if (aElement->GetParserCreated() == NS_FROM_PARSER_NETWORK &&
-      !ReadyToExecuteScripts()) {
-    NS_ASSERTION(!mParserBlockingRequest,
-        "There can be only one parser-blocking script at a time");
-    mParserBlockingRequest = request;
-    return NS_ERROR_HTMLPARSER_BLOCK;
+
+  // If there weren't any pending requests before, and this one is
+  // ready to execute, do that as soon as it's safe.
+  if (!request->mLoading && !hadPendingRequests && ReadyToExecuteScripts()) {
+    nsContentUtils::AddScriptRunner(NS_NewRunnableMethod(this,
+      &nsScriptLoader::ProcessPendingRequests));
   }
-  // We now have a document.written inline script or we have an inline script
-  // from the network but there is no style sheet that is blocking scripts.
-  // Don't check for style sheets blocking scripts in the document.write
-  // case to avoid style sheet network activity affecting when
-  // document.write returns. It's not really necessary to do this if
-  // there's no document.write currently on the call stack. However,
-  // this way matches IE more closely than checking if document.write
-  // is on the call stack.
-  NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
-      "Not safe to run a parser-inserted script?");
-  return ProcessRequest(request);
+
+  // Added as pending request, now we can send blocking back
+  return NS_ERROR_HTMLPARSER_BLOCK;
 }
 
 nsresult
 nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest)
 {
-  NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
-               "Processing requests when running scripts is unsafe.");
+  NS_ASSERTION(ReadyToExecuteScripts() && nsContentUtils::IsSafeToRunScript(),
+               "Caller forgot to check ReadyToExecuteScripts()");
 
   NS_ENSURE_ARG(aRequest);
   nsAFlatString* script;
   nsAutoString textData;
 
   NS_TIME_FUNCTION;
 
   nsCOMPtr<nsIDocument> doc;
@@ -828,71 +799,81 @@ nsScriptLoader::EvaluateScript(nsScriptL
   if (stid == nsIProgrammingLanguage::JAVASCRIPT) {
     NS_ASSERTION(!::JS_IsExceptionPending(cx),
                  "JS_ReportPendingException wasn't called");
     ::JS_EndRequest(cx);
   }
   return rv;
 }
 
+nsScriptLoadRequest*
+nsScriptLoader::GetFirstPendingRequest()
+{
+  for (PRInt32 i = 0; i < mRequests.Count(); ++i) {
+    if (!mRequests[i]->mDefer) {
+      return mRequests[i];
+    }
+  }
+
+  return nsnull;
+}
+
 void
 nsScriptLoader::ProcessPendingRequestsAsync()
 {
-  if (mParserBlockingRequest || !mPendingChildLoaders.IsEmpty()) {
+  if (GetFirstPendingRequest() || !mPendingChildLoaders.IsEmpty()) {
     nsCOMPtr<nsIRunnable> ev = NS_NewRunnableMethod(this,
       &nsScriptLoader::ProcessPendingRequests);
 
     NS_DispatchToCurrentThread(ev);
   }
 }
 
 void
 nsScriptLoader::ProcessPendingRequests()
 {
-  nsCOMPtr<nsScriptLoadRequest> request;
-  if (mParserBlockingRequest &&
-      !mParserBlockingRequest->mLoading &&
-      ReadyToExecuteScripts()) {
-    request.swap(mParserBlockingRequest);
-    // nsContentSink::ScriptAvailable unblocks the parser
-    ProcessRequest(request);
-  }
+  while (1) {
+    nsRefPtr<nsScriptLoadRequest> request;
+    if (ReadyToExecuteScripts()) {
+      request = GetFirstPendingRequest();
+      if (request && !request->mLoading) {
+        mRequests.RemoveObject(request);
+      }
+      else {
+        request = nsnull;
+      }
+    }
 
-  PRInt32 i = 0;
-  while (mEnabled && i < mAsyncRequests.Count()) {
-    if (!mAsyncRequests[i]->mLoading) {
-      request = mAsyncRequests[i];
-      mAsyncRequests.RemoveObjectAt(i);
-      ProcessRequest(request);
-      continue;
+    for (PRInt32 i = 0;
+         !request && mEnabled && i < mAsyncRequests.Count();
+         ++i) {
+      if (!mAsyncRequests[i]->mLoading) {
+        request = mAsyncRequests[i];
+        mAsyncRequests.RemoveObjectAt(i);
+      }
     }
-    ++i;
-  }
 
-  if (mDocumentParsingDone) {
-    while (mDeferRequests.Count() && !mDeferRequests[0]->mLoading) {
-      request = mDeferRequests[0];
-      mDeferRequests.RemoveObjectAt(0);
-      ProcessRequest(request);
-    }
+    if (!request)
+      break;
+
+    ProcessRequest(request);
   }
 
   while (!mPendingChildLoaders.IsEmpty() && ReadyToExecuteScripts()) {
     nsRefPtr<nsScriptLoader> child = mPendingChildLoaders[0];
     mPendingChildLoaders.RemoveElementAt(0);
     child->RemoveExecuteBlocker();
   }
 
-  if (mDocumentParsingDone && mDocument &&
-      !mParserBlockingRequest && !mAsyncRequests.Count() &&
-      !mDeferRequests.Count()) {
+  if (mUnblockOnloadWhenDoneProcessing && mDocument &&
+      !GetFirstPendingRequest() && !mAsyncRequests.Count()) {
     // No more pending scripts; time to unblock onload.
     // OK to unblock onload synchronously here, since callers must be
     // prepared for the world changing anyway.
-    mDocumentParsingDone = PR_FALSE;
+    mUnblockOnloadWhenDoneProcessing = PR_FALSE;
     mDocument->UnblockOnload(PR_TRUE);
   }
 }
 
 PRBool
 nsScriptLoader::ReadyToExecuteScripts()
 {
   // Make sure the SelfReadyToExecuteScripts check is first, so that
@@ -1047,23 +1028,19 @@ 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 (mDeferRequests.RemoveObject(request) ||
+    if (mRequests.RemoveObject(request) ||
         mAsyncRequests.RemoveObject(request)) {
       FireScriptAvailable(rv, request);
-    } else if (mParserBlockingRequest == request) {
-      mParserBlockingRequest = nsnull;
-      // nsContentSink::ScriptAvailable unblocks the parser
-      FireScriptAvailable(rv, request);
     } else {
       mPreloads.RemoveElement(request, PreloadRequestComparator());
     }
   }
 
   // Process our request and/or any pending ones
   ProcessPendingRequests();
 
@@ -1124,20 +1101,19 @@ nsScriptLoader::PrepareLoadedRequest(nsS
       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(mDeferRequests.IndexOf(aRequest) >= 0 ||
+  NS_ASSERTION(mRequests.IndexOf(aRequest) >= 0 ||
                mAsyncRequests.IndexOf(aRequest) >= 0 ||
-               mPreloads.Contains(aRequest, PreloadRequestComparator()) ||
-               mParserBlockingRequest,
+               mPreloads.Contains(aRequest, PreloadRequestComparator()),
                "aRequest should be pending!");
 
   // Mark this as loaded
   aRequest->mLoading = PR_FALSE;
 
   return NS_OK;
 }
 
@@ -1172,23 +1148,25 @@ nsScriptLoader::ShouldExecuteScript(nsID
 }
 
 void
 nsScriptLoader::ParsingComplete(PRBool aTerminated)
 {
   if (mDeferEnabled) {
     // Have to check because we apparently get ParsingComplete
     // without BeginDeferringScripts in some cases
-    mDocumentParsingDone = PR_TRUE;
+    mUnblockOnloadWhenDoneProcessing = PR_TRUE;
   }
   mDeferEnabled = PR_FALSE;
   if (aTerminated) {
-    mDeferRequests.Clear();
-    mAsyncRequests.Clear();
-    mParserBlockingRequest = nsnull;
+    mRequests.Clear();
+  } else {
+    for (PRUint32 i = 0; i < (PRUint32)mRequests.Count(); ++i) {
+      mRequests[i]->mDefer = PR_FALSE;
+    }
   }
 
   // Have to call this even if aTerminated so we'll correctly unblock
   // onload and all.
   ProcessPendingRequests();
 }
 
 void
@@ -1198,16 +1176,18 @@ nsScriptLoader::PreloadURI(nsIURI *aURI,
   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
@@ -55,17 +55,16 @@
 class nsScriptLoadRequest;
 
 //////////////////////////////////////////////////////////////
 // Script loader implementation
 //////////////////////////////////////////////////////////////
 
 class nsScriptLoader : public nsIStreamLoaderObserver
 {
-  friend class nsScriptRequestProcessor;
 public:
   nsScriptLoader(nsIDocument* aDocument);
   virtual ~nsScriptLoader();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSISTREAMLOADEROBSERVER
 
   /**
@@ -220,30 +219,30 @@ public:
    */
   void ParsingComplete(PRBool aTerminated);
 
   /**
    * Returns the number of pending scripts, deferred or not.
    */
   PRUint32 HasPendingOrCurrentScripts()
   {
-    return mCurrentScript || mParserBlockingRequest;
+    return mCurrentScript || GetFirstPendingRequest();
   }
 
   /**
    * 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);
 
-private:
+protected:
   /**
    * Helper function to check the content policy for a given request.
    */
   static nsresult CheckContentPolicy(nsIDocument* aDocument,
                                      nsISupports *aContext,
                                      nsIURI *aURI,
                                      const nsAString &aType);
 
@@ -290,21 +289,23 @@ private:
                           const nsAFlatString& aScript);
 
   nsresult PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
                                 nsIStreamLoader* aLoader,
                                 nsresult aStatus,
                                 PRUint32 aStringLen,
                                 const PRUint8* aString);
 
+  // Returns the first pending (non deferred) request
+  nsScriptLoadRequest* GetFirstPendingRequest();
+
   nsIDocument* mDocument;                   // [WEAK]
   nsCOMArray<nsIScriptLoaderObserver> mObservers;
+  nsCOMArray<nsScriptLoadRequest> mRequests;
   nsCOMArray<nsScriptLoadRequest> mAsyncRequests;
-  nsCOMArray<nsScriptLoadRequest> mDeferRequests;
-  nsCOMPtr<nsScriptLoadRequest> mParserBlockingRequest;
 
   // In mRequests, the additional information here is stored by the element.
   struct PreloadInfo {
     nsRefPtr<nsScriptLoadRequest> mRequest;
     nsString mCharset;
   };
 
   struct PreloadRequestComparator {
@@ -320,12 +321,12 @@ private:
   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;
-  PRPackedBool mDocumentParsingDone;
+  PRPackedBool mUnblockOnloadWhenDoneProcessing;
 };
 
 #endif //__nsScriptLoader_h__
--- a/content/base/test/test_bug28293.html
+++ b/content/base/test/test_bug28293.html
@@ -4,42 +4,46 @@
 https://bugzilla.mozilla.org/show_bug.cgi?id=28293
 -->
 <head>
   <title>Test for Bug 28293</title>
   <script type="text/javascript" src="/MochiKit/packed.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   <script>
-scriptInsertedExternalExecuted = false;
 res = 'A';
 
 SimpleTest.waitForExplicitFinish();
 onload = function () {
 
   res+='2';
 
   s = document.createElement('script');
   s.textContent="res+='g';";
   s.defer = true;
   document.body.appendChild(s);
 
   res+='3';
 
   s = document.createElement('script');
+  s.src="file_bug28293.sjs?res+='h';";
+  s.defer = true;
+  document.body.appendChild(s);
+
+  s = document.createElement('script');
   s.textContent="res+='i';done()";
   s.defer = true;
   document.body.appendChild(s);
 
   res+='4';
 }
 
 function done() {
-  is(res, "AacBCDEFGeHIJb1M2g3i", "scripts executed in the wrong order");
-  ok(scriptInsertedExternalExecuted, "Dynamic script did not block load");
+  is(res, "AacBCDEFGeHIJfbd1M2g34hi", "scripts executed in the wrong order");
+  ok(!fHadExecuted, "Dynamic script executed too late");
   SimpleTest.finish();
 }
 </script>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=28293">Mozilla Bug 28293</a>
 
 <script defer>
@@ -51,16 +55,21 @@ res += 'c';
 </script>
 <script>
 res += 'B';
 </script>
 <script>
 res += 'C';
 
 s = document.createElement('script');
+s.src="file_bug28293.sjs?res+='d';";
+s.defer = true;
+document.body.appendChild(s);
+
+s = document.createElement('script');
 s.textContent="res+='D';";
 document.body.appendChild(s);
 
 res += 'E';
 </script>
 <script>
 res += 'F';
 document.addEventListener("DOMContentLoaded", function() {
@@ -73,15 +82,18 @@ res += 'G';
 </script>
 <script defer>
 res += 'e';
 </script>
 <script src="file_bug28293.sjs?res+='H';"></script>
 <script>
 res += 'I';
 s = document.createElement('script');
-s.src="file_bug28293.sjs?scriptInsertedExternalExecuted=true;";
+s.src="file_bug28293.sjs?fHadExecuted=(res.indexOf('f')>=0);";
 document.body.appendChild(s);
 res += 'J';
 </script>
+<script defer>
+res += 'f';
+</script>
 
 </body>
 </html>
--- a/content/base/test/test_bug28293.xhtml
+++ b/content/base/test/test_bug28293.xhtml
@@ -3,42 +3,46 @@
 https://bugzilla.mozilla.org/show_bug.cgi?id=28293
 -->
 <head>
   <title>Test for Bug 28293</title>
   <script type="text/javascript" src="/MochiKit/packed.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
   <script>
-scriptInsertedExternalExecuted = false;
 res = 'A';
 
 SimpleTest.waitForExplicitFinish();
 onload = function () {
 
   res+='2';
 
   s = document.createElement('script');
   s.textContent="res+='g';";
   s.defer = true;
   document.body.appendChild(s);
 
   res+='3';
 
   s = document.createElement('script');
+  s.src="file_bug28293.sjs?res+='h';";
+  s.defer = true;
+  document.body.appendChild(s);
+
+  s = document.createElement('script');
   s.textContent="res+='i';done()";
   s.defer = true;
   document.body.appendChild(s);
 
   res+='4';
 }
 
 function done() {
-  is(res, "AacBCDEFGeHIJb1M2g3i", "scripts executed in the wrong order");
-  ok(scriptInsertedExternalExecuted, "Dynamic script did not block load");
+  is(res, "AacBCDEFGeHIJfbd1M2g34hi", "scripts executed in the wrong order");
+  ok(!fHadExecuted, "Dynamic script executed too late");
   SimpleTest.finish();
 }
 </script>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=28293">Mozilla Bug 28293</a>
 
 <script defer="defer">
@@ -50,16 +54,21 @@ res += 'c';
 </script>
 <script>
 res += 'B';
 </script>
 <script>
 res += 'C';
 
 s = document.createElement('script');
+s.src="file_bug28293.sjs?res+='d';";
+s.defer = true;
+document.body.appendChild(s);
+
+s = document.createElement('script');
 s.textContent="res+='D';";
 document.body.appendChild(s);
 
 res += 'E';
 </script>
 <script>
 res += 'F';
 document.addEventListener("DOMContentLoaded", function() {
@@ -73,16 +82,19 @@ res += 'G';
 <script defer="defer">
 res += 'e';
 </script>
 <script src="file_bug28293.sjs?res+='H';"></script>
 <script>
 <![CDATA[
 res += 'I';
 s = document.createElement('script');
-s.src="file_bug28293.sjs?scriptInsertedExternalExecuted=true;";
+s.src="file_bug28293.sjs?fHadExecuted=(res.indexOf('f')>=0);";
 document.body.appendChild(s);
 res += 'J';
 ]]>
 </script>
+<script defer="defer">
+res += 'f';
+</script>
 
 </body>
 </html>
--- a/content/html/content/src/nsHTMLScriptElement.cpp
+++ b/content/html/content/src/nsHTMLScriptElement.cpp
@@ -358,17 +358,16 @@ protected:
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Script)
 
 
 nsHTMLScriptElement::nsHTMLScriptElement(already_AddRefed<nsINodeInfo> aNodeInfo,
                                          PRUint32 aFromParser)
   : nsGenericHTMLElement(aNodeInfo)
-  , nsScriptElement(aFromParser)
 {
   mDoneAddingChildren = !aFromParser;
   AddMutationObserver(this);
 }
 
 nsHTMLScriptElement::~nsHTMLScriptElement()
 {
 }
@@ -424,17 +423,17 @@ nsHTMLScriptElement::Clone(nsINodeInfo *
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   nsCOMPtr<nsINode> kungFuDeathGrip = it;
   nsresult rv = CopyInnerTo(it);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // The clone should be marked evaluated if we are.
-  it->mAlreadyStarted = mAlreadyStarted;
+  it->mIsEvaluated = mIsEvaluated;
   it->mLineNumber = mLineNumber;
   it->mMalformed = mMalformed;
 
   kungFuDeathGrip.swap(*aResult);
 
   return NS_OK;
 }
 
@@ -473,20 +472,21 @@ nsHTMLScriptElement::SetInnerHTML(const 
   return nsContentUtils::SetNodeTextContent(this, aInnerHTML, PR_TRUE);
 }
 
 nsresult
 nsHTMLScriptElement::DoneAddingChildren(PRBool aHaveNotified)
 {
   mDoneAddingChildren = PR_TRUE;
   nsresult rv = MaybeProcessScript();
-  if (!mAlreadyStarted) {
-    // Need to lose parser-insertedness here to allow another script to cause
+  if (!mIsEvaluated) {
+    // Need to thaw the script uri here to allow another script to cause
     // execution later.
-    LoseParserInsertedness();
+    mFrozen = PR_FALSE;
+    mUri = nsnull;
   }
   return rv;
 }
 
 PRBool
 nsHTMLScriptElement::IsDoneAddingChildren()
 {
   return mDoneAddingChildren;
@@ -550,17 +550,17 @@ nsHTMLScriptElement::MaybeProcessScript(
 {
   nsresult rv = nsScriptElement::MaybeProcessScript();
   if (rv == NS_CONTENT_SCRIPT_IS_EVENTHANDLER) {
     // Don't return NS_CONTENT_SCRIPT_IS_EVENTHANDLER since callers can't deal
     rv = NS_OK;
 
     // We tried to evaluate the script but realized it was an eventhandler
     // mEvaluated will already be set at this point
-    NS_ASSERTION(mAlreadyStarted, "should have set mIsEvaluated already");
+    NS_ASSERTION(mIsEvaluated, "should have set mIsEvaluated already");
     NS_ASSERTION(!mScriptEventHandler, "how could we have an SEH already?");
 
     mScriptEventHandler = new nsHTMLScriptEventHandler(this);
     NS_ENSURE_TRUE(mScriptEventHandler, NS_ERROR_OUT_OF_MEMORY);
 
     nsAutoString event_val;
     GetAttr(kNameSpaceID_None, nsGkAtoms::event, event_val);
     mScriptEventHandler->ParseEventString(event_val);
--- a/content/html/content/test/test_bug300691-2.html
+++ b/content/html/content/test/test_bug300691-2.html
@@ -4,25 +4,24 @@
 https://bugzilla.mozilla.org/show_bug.cgi?id=300691
 -->
 <head>
   <title>Test for Bug 300691</title>
   <script type="text/javascript" src="/MochiKit/packed.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
-<body onload="done();">
+<body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=300691">Mozilla Bug 300691</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="text/javascript">
-  SimpleTest.waitForExplicitFinish();
   // First, setup.  We'll be toggling these variables as we go.
   var test1Ran = false;
   var test2Ran = false;
   var test3Ran = false;
   var test4Ran = false;
   var test5Ran = false;
   var test6Ran = false;
   var test7Ran = false;
@@ -108,17 +107,16 @@ https://bugzilla.mozilla.org/show_bug.cg
   $("test8").insertBefore(document.createTextNode("test8Ran = true"),
                           $("test8").firstChild);
   is(test8Ran, true, "Should be 8!");
 
   $("test9").firstChild.data = "test9Ran = true";
   is(test9Ran, true, "Should be 9!");
 </script>
 <script type="text/javascript">
-function done() {
   is(test1Ran, true, "Should have run!");
   is(test3Ran, false, "Already executed test3 script once");
   is(test4Ran, false,
      "Should have executed whitespace-only script already");
   is(test5Ran, false,
      "Should have executed once the whitespace node was added");
   is(test6Ran, false,
      "Should have executed once the whitespace node was added 2");
@@ -127,15 +125,13 @@ function done() {
   is(test12Ran, true, "Setting src should execute script");
   is(test13Ran, true, "Setting src attribute should execute script");
   is(test14aRan, true, "src attribute takes precedence over inline content");
   is(test14bRan, false, "src attribute takes precedence over inline content 2");
   is(test15aRan, true,
      "src attribute load should have started before the attribute got removed");
   is(test15bRan, false,
      "src attribute still got executed, so this shouldn't have been");
-  SimpleTest.finish();
-}
 </script>
 </pre>
 </body>
 </html>
 
--- a/content/svg/content/src/nsSVGScriptElement.cpp
+++ b/content/svg/content/src/nsSVGScriptElement.cpp
@@ -130,17 +130,16 @@ NS_INTERFACE_TABLE_HEAD(nsSVGScriptEleme
 NS_INTERFACE_MAP_END_INHERITING(nsSVGScriptElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGScriptElement::nsSVGScriptElement(already_AddRefed<nsINodeInfo> aNodeInfo,
                                        PRUint32 aFromParser)
   : nsSVGScriptElementBase(aNodeInfo)
-  , nsScriptElement(aFromParser)
 {
   mDoneAddingChildren = !aFromParser;
   AddMutationObserver(this);
 }
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
@@ -156,17 +155,17 @@ nsSVGScriptElement::Clone(nsINodeInfo *a
   }
 
   nsCOMPtr<nsINode> kungFuDeathGrip = it;
   nsresult rv = it->Init();
   rv |= CopyInnerTo(it);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // The clone should be marked evaluated if we are.
-  it->mAlreadyStarted = mAlreadyStarted;
+  it->mIsEvaluated = mIsEvaluated;
   it->mLineNumber = mLineNumber;
   it->mMalformed = mMalformed;
 
   kungFuDeathGrip.swap(*aResult);
 
   return NS_OK;
 }
 
@@ -274,20 +273,21 @@ nsSVGScriptElement::GetStringInfo()
 //----------------------------------------------------------------------
 // nsIContent methods
 
 nsresult
 nsSVGScriptElement::DoneAddingChildren(PRBool aHaveNotified)
 {
   mDoneAddingChildren = PR_TRUE;
   nsresult rv = MaybeProcessScript();
-  if (!mAlreadyStarted) {
-    // Need to lose parser-insertedness here to allow another script to cause
+  if (!mIsEvaluated) {
+    // Need to thaw the script uri here to allow another script to cause
     // execution later.
-    LoseParserInsertedness();
+    mFrozen = PR_FALSE;
+    mUri = nsnull;
   }
   return rv;
 }
 
 PRBool
 nsSVGScriptElement::IsDoneAddingChildren()
 {
   return mDoneAddingChildren;
deleted file mode 100644
--- a/content/test/reftest/bug591981-1.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<title>Script-inserted script</title>
-</head>
-<body>
-<div></div>
-<script>
-function log(text) {
-  var p = document.createElement("p");
-  p.appendChild(document.createTextNode(text));
-  document.getElementsByTagName("div")[0].appendChild(p);
-}
-
-var head = document.getElementsByTagName("head")[0];
-
-var external = document.createElement("script");
-external.src = "bug591981-script.js";
-head.insertBefore(external, head.firstChild); // what jQuery does
-
-var internal = document.createElement("script");
-var data = "log('internal')";
-try {
-  internal.text = data;
-} catch(e) {
-  internal.appendChild(document.createTextNode(data));
-}
-head.insertBefore(internal, head.firstChild); // what jQuery does
-
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/content/test/reftest/bug591981-2.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<title>Script trying to execute parser-inserted non-executed scripts</title>
-</head>
-<body>
-<div></div>
-<script></script>
-<script></script>
-<script>
-function log(text) {
-  var p = document.createElement("p");
-  p.appendChild(document.createTextNode(text));
-  document.getElementsByTagName("div")[0].appendChild(p);
-}
-
-var head = document.getElementsByTagName("head")[0];
-
-var external = document.getElementsByTagName("script")[0];
-external.src = "bug591981-script.js";
-
-var internal = document.getElementsByTagName("script")[1];
-var data = "log('internal')";
-try {
-  internal.text = data;
-} catch(e) {
-  internal.appendChild(document.createTextNode(data));
-}
-
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/content/test/reftest/bug591981-ref.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<title>Script-inserted script</title>
-</head>
-<body>
-<div><p>internal</p><p>external</p></div>
-</body>
-</html>
deleted file mode 100644
--- a/content/test/reftest/bug591981-script.js
+++ /dev/null
@@ -1,1 +0,0 @@
-log("external");
--- a/content/test/reftest/reftest.list
+++ b/content/test/reftest/reftest.list
@@ -1,8 +1,6 @@
 == bug453105.html bug453105-ref.html
 == optiontext.html optiontext-ref.html
 == bug456008.xhtml bug456008-ref.html
 == bug439965.html bug439965-ref.html
 == bug427779.xml bug427779-ref.xml
 == bug559996.html bug559996-ref.html
-== bug591981-1.html bug591981-ref.html
-== bug591981-2.html bug591981-ref.html
--- a/dom/tests/mochitest/bugs/child_bug260264.html
+++ b/dom/tests/mochitest/bugs/child_bug260264.html
@@ -1,11 +1,10 @@
 <html>
   <head>
-    <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
     <script type="application/javascript" src="utils_bug260264.js"></script>
   </head>
   <body>
     <iframe id="frame"></iframe>
     <script type="application/javascript">
       document.getElementById("frame").src =
         alter_file(alter_host(location.href, "mochi.test:8888"),
                    "grandchild_bug260264.html");
--- a/dom/tests/mochitest/bugs/grandchild_bug260264.html
+++ b/dom/tests/mochitest/bugs/grandchild_bug260264.html
@@ -1,11 +1,10 @@
 <html>
   <head>
-    <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
     <script type="application/javascript" src="utils_bug260264.js"></script>
   </head>
   <body>
     <a id="nested link" href="javascript:(function(){})()">nested link</a>
     <script type="application/javascript">
       var event = location.hash.split("#").pop();
       send(document.getElementById("nested link"), event, function() {
         var popup = window.open("http://example.com"),
--- a/dom/tests/mochitest/bugs/test_bug260264.html
+++ b/dom/tests/mochitest/bugs/test_bug260264.html
@@ -2,17 +2,16 @@
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=260264
 -->
 <head>
   <title>Test for Bug 260264</title>
   <script type="application/javascript" src="/MochiKit/packed.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <script type="application/javascript" src="utils_bug260264.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=260264">Mozilla Bug 260264</a>
 <p id="display">
   <a id="link" href="javascript:(function(){})()">link</a>
 </p>
--- a/dom/tests/mochitest/bugs/utils_bug260264.js
+++ b/dom/tests/mochitest/bugs/utils_bug260264.js
@@ -1,8 +1,15 @@
+(function() {
+  // For sendMouseEvent:
+  document.getElementsByTagName("head").item(0)
+    .appendChild(document.createElement("script")).src =
+      "/tests/SimpleTest/EventUtils.js";
+})();
+
 /**
  * Dispatches |handler| to |element|, as if fired in response to |event|.
  */
 function send(element, event, handler) {
   function unique_handler() { return handler.apply(this, arguments) }
   element.addEventListener(event, unique_handler, false);
   try { sendMouseEvent({ type: event }, element.id) }
   finally { element.removeEventListener(event, unique_handler, false) }