forked from mirrors/gecko-dev
		
	 a60d06b5ef
			
		
	
	
		a60d06b5ef
		
	
	
	
	
		
			
			Differential Revision: https://phabricator.services.mozilla.com/D19269 --HG-- extra : moz-landing-system : lando
		
			
				
	
	
		
			621 lines
		
	
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			621 lines
		
	
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #ifndef mozilla_dom_ScriptLoader_h
 | |
| #define mozilla_dom_ScriptLoader_h
 | |
| 
 | |
| #include "nsCOMPtr.h"
 | |
| #include "nsRefPtrHashtable.h"
 | |
| #include "mozilla/Encoding.h"
 | |
| #include "nsIScriptElement.h"
 | |
| #include "nsCOMArray.h"
 | |
| #include "nsCycleCollectionParticipant.h"
 | |
| #include "nsTArray.h"
 | |
| #include "nsAutoPtr.h"
 | |
| #include "nsICacheInfoChannel.h"
 | |
| #include "mozilla/dom/Document.h"
 | |
| #include "nsIIncrementalStreamLoader.h"
 | |
| #include "nsURIHashKey.h"
 | |
| #include "mozilla/CORSMode.h"
 | |
| #include "mozilla/dom/ScriptLoadRequest.h"
 | |
| #include "mozilla/dom/SRIMetadata.h"
 | |
| #include "mozilla/dom/SRICheck.h"
 | |
| #include "mozilla/Maybe.h"
 | |
| #include "mozilla/MozPromise.h"
 | |
| #include "mozilla/net/ReferrerPolicy.h"
 | |
| #include "mozilla/StaticPrefs.h"
 | |
| #include "mozilla/Vector.h"
 | |
| 
 | |
| class nsIURI;
 | |
| 
 | |
