Bug 1513014 - Defer reporting errors while preloading until the request is actually used r=smaug
authorJon Coppeard <jcoppeard@mozilla.com>
Thu, 24 Jan 2019 14:57:30 +0000
changeset 512425 a68a2da104f324b649563af809965d87e8db7791
parent 512424 2ab90d1a0e614223e6be7ee0bdfe76cf7bd9a166
child 512432 82d47da67b4dfe32998f5e443d16530adc1daf0e
push id10566
push userarchaeopteryx@coole-files.de
push dateMon, 28 Jan 2019 12:41:12 +0000
treeherdermozilla-beta@69a3d7c8d04b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1513014
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1513014 - Defer reporting errors while preloading until the request is actually used r=smaug
dom/script/ModuleLoadRequest.cpp
dom/script/ScriptLoadRequest.cpp
dom/script/ScriptLoadRequest.h
dom/script/ScriptLoader.cpp
dom/script/ScriptLoader.h
--- a/dom/script/ModuleLoadRequest.cpp
+++ b/dom/script/ModuleLoadRequest.cpp
@@ -151,27 +151,35 @@ void ModuleLoadRequest::ModuleLoaded() {
     ModuleErrored();
     return;
   }
 
   mLoader->StartFetchingModuleDependencies(this);
 }
 
 void ModuleLoadRequest::ModuleErrored() {
+  if (IsCanceled()) {
+    return;
+  }
+
   LOG(("ScriptLoadRequest (%p): Module errored", this));
 
   mLoader->CheckModuleDependenciesLoaded(this);
   MOZ_ASSERT(!mModuleScript || mModuleScript->HasParseError());
 
   CancelImports();
   SetReady();
   LoadFinished();
 }
 
 void ModuleLoadRequest::DependenciesLoaded() {
+  if (IsCanceled()) {
+    return;
+  }
+
   // The module and all of its dependencies have been successfully fetched and
   // compiled.
 
   LOG(("ScriptLoadRequest (%p): Module dependencies loaded", this));
 
   MOZ_ASSERT(mModuleScript);
 
   mLoader->CheckModuleDependenciesLoaded(this);
--- a/dom/script/ScriptLoadRequest.cpp
+++ b/dom/script/ScriptLoadRequest.cpp
@@ -86,17 +86,18 @@ ScriptLoadRequest::ScriptLoadRequest(Scr
       mFetchOptions(aFetchOptions),
       mOffThreadToken(nullptr),
       mScriptTextLength(0),
       mScriptBytecode(),
       mBytecodeOffset(0),
       mURI(aURI),
       mLineNo(1),
       mIntegrity(aIntegrity),
-      mReferrer(aReferrer) {
+      mReferrer(aReferrer),
+      mUnreportedPreloadError(NS_OK) {
   MOZ_ASSERT(mFetchOptions);
 }
 
 ScriptLoadRequest::~ScriptLoadRequest() {
   // We should always clean up any off-thread script parsing resources.
   MOZ_ASSERT(!mOffThreadToken);
 
   // But play it safe in release builds and try to clean them up here
--- a/dom/script/ScriptLoadRequest.h
+++ b/dom/script/ScriptLoadRequest.h
@@ -234,36 +234,36 @@ class ScriptLoadRequest
   void SetScript(JSScript* aScript);
 
   void MaybeCancelOffThreadScript();
   void DropBytecodeCacheReferences();
 
   using super::getNext;
   using super::isInList;
 
-  const ScriptKind
-      mKind;  // Whether this is a classic script or a module script.
+  const ScriptKind mKind;  // Whether this is a classic script or a module
+                           // script.
   ScriptMode mScriptMode;  // Whether this is a blocking, defer or async script.
   Progress mProgress;      // Are we still waiting for a load to complete?
   DataType mDataType;      // Does this contain Source or Bytecode?
   bool mScriptFromHead;    // Synchronous head script block loading of other non
                            // js/css content.
   bool mIsInline;          // Is the script inline or loaded?
   bool mHasSourceMapURL;   // Does the HTTP header have a source map url?
   bool mInDeferList;       // True if we live in mDeferRequests.
   bool mInAsyncList;       // True if we live in mLoadingAsyncRequests or
                            // mLoadedAsyncRequests.
   bool mIsNonAsyncScriptInserted;  // True if we live in
                                    // mNonAsyncExternalScriptInsertedRequests
   bool mIsXSLT;                    // True if we live in mXSLTRequests.
   bool mIsCanceled;                // True if we have been explicitly canceled.
-  bool
-      mWasCompiledOMT;  // True if the script has been compiled off main thread.
-  bool mIsTracking;  // True if the script comes from a source on our tracking
-                     // protection list.
+  bool mWasCompiledOMT;    // True if the script has been compiled off main
+                           // thread.
+  bool mIsTracking;        // True if the script comes from a source on our
+                           // tracking protection list.
 
   RefPtr<ScriptFetchOptions> mFetchOptions;
 
   JS::OffThreadToken* mOffThreadToken;  // Off-thread parsing token.
   nsString mSourceMapURL;  // Holds source map url for loaded scripts
 
   // Holds the top-level JSScript that corresponds to the current source, once
   // it is parsed, and planned to be saved in the bytecode cache.
@@ -292,16 +292,20 @@ class ScriptLoadRequest
   const nsCOMPtr<nsIURI> mReferrer;
 
   // Holds the Cache information, which is used to register the bytecode
   // on the cache entry, such that we can load it the next time.
   nsCOMPtr<nsICacheInfoChannel> mCacheInfo;
 
   // The base URL used for resolving relative module imports.
   nsCOMPtr<nsIURI> mBaseURL;
+
+  // For preload requests, we defer reporting errors to the console until the
+  // request is used.
+  nsresult mUnreportedPreloadError;
 };
 
 class ScriptLoadRequestList : private mozilla::LinkedList<ScriptLoadRequest> {
   typedef mozilla::LinkedList<ScriptLoadRequest> super;
 
  public:
   ~ScriptLoadRequestList();
 
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -1798,16 +1798,19 @@ ScriptLoadRequest* ScriptLoader::LookupP
       referrerPolicy != request->ReferrerPolicy() ||
       aScriptKind != request->mKind) {
     // Drop the preload.
     request->Cancel();
     AccumulateCategorical(LABELS_DOM_SCRIPT_PRELOAD_RESULT::RequestMismatch);
     return nullptr;
   }
 
+  // Report any errors that we skipped while preloading.
+  ReportPreloadErrorsToConsole(request);
+
   return request;
 }
 
 void ScriptLoader::GetSRIMetadata(const nsAString& aIntegrityAttr,
                                   SRIMetadata* aMetadataOut) {
   MOZ_ASSERT(aMetadataOut->IsEmpty());
 
   if (aIntegrityAttr.IsEmpty()) {
@@ -3191,16 +3194,19 @@ nsresult ScriptLoader::SaveSRIHash(
   return NS_OK;
 }
 
 void ScriptLoader::ReportErrorToConsole(ScriptLoadRequest* aRequest,
                                         nsresult aResult) const {
   MOZ_ASSERT(aRequest);
 
   if (aRequest->IsPreload()) {
+    // Skip reporting errors in preload requests. If the request is actually
+    // used then we will report the error in ReportPreloadErrorsToConsole below.
+    aRequest->mUnreportedPreloadError = aResult;
     return;
   }
 
   bool isScript = !aRequest->IsModuleRequest();
   const char* message;
   if (aResult == NS_ERROR_MALFORMED_URI) {
     message = isScript ? "ScriptSourceMalformed" : "ModuleSourceMalformed";
   } else if (aResult == NS_ERROR_DOM_BAD_URI) {
@@ -3220,16 +3226,29 @@ void ScriptLoader::ReportErrorToConsole(
   uint32_t columnNo = element ? element->GetScriptColumnNumber() : 0;
 
   nsContentUtils::ReportToConsole(
       nsIScriptError::warningFlag, NS_LITERAL_CSTRING("Script Loader"),
       mDocument, nsContentUtils::eDOM_PROPERTIES, message, params,
       ArrayLength(params), nullptr, EmptyString(), lineNo, columnNo);
 }
 
+void ScriptLoader::ReportPreloadErrorsToConsole(ScriptLoadRequest* aRequest) {
+  if (NS_FAILED(aRequest->mUnreportedPreloadError)) {
+    ReportErrorToConsole(aRequest, aRequest->mUnreportedPreloadError);
+    aRequest->mUnreportedPreloadError = NS_OK;
+  }
+
+  if (aRequest->IsModuleRequest()) {
+    for (auto childRequest : aRequest->AsModuleRequest()->mImports) {
+      ReportPreloadErrorsToConsole(childRequest);
+    }
+  }
+}
+
 void ScriptLoader::HandleLoadError(ScriptLoadRequest* aRequest,
                                    nsresult aResult) {
   /*
    * Handle script not loading error because source was a tracking URL.
    * We make a note of this script node by including it in a dedicated
    * array of blocked tracking nodes under its parent document.
    */
   if (aResult == NS_ERROR_TRACKING_URI) {
--- a/dom/script/ScriptLoader.h
+++ b/dom/script/ScriptLoader.h
@@ -443,16 +443,17 @@ class ScriptLoader final : public nsISup
                      nsIIncrementalStreamLoader* aLoader, nsresult aSRIStatus,
                      SRICheckDataVerifier* aSRIDataVerifier) const;
 
   nsresult SaveSRIHash(ScriptLoadRequest* aRequest,
                        SRICheckDataVerifier* aSRIDataVerifier) const;
 
   void ReportErrorToConsole(ScriptLoadRequest* aRequest,
                             nsresult aResult) const;
+  void ReportPreloadErrorsToConsole(ScriptLoadRequest* aRequest);
 
   nsresult AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest,
                                      bool* aCouldCompileOut);
   nsresult ProcessRequest(ScriptLoadRequest* aRequest);
   void ProcessDynamicImport(ModuleLoadRequest* aRequest);
   nsresult CompileOffThreadOrProcessRequest(ScriptLoadRequest* aRequest);
   void FireScriptAvailable(nsresult aResult, ScriptLoadRequest* aRequest);
   void FireScriptEvaluated(nsresult aResult, ScriptLoadRequest* aRequest);