| namespace JS {
 | |
| 
 | |
| template <typename UnitT>
 | |
| class SourceText;
 | |
| 
 | |
| }  // namespace JS
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace dom {
 | |
| 
 | |
| class AutoJSAPI;
 | |
| class LoadedScript;
 | |
| class ModuleLoadRequest;
 | |
| class ModuleScript;
 | |
| class ScriptLoadHandler;
 | |
| class ScriptRequestProcessor;
 | |
| 
 | |
| //////////////////////////////////////////////////////////////
 | |
| // Script loader implementation
 | |
| //////////////////////////////////////////////////////////////
 | |
| 
 | |
| class ScriptLoader final : public nsISupports {
 | |
|   class MOZ_STACK_CLASS AutoCurrentScriptUpdater {
 | |
|    public:
 | |
|     AutoCurrentScriptUpdater(ScriptLoader* aScriptLoader,
 | |
|                              nsIScriptElement* aCurrentScript)
 | |
|         : mOldScript(aScriptLoader->mCurrentScript),
 | |
|           mScriptLoader(aScriptLoader) {
 | |
|       nsCOMPtr<nsINode> node = do_QueryInterface(aCurrentScript);
 | |
|       mScriptLoader->mCurrentScript =
 | |
|           node && !node->IsInShadowTree() ? aCurrentScript : nullptr;
 | |
|     }
 | |
| 
 | |
|     ~AutoCurrentScriptUpdater() {
 | |
|       mScriptLoader->mCurrentScript.swap(mOldScript);
 | |
|     }
 | |
| 
 | |
|    private:
 | |
|     nsCOMPtr<nsIScriptElement> mOldScript;
 | |
|     ScriptLoader* mScriptLoader;
 | |
|   };
 | |
| 
 | |
|   friend class ModuleLoadRequest;
 | |
|   friend class ScriptRequestProcessor;
 | |
|   friend class ScriptLoadHandler;
 | |
|   friend class AutoCurrentScriptUpdater;
 | |
| 
 | |
|  public:
 | |
|   explicit ScriptLoader(Document* aDocument);
 | |
| 
 | |
|   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 | |
|   NS_DECL_CYCLE_COLLECTION_CLASS(ScriptLoader)
 | |
| 
 | |
|   /**
 | |
|    * The loader maintains a weak reference to the document with
 | |
|    * which it is initialized. This call forces the reference to
 | |
|    * be dropped.
 | |
|    */
 | |
|   void DropDocumentReference() { mDocument = nullptr; }
 | |
| 
 | |
|   /**
 | |
|    * Add an observer for all scripts loaded through this loader.
 | |
|    *
 | |
|    * @param aObserver observer for all script processing.
 | |
|    */
 | |
|   nsresult AddObserver(nsIScriptLoaderObserver* aObserver) {
 | |
|     return mObservers.AppendObject(aObserver) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Remove an observer.
 | |
|    *
 | |
|    * @param aObserver observer to be removed
 | |
|    */
 | |
|   void RemoveObserver(nsIScriptLoaderObserver* aObserver) {
 | |
|     mObservers.RemoveObject(aObserver);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Process a script element. This will include both loading the
 | |
|    * source of the element if it is not inline and evaluating
 | |
|    * the script itself.
 | |
|    *
 | |
|    * If the script is an inline script that can be executed immediately
 | |
|    * (i.e. there are no other scripts pending) then ScriptAvailable
 | |
|    * and ScriptEvaluated will be called before the function returns.
 | |
|    *
 | |
|    * If true is returned the script could not be executed immediately.
 | |
|    * In this case ScriptAvailable is guaranteed to be called at a later
 | |
|    * point (as well as possibly ScriptEvaluated).
 | |
|    *
 | |
|    * @param aElement The element representing the script to be loaded and
 | |
|    *        evaluated.
 | |
|    */
 | |
|   bool ProcessScriptElement(nsIScriptElement* aElement);
 | |
| 
 | |
|   /**
 | |
|    * Gets the currently executing script. This is useful if you want to
 | |
|    * generate a unique key based on the currently executing script.
 | |
|    */
 | |
|   nsIScriptElement* GetCurrentScript() { return mCurrentScript; }
 | |
| 
 | |
|   nsIScriptElement* GetCurrentParserInsertedScript() {
 | |
|     return mCurrentParserInsertedScript;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Whether the loader is enabled or not.
 | |
|    * When disabled, processing of new script elements is disabled.
 | |
|    * Any call to ProcessScriptElement() will return false. Note that
 | |
|    * this DOES NOT disable currently loading or executing scripts.
 | |
|    */
 | |
|   bool GetEnabled() { return mEnabled; }
 | |
| 
 | |
|   void SetEnabled(bool aEnabled) {
 | |
|     if (!mEnabled && aEnabled) {
 | |
|       ProcessPendingRequestsAsync();
 | |
|     }
 | |
|     mEnabled = aEnabled;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Add/remove a blocker for parser-blocking scripts (and XSLT
 | |
|    * scripts). Blockers will stop such scripts from executing, but not from
 | |
|    * loading.
 | |
|    */
 | |
|   void AddParserBlockingScriptExecutionBlocker() {
 | |
|     ++mParserBlockingBlockerCount;
 | |
|   }
 | |
| 
 | |
|   void RemoveParserBlockingScriptExecutionBlocker() {
 | |
|     if (!--mParserBlockingBlockerCount && ReadyToExecuteScripts()) {
 | |
|       ProcessPendingRequestsAsync();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Add/remove a blocker for execution of all scripts.  Blockers will stop
 | |
|    * scripts from executing, but not from loading.
 | |
|    */
 | |
|   void AddExecuteBlocker() { ++mBlockerCount; }
 | |
| 
 | |
|   void RemoveExecuteBlocker() {
 | |
|     MOZ_ASSERT(mBlockerCount);
 | |
|     if (!--mBlockerCount) {
 | |
|       ProcessPendingRequestsAsync();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Convert the given buffer to a UTF-16 string.
 | |
|    * @param aChannel     Channel corresponding to the data. May be null.
 | |
|    * @param aData        The data to convert
 | |
|    * @param aLength      Length of the data
 | |
|    * @param aHintCharset Hint for the character set (e.g., from a charset
 | |
|    *                     attribute). May be the empty string.
 | |
|    * @param aDocument    Document which the data is loaded for. Must not be
 | |
|    *                     null.
 | |
|    * @param aBufOut      [out] char16_t array allocated by ConvertToUTF16 and
 | |
|    *                     containing data converted to unicode.  Caller must
 | |
|    *                     js_free() this data when no longer needed.
 | |
|    * @param aLengthOut   [out] Length of array returned in aBufOut in number
 | |
|    *                     of char16_t code units.
 | |
|    */
 | |
|   static nsresult ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
 | |
|                                  uint32_t aLength,
 | |
|                                  const nsAString& aHintCharset,
 | |
|                                  Document* aDocument, char16_t*& aBufOut,
 | |
|                                  size_t& aLengthOut);
 | |
| 
 | |
|   static inline nsresult ConvertToUTF16(nsIChannel* aChannel,
 | |
|                                         const uint8_t* aData, uint32_t aLength,
 | |
|                                         const nsAString& aHintCharset,
 | |
|                                         Document* aDocument,
 | |
|                                         JS::UniqueTwoByteChars& aBufOut,
 | |
|                                         size_t& aLengthOut) {
 | |
|     char16_t* bufOut;
 | |
|     nsresult rv = ConvertToUTF16(aChannel, aData, aLength, aHintCharset,
 | |
|                                  aDocument, bufOut, aLengthOut);
 | |
|     if (NS_SUCCEEDED(rv)) {
 | |
|       aBufOut.reset(bufOut);
 | |
|     }
 | |
|     return rv;
 | |
|   };
 | |
| 
 | |
|   /**
 | |
|    * Handle the completion of a stream.  This is called by the
 | |
|    * ScriptLoadHandler object which observes the IncrementalStreamLoader
 | |
|    * loading the script. The streamed content is expected to be stored on the
 | |
|    * aRequest argument.
 | |
|    */
 | |
|   nsresult OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
 | |
|                             ScriptLoadRequest* aRequest,
 | |
|                             nsresult aChannelStatus, nsresult aSRIStatus,
 | |
|                             SRICheckDataVerifier* aSRIDataVerifier);
 | |
| 
 | |
|   /**
 | |
|    * Returns wether any request is queued, and not executed yet.
 | |
|    */
 | |
|   bool HasPendingRequests();
 | |
| 
 | |
|   /**
 | |
|    * Processes any pending requests that are ready for processing.
 | |
|    */
 | |
|   void ProcessPendingRequests();
 | |
| 
 | |
|   /**
 | |
|    * Starts deferring deferred scripts and puts them in the mDeferredRequests
 | |
|    * queue instead.
 | |
|    */
 | |
|   void BeginDeferringScripts() {
 | |
|     mDeferEnabled = true;
 | |
|     if (mDocument) {
 | |
|       mDocument->BlockOnload();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Notifies the script loader that parsing is done.  If aTerminated is true,
 | |
|    * this will drop any pending scripts that haven't run yet.  Otherwise, it
 | |
|    * will stops deferring scripts and immediately processes the
 | |
|    * mDeferredRequests queue.
 | |
|    *
 | |
|    * WARNING: This function will synchronously execute content scripts, so be
 | |
|    * prepared that the world might change around you.
 | |
|    */
 | |
|   void ParsingComplete(bool aTerminated);
 | |
| 
 | |
|   /**
 | |
|    * Returns the number of pending scripts, deferred or not.
 | |
|    */
 | |
|   uint32_t HasPendingOrCurrentScripts() {
 | |
|     return mCurrentScript || mParserBlockingRequest;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * 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.
 | |
|    * @param aCrossOrigin The crossorigin attribute for the script.
 | |
|    *                     Void if not present.
 | |
|    * @param aIntegrity The expect hash url, if avail, of the request
 | |
|    * @param aScriptFromHead Whether or not the script was a child of head
 | |
|    */
 | |
|   virtual void PreloadURI(nsIURI* aURI, const nsAString& aCharset,
 | |
|                           const nsAString& aType, const nsAString& aCrossOrigin,
 | |
|                           const nsAString& aIntegrity, bool aScriptFromHead,
 | |
|                           bool aAsync, bool aDefer, bool aNoModule,
 | |
|                           const mozilla::net::ReferrerPolicy aReferrerPolicy);
 | |
| 
 | |
|   /**
 | |
|    * Process a request that was deferred so that the script could be compiled
 | |
|    * off thread.
 | |
|    */
 | |
|   nsresult ProcessOffThreadRequest(ScriptLoadRequest* aRequest);
 | |
| 
 | |
|   bool AddPendingChildLoader(ScriptLoader* aChild) {
 | |
|     return mPendingChildLoaders.AppendElement(aChild) != nullptr;
 | |
|   }
 | |
| 
 | |
|   mozilla::dom::DocGroup* GetDocGroup() const {
 | |
|     return mDocument->GetDocGroup();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Register the fact that we saw the load event, and that we need to save the
 | |
|    * bytecode at the next loop cycle unless new scripts are waiting in the
 | |
|    * pipeline.
 | |
|    */
 | |
|   void LoadEventFired();
 | |
| 
 | |
|   /**
 | |
|    * Destroy and prevent the ScriptLoader or the ScriptLoadRequests from owning
 | |
|    * any references to the JSScript or to the Request which might be used for
 | |
|    * caching the encoded bytecode.
 | |
|    */
 | |
|   void Destroy() { GiveUpBytecodeEncoding(); }
 | |
| 
 | |
|   /**
 | |
|    * Implement the HostResolveImportedModule abstract operation.
 | |
|    *
 | |
|    * Resolve a module specifier string and look this up in the module
 | |
|    * map, returning the result. This is only called for previously
 | |
|    * loaded modules and always succeeds.
 | |
|    *
 | |
|    * @param aReferencingPrivate A JS::Value which is either undefined
 | |
|    *                            or contains a LoadedScript private pointer.
 | |
|    * @param aSpecifier The module specifier.
 | |
|    * @param aModuleOut This is set to the module found.
 | |
|    */
 | |
|   static void ResolveImportedModule(JSContext* aCx,
 | |
|                                     JS::Handle<JS::Value> aReferencingPrivate,
 | |
|                                     JS::Handle<JSString*> aSpecifier,
 | |
|                                     JS::MutableHandle<JSObject*> aModuleOut);
 | |
| 
 | |
|   void StartDynamicImport(ModuleLoadRequest* aRequest);
 | |
|   void FinishDynamicImport(ModuleLoadRequest* aRequest, nsresult aResult);
 | |
|   void FinishDynamicImport(JSContext* aCx, ModuleLoadRequest* aRequest,
 | |
|                            nsresult aResult);
 | |
| 
 | |
|   /*
 | |
|    * Get the currently active script. This is used as the initiating script when
 | |
|    * executing timeout handler scripts.
 | |
|    */
 | |
|   static LoadedScript* GetActiveScript(JSContext* aCx);
 | |
| 
 | |
|   Document* GetDocument() const { return mDocument; }
 | |
| 
 | |
|  private:
 | |
|   virtual ~ScriptLoader();
 | |
| 
 | |
|   void EnsureModuleHooksInitialized();
 | |
| 
 | |
|   ScriptLoadRequest* CreateLoadRequest(
 | |
|       ScriptKind aKind, nsIURI* aURI, nsIScriptElement* aElement,
 | |
|       nsIPrincipal* aTriggeringPrincipal, mozilla::CORSMode aCORSMode,
 | |
|       const SRIMetadata& aIntegrity,
 | |
|       mozilla::net::ReferrerPolicy aReferrerPolicy);
 | |
| 
 | |
|   /**
 | |
|    * Unblocks the creator parser of the parser-blocking scripts.
 | |
|    */
 | |
|   void UnblockParser(ScriptLoadRequest* aParserBlockingRequest);
 | |
| 
 | |
|   /**
 | |
|    * Asynchronously resumes the creator parser of the parser-blocking scripts.
 | |
|    */
 | |
|   void ContinueParserAsync(ScriptLoadRequest* aParserBlockingRequest);
 | |
| 
 | |
|   bool ProcessExternalScript(nsIScriptElement* aElement, ScriptKind aScriptKind,
 | |
|                              nsAutoString aTypeAttr,
 | |
|                              nsIContent* aScriptContent);
 | |
| 
 | |
|   bool ProcessInlineScript(nsIScriptElement* aElement, ScriptKind aScriptKind);
 | |
| 
 | |
|   ScriptLoadRequest* LookupPreloadRequest(nsIScriptElement* aElement,
 | |
|                                           ScriptKind aScriptKind);
 | |
| 
 | |
|   void GetSRIMetadata(const nsAString& aIntegrityAttr,
 | |
|                       SRIMetadata* aMetadataOut);
 | |
| 
 | |
|   /**
 | |
|    * Given a script element, get the referrer policy should be applied to load
 | |
|    * requests.
 | |
|    */
 | |
|   mozilla::net::ReferrerPolicy GetReferrerPolicy(nsIScriptElement* aElement);
 | |
| 
 | |
|   /**
 | |
|    * Helper function to check the content policy for a given request.
 | |
|    */
 | |
|   static nsresult CheckContentPolicy(Document* aDocument, nsISupports* aContext,
 | |
|                                      const nsAString& aType,
 | |
|                                      ScriptLoadRequest* aRequest);
 | |
| 
 | |
|   /**
 | |
|    * Start a load for aRequest's URI.
 | |
|    */
 | |
|   nsresult StartLoad(ScriptLoadRequest* aRequest);
 | |
| 
 | |
|   /**
 | |
|    * Abort the current stream, and re-start with a new load request from scratch
 | |
|    * without requesting any alternate data. Returns NS_BINDING_RETARGETED on
 | |
|    * success, as this error code is used to abort the input stream.
 | |
|    */
 | |
|   nsresult RestartLoad(ScriptLoadRequest* aRequest);
 | |
| 
 | |
|   void HandleLoadError(ScriptLoadRequest* aRequest, nsresult aResult);
 | |
| 
 | |
|   /**
 | |
|    * Process any pending requests asynchronously (i.e. off an event) if there
 | |
|    * are any. Note that this is a no-op if there aren't any currently pending
 | |
|    * requests.
 | |
|    *
 | |
|    * This function is virtual to allow cross-library calls to SetEnabled()
 | |
|    */
 | |
|   virtual void ProcessPendingRequestsAsync();
 | |
| 
 | |
|   /**
 | |
|    * If true, the loader is ready to execute parser-blocking scripts, and so are
 | |
|    * all its ancestors.  If the loader itself is ready but some ancestor is not,
 | |
|    * this function will add an execute blocker and ask the ancestor to remove it
 | |
|    * once it becomes ready.
 | |
|    */
 | |
|   bool ReadyToExecuteParserBlockingScripts();
 | |
| 
 | |
|   /**
 | |
|    * Return whether just this loader is ready to execute parser-blocking
 | |
|    * scripts.
 | |
|    */
 | |
|   bool SelfReadyToExecuteParserBlockingScripts() {
 | |
|     return ReadyToExecuteScripts() && !mParserBlockingBlockerCount;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Return whether this loader is ready to execute scripts in general.
 | |
|    */
 | |
|   bool ReadyToExecuteScripts() { return mEnabled && !mBlockerCount; }
 | |
| 
 | |
|   nsresult VerifySRI(ScriptLoadRequest* aRequest,
 | |
|                      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);
 | |
|   nsresult EvaluateScript(ScriptLoadRequest* aRequest);
 | |
| 
 | |
|   /**
 | |
|    * Queue the current script load request to be saved, when the page
 | |
|    * initialization ends. The page initialization end is defined as being the
 | |
|    * time when the load event got received, and when no more scripts are waiting
 | |
|    * to be executed.
 | |
|    */
 | |
|   void RegisterForBytecodeEncoding(ScriptLoadRequest* aRequest);
 | |
| 
 | |
|   /**
 | |
|    * Check if all conditions are met, i-e that the onLoad event fired and that
 | |
|    * no more script have to be processed.  If all conditions are met, queue an
 | |
|    * event to encode all the bytecode and save them on the cache.
 | |
|    */
 | |
|   void MaybeTriggerBytecodeEncoding();
 | |
| 
 | |
|   /**
 | |
|    * Iterate over all script load request and save the bytecode of executed
 | |
|    * functions on the cache provided by the channel.
 | |
|    */
 | |
|   void EncodeBytecode();
 | |
|   void EncodeRequestBytecode(JSContext* aCx, ScriptLoadRequest* aRequest);
 | |
| 
 | |
|   void GiveUpBytecodeEncoding();
 | |
| 
 | |
|   already_AddRefed<nsIScriptGlobalObject> GetScriptGlobalObject();
 | |
|   nsresult FillCompileOptionsForRequest(const mozilla::dom::AutoJSAPI& jsapi,
 | |
|                                         ScriptLoadRequest* aRequest,
 | |
|                                         JS::Handle<JSObject*> aScopeChain,
 | |
|                                         JS::CompileOptions* aOptions);
 | |
| 
 | |
|   uint32_t NumberOfProcessors();
 | |
|   nsresult PrepareLoadedRequest(ScriptLoadRequest* aRequest,
 | |
|                                 nsIIncrementalStreamLoader* aLoader,
 | |
|                                 nsresult aStatus);
 | |
| 
 | |
|   void AddDeferRequest(ScriptLoadRequest* aRequest);
 | |
|   void AddAsyncRequest(ScriptLoadRequest* aRequest);
 | |
|   bool MaybeRemovedDeferRequests();
 | |
| 
 | |
|   void MaybeMoveToLoadedList(ScriptLoadRequest* aRequest);
 | |
| 
 | |
|   mozilla::Maybe<JS::SourceText<char16_t>> GetScriptSource(
 | |
|       JSContext* aCx, ScriptLoadRequest* aRequest);
 | |
| 
 | |
|   void SetModuleFetchStarted(ModuleLoadRequest* aRequest);
 | |
|   void SetModuleFetchFinishedAndResumeWaitingRequests(
 | |
|       ModuleLoadRequest* aRequest, nsresult aResult);
 | |
| 
 | |
|   bool IsFetchingModule(ModuleLoadRequest* aRequest) const;
 | |
| 
 | |
|   bool ModuleMapContainsURL(nsIURI* aURL) const;
 | |
|   RefPtr<mozilla::GenericNonExclusivePromise> WaitForModuleFetch(nsIURI* aURL);
 | |
|   ModuleScript* GetFetchedModule(nsIURI* aURL) const;
 | |
| 
 | |
|   friend JSObject* HostResolveImportedModule(
 | |
|       JSContext* aCx, JS::Handle<JS::Value> aReferencingPrivate,
 | |
|       JS::Handle<JSString*> aSpecifier);
 | |
| 
 | |
|   // Returns wether we should save the bytecode of this script after the
 | |
|   // execution of the script.
 | |
|   static bool ShouldCacheBytecode(ScriptLoadRequest* aRequest);
 | |
| 
 | |
|   nsresult CreateModuleScript(ModuleLoadRequest* aRequest);
 | |
|   nsresult ProcessFetchedModuleSource(ModuleLoadRequest* aRequest);
 | |
|   void CheckModuleDependenciesLoaded(ModuleLoadRequest* aRequest);
 | |
|   void ProcessLoadedModuleTree(ModuleLoadRequest* aRequest);
 | |
|   bool InstantiateModuleTree(ModuleLoadRequest* aRequest);
 | |
|   JS::Value FindFirstParseError(ModuleLoadRequest* aRequest);
 | |
|   void StartFetchingModuleDependencies(ModuleLoadRequest* aRequest);
 | |
| 
 | |
|   RefPtr<mozilla::GenericPromise> StartFetchingModuleAndDependencies(
 | |
|       ModuleLoadRequest* aParent, nsIURI* aURI);
 | |
| 
 | |
|   nsresult InitDebuggerDataForModuleTree(JSContext* aCx,
 | |
|                                          ModuleLoadRequest* aRequest);
 | |
| 
 | |
|   void RunScriptWhenSafe(ScriptLoadRequest* aRequest);
 | |
| 
 | |
|   Document* mDocument;  // [WEAK]
 | |
|   nsCOMArray<nsIScriptLoaderObserver> mObservers;
 | |
|   ScriptLoadRequestList mNonAsyncExternalScriptInsertedRequests;
 | |
|   // mLoadingAsyncRequests holds async requests while they're loading; when they
 | |
|   // have been loaded they are moved to mLoadedAsyncRequests.
 | |
|   ScriptLoadRequestList mLoadingAsyncRequests;
 | |
|   ScriptLoadRequestList mLoadedAsyncRequests;
 | |
|   ScriptLoadRequestList mDeferRequests;
 | |
|   ScriptLoadRequestList mXSLTRequests;
 | |
|   ScriptLoadRequestList mDynamicImportRequests;
 | |
|   RefPtr<ScriptLoadRequest> mParserBlockingRequest;
 | |
| 
 | |
|   // List of script load request that are holding a buffer which has to be saved
 | |
|   // on the cache.
 | |
|   ScriptLoadRequestList mBytecodeEncodingQueue;
 | |
| 
 | |
|   // In mRequests, the additional information here is stored by the element.
 | |
|   struct PreloadInfo {
 | |
|     RefPtr<ScriptLoadRequest> mRequest;
 | |
|     nsString mCharset;
 | |
|   };
 | |
| 
 | |
|   friend void ImplCycleCollectionUnlink(ScriptLoader::PreloadInfo& aField);
 | |
|   friend void ImplCycleCollectionTraverse(
 | |
|       nsCycleCollectionTraversalCallback& aCallback,
 | |
|       ScriptLoader::PreloadInfo& aField, const char* aName, uint32_t aFlags);
 | |
| 
 | |
|   struct PreloadRequestComparator {
 | |
|     bool Equals(const PreloadInfo& aPi,
 | |
|                 ScriptLoadRequest* const& aRequest) const {
 | |
|       return aRequest == aPi.mRequest;
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   struct PreloadURIComparator {
 | |
|     bool Equals(const PreloadInfo& aPi, nsIURI* const& aURI) const;
 | |
|   };
 | |
| 
 | |
|   nsTArray<PreloadInfo> mPreloads;
 | |
| 
 | |
|   nsCOMPtr<nsIScriptElement> mCurrentScript;
 | |
|   nsCOMPtr<nsIScriptElement> mCurrentParserInsertedScript;
 | |
|   nsTArray<RefPtr<ScriptLoader>> mPendingChildLoaders;
 | |
|   uint32_t mParserBlockingBlockerCount;
 | |
|   uint32_t mBlockerCount;
 | |
|   uint32_t mNumberOfProcessors;
 | |
|   bool mEnabled;
 | |
|   bool mDeferEnabled;
 | |
|   bool mDocumentParsingDone;
 | |
|   bool mBlockingDOMContentLoaded;
 | |
|   bool mLoadEventFired;
 | |
|   bool mGiveUpEncoding;
 | |
| 
 | |
|   // Module map
 | |
|   nsRefPtrHashtable<nsURIHashKey, mozilla::GenericNonExclusivePromise::Private>
 | |
|       mFetchingModules;
 | |
|   nsRefPtrHashtable<nsURIHashKey, ModuleScript> mFetchedModules;
 | |
| 
 | |
|   nsCOMPtr<nsIConsoleReportCollector> mReporter;
 | |
| 
 | |
|   // Logging
 | |
|  public:
 | |
|   static LazyLogModule gCspPRLog;
 | |
|   static LazyLogModule gScriptLoaderLog;
 | |
| };
 | |
| 
 | |
| class nsAutoScriptLoaderDisabler {
 | |
|  public:
 | |
|   explicit nsAutoScriptLoaderDisabler(Document* aDoc) {
 | |
|     mLoader = aDoc->ScriptLoader();
 | |
|     mWasEnabled = mLoader->GetEnabled();
 | |
|     if (mWasEnabled) {
 | |
|       mLoader->SetEnabled(false);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   ~nsAutoScriptLoaderDisabler() {
 | |
|     if (mWasEnabled) {
 | |
|       mLoader->SetEnabled(true);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   bool mWasEnabled;
 | |
|   RefPtr<ScriptLoader> mLoader;
 | |
| };
 | |
| 
 | |
| }  // namespace dom
 | |
| }  // namespace mozilla
 | |
| 
 | |
| #endif  // mozilla_dom_ScriptLoader_h
 |