Bug 1688832: part 6) Prepare `AccessibleCaretManager::DispatchCaretStateChangedEvent...
[gecko.git] / dom / script / ScriptLoader.h
blob4228f7c7583957ffb575a70f0c4629ff5c43aae7
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_ScriptLoader_h
8 #define mozilla_dom_ScriptLoader_h
10 #include "js/TypeDecls.h"
11 #include "nsCOMPtr.h"
12 #include "nsRefPtrHashtable.h"
13 #include "nsIScriptElement.h"
14 #include "nsCOMArray.h"
15 #include "nsCycleCollectionParticipant.h"
16 #include "nsTArray.h"
17 #include "nsINode.h"
18 #include "nsIObserver.h"
19 #include "nsIScriptLoaderObserver.h"
20 #include "nsURIHashKey.h"
21 #include "mozilla/CORSMode.h"
22 #include "mozilla/dom/LoadedScript.h"
23 #include "mozilla/dom/ScriptLoadRequest.h"
24 #include "mozilla/MaybeOneOf.h"
25 #include "mozilla/MozPromise.h"
26 #include "ScriptKind.h"
28 class nsCycleCollectionTraversalCallback;
29 class nsIChannel;
30 class nsIConsoleReportCollector;
31 class nsIContent;
32 class nsIIncrementalStreamLoader;
33 class nsIPrincipal;
34 class nsIScriptGlobalObject;
35 class nsIURI;
37 namespace JS {
39 class CompileOptions;
41 template <typename UnitT>
42 class SourceText;
44 } // namespace JS
46 namespace mozilla {
48 class LazyLogModule;
49 union Utf8Unit;
51 namespace dom {
53 class AutoJSAPI;
54 class DocGroup;
55 class Document;
56 class LoadedScript;
57 class ModuleLoadRequest;
58 class ModuleScript;
59 class SRICheckDataVerifier;
60 class SRIMetadata;
61 class ScriptLoadHandler;
62 class ScriptLoader;
63 class ScriptRequestProcessor;
65 enum class ReferrerPolicy : uint8_t;
67 class AsyncCompileShutdownObserver final : public nsIObserver {
68 ~AsyncCompileShutdownObserver() { Unregister(); }
70 public:
71 explicit AsyncCompileShutdownObserver(ScriptLoader* aLoader)
72 : mScriptLoader(aLoader) {}
74 void OnShutdown();
75 void Unregister();
77 NS_DECL_ISUPPORTS
78 NS_DECL_NSIOBSERVER
80 private:
81 // Defined during registration in ScriptLoader constructor, and
82 // cleared during destructor, ScriptLoader::Destroy() or Shutdown.
83 ScriptLoader* mScriptLoader;
86 //////////////////////////////////////////////////////////////
87 // Script loader implementation
88 //////////////////////////////////////////////////////////////
90 class ScriptLoader final : public nsISupports {
91 class MOZ_STACK_CLASS AutoCurrentScriptUpdater {
92 public:
93 AutoCurrentScriptUpdater(ScriptLoader* aScriptLoader,
94 nsIScriptElement* aCurrentScript)
95 : mOldScript(aScriptLoader->mCurrentScript),
96 mScriptLoader(aScriptLoader) {
97 nsCOMPtr<nsINode> node = do_QueryInterface(aCurrentScript);
98 mScriptLoader->mCurrentScript =
99 node && !node->IsInShadowTree() ? aCurrentScript : nullptr;
102 ~AutoCurrentScriptUpdater() {
103 mScriptLoader->mCurrentScript.swap(mOldScript);
106 private:
107 nsCOMPtr<nsIScriptElement> mOldScript;
108 ScriptLoader* mScriptLoader;
111 friend class ModuleLoadRequest;
112 friend class ScriptRequestProcessor;
113 friend class ScriptLoadHandler;
114 friend class AutoCurrentScriptUpdater;
116 public:
117 explicit ScriptLoader(Document* aDocument);
119 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
120 NS_DECL_CYCLE_COLLECTION_CLASS(ScriptLoader)
123 * The loader maintains a weak reference to the document with
124 * which it is initialized. This call forces the reference to
125 * be dropped.
127 void DropDocumentReference() { mDocument = nullptr; }
130 * Add an observer for all scripts loaded through this loader.
132 * @param aObserver observer for all script processing.
134 nsresult AddObserver(nsIScriptLoaderObserver* aObserver) {
135 return mObservers.AppendObject(aObserver) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
139 * Remove an observer.
141 * @param aObserver observer to be removed
143 void RemoveObserver(nsIScriptLoaderObserver* aObserver) {
144 mObservers.RemoveObject(aObserver);
148 * Process a script element. This will include both loading the
149 * source of the element if it is not inline and evaluating
150 * the script itself.
152 * If the script is an inline script that can be executed immediately
153 * (i.e. there are no other scripts pending) then ScriptAvailable
154 * and ScriptEvaluated will be called before the function returns.
156 * If true is returned the script could not be executed immediately.
157 * In this case ScriptAvailable is guaranteed to be called at a later
158 * point (as well as possibly ScriptEvaluated).
160 * @param aElement The element representing the script to be loaded and
161 * evaluated.
163 bool ProcessScriptElement(nsIScriptElement* aElement);
166 * Gets the currently executing script. This is useful if you want to
167 * generate a unique key based on the currently executing script.
169 nsIScriptElement* GetCurrentScript() { return mCurrentScript; }
171 nsIScriptElement* GetCurrentParserInsertedScript() {
172 return mCurrentParserInsertedScript;
176 * Whether the loader is enabled or not.
177 * When disabled, processing of new script elements is disabled.
178 * Any call to ProcessScriptElement() will return false. Note that
179 * this DOES NOT disable currently loading or executing scripts.
181 bool GetEnabled() { return mEnabled; }
183 void SetEnabled(bool aEnabled) {
184 if (!mEnabled && aEnabled) {
185 ProcessPendingRequestsAsync();
187 mEnabled = aEnabled;
191 * Check whether to speculatively OMT parse scripts as soon as
192 * they are fetched, even if not a parser blocking request.
193 * Controlled by
194 * dom.script_loader.external_scripts.speculative_omt_parse_enabled
196 bool SpeculativeOMTParsingEnabled() const {
197 return mSpeculativeOMTParsingEnabled;
201 * Add/remove a blocker for parser-blocking scripts (and XSLT
202 * scripts). Blockers will stop such scripts from executing, but not from
203 * loading.
205 void AddParserBlockingScriptExecutionBlocker() {
206 ++mParserBlockingBlockerCount;
209 void RemoveParserBlockingScriptExecutionBlocker() {
210 if (!--mParserBlockingBlockerCount && ReadyToExecuteScripts()) {
211 ProcessPendingRequestsAsync();
216 * Add/remove a blocker for execution of all scripts. Blockers will stop
217 * scripts from executing, but not from loading.
219 void AddExecuteBlocker() { ++mBlockerCount; }
221 void RemoveExecuteBlocker() {
222 MOZ_ASSERT(mBlockerCount);
223 if (!--mBlockerCount) {
224 ProcessPendingRequestsAsync();
229 * Convert the given buffer to a UTF-16 string. If the buffer begins with a
230 * BOM, it is interpreted as that encoding; otherwise the first of |aChannel|,
231 * |aHintCharset|, or |aDocument| that provides a recognized encoding is used,
232 * or Windows-1252 if none of them do.
234 * Encoding errors in the buffer are converted to replacement characters, so
235 * allocation failure is the only way this function can fail.
237 * @param aChannel Channel corresponding to the data. May be null.
238 * @param aData The data to convert
239 * @param aLength Length of the data
240 * @param aHintCharset Character set hint (e.g., from a charset attribute).
241 * @param aDocument Document which the data is loaded for. May be null.
242 * @param aBufOut [out] fresh char16_t array containing data converted to
243 * Unicode. Caller must js_free() this data when finished
244 * with it.
245 * @param aLengthOut [out] Length of array returned in aBufOut in number
246 * of char16_t code units.
248 static nsresult ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
249 uint32_t aLength,
250 const nsAString& aHintCharset,
251 Document* aDocument, char16_t*& aBufOut,
252 size_t& aLengthOut);
254 static inline nsresult ConvertToUTF16(nsIChannel* aChannel,
255 const uint8_t* aData, uint32_t aLength,
256 const nsAString& aHintCharset,
257 Document* aDocument,
258 JS::UniqueTwoByteChars& aBufOut,
259 size_t& aLengthOut) {
260 char16_t* bufOut;
261 nsresult rv = ConvertToUTF16(aChannel, aData, aLength, aHintCharset,
262 aDocument, bufOut, aLengthOut);
263 if (NS_SUCCEEDED(rv)) {
264 aBufOut.reset(bufOut);
266 return rv;
270 * Convert the given buffer to a UTF-8 string. If the buffer begins with a
271 * BOM, it is interpreted as that encoding; otherwise the first of |aChannel|,
272 * |aHintCharset|, or |aDocument| that provides a recognized encoding is used,
273 * or Windows-1252 if none of them do.
275 * Encoding errors in the buffer are converted to replacement characters, so
276 * allocation failure is the only way this function can fail.
278 * @param aChannel Channel corresponding to the data. May be null.
279 * @param aData The data to convert
280 * @param aLength Length of the data
281 * @param aHintCharset Character set hint (e.g., from a charset attribute).
282 * @param aDocument Document which the data is loaded for. May be null.
283 * @param aBufOut [out] fresh Utf8Unit array containing data converted to
284 * Unicode. Caller must js_free() this data when finished
285 * with it.
286 * @param aLengthOut [out] Length of array returned in aBufOut in UTF-8 code
287 * units (i.e. in bytes).
289 static nsresult ConvertToUTF8(nsIChannel* aChannel, const uint8_t* aData,
290 uint32_t aLength, const nsAString& aHintCharset,
291 Document* aDocument, Utf8Unit*& aBufOut,
292 size_t& aLengthOut);
295 * Handle the completion of a stream. This is called by the
296 * ScriptLoadHandler object which observes the IncrementalStreamLoader
297 * loading the script. The streamed content is expected to be stored on the
298 * aRequest argument.
300 nsresult OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
301 ScriptLoadRequest* aRequest,
302 nsresult aChannelStatus, nsresult aSRIStatus,
303 SRICheckDataVerifier* aSRIDataVerifier);
306 * Returns wether any request is queued, and not executed yet.
308 bool HasPendingRequests();
311 * Processes any pending requests that are ready for processing.
313 void ProcessPendingRequests();
316 * Starts deferring deferred scripts and puts them in the mDeferredRequests
317 * queue instead.
319 void BeginDeferringScripts();
322 * Notifies the script loader that parsing is done. If aTerminated is true,
323 * this will drop any pending scripts that haven't run yet, otherwise it will
324 * do nothing.
326 void ParsingComplete(bool aTerminated);
329 * Notifies the script loader that the checkpoint to begin execution of defer
330 * scripts has been reached. This is either the end of of the document parse
331 * or the end of loading of parser-inserted stylesheets, whatever happens
332 * last.
334 * Otherwise, it will stop deferring scripts and immediately processes the
335 * mDeferredRequests queue.
337 * WARNING: This function will synchronously execute content scripts, so be
338 * prepared that the world might change around you.
340 void DeferCheckpointReached();
343 * Returns the number of pending scripts, deferred or not.
345 uint32_t HasPendingOrCurrentScripts() {
346 return mCurrentScript || mParserBlockingRequest;
350 * Adds aURI to the preload list and starts loading it.
352 * @param aURI The URI of the external script.
353 * @param aCharset The charset parameter for the script.
354 * @param aType The type parameter for the script.
355 * @param aCrossOrigin The crossorigin attribute for the script.
356 * Void if not present.
357 * @param aIntegrity The expect hash url, if avail, of the request
358 * @param aScriptFromHead Whether or not the script was a child of head
360 virtual void PreloadURI(nsIURI* aURI, const nsAString& aCharset,
361 const nsAString& aType, const nsAString& aCrossOrigin,
362 const nsAString& aIntegrity, bool aScriptFromHead,
363 bool aAsync, bool aDefer, bool aNoModule,
364 bool aLinkPreload,
365 const ReferrerPolicy aReferrerPolicy);
368 * Process a request that was deferred so that the script could be compiled
369 * off thread.
371 nsresult ProcessOffThreadRequest(ScriptLoadRequest* aRequest);
373 bool AddPendingChildLoader(ScriptLoader* aChild) {
374 // XXX(Bug 1631371) Check if this should use a fallible operation as it
375 // pretended earlier. Else, change the return type to void.
376 mPendingChildLoaders.AppendElement(aChild);
377 return true;
380 mozilla::dom::DocGroup* GetDocGroup() const;
383 * Register the fact that we saw the load event, and that we need to save the
384 * bytecode at the next loop cycle unless new scripts are waiting in the
385 * pipeline.
387 void LoadEventFired();
390 * Destroy and prevent the ScriptLoader or the ScriptLoadRequests from owning
391 * any references to the JSScript or to the Request which might be used for
392 * caching the encoded bytecode.
394 void Destroy();
397 * Implement the HostResolveImportedModule abstract operation.
399 * Resolve a module specifier string and look this up in the module
400 * map, returning the result. This is only called for previously
401 * loaded modules and always succeeds.
403 * @param aReferencingPrivate A JS::Value which is either undefined
404 * or contains a LoadedScript private pointer.
405 * @param aSpecifier The module specifier.
406 * @param aModuleOut This is set to the module found.
408 static void ResolveImportedModule(JSContext* aCx,
409 JS::Handle<JS::Value> aReferencingPrivate,
410 JS::Handle<JSString*> aSpecifier,
411 JS::MutableHandle<JSObject*> aModuleOut);
413 void StartDynamicImport(ModuleLoadRequest* aRequest);
416 * Shorthand Wrapper for JSAPI FinishDynamicImport function for the reject
417 * case where we do not have `aEvaluationPromise`. As there is no evaluation
418 * Promise, JS::FinishDynamicImport will always reject.
420 * @param aRequest
421 * The module load request for the dynamic module.
422 * @param aResult
423 * The result of running ModuleEvaluate -- If this is successful, then
424 * we can await the associated EvaluationPromise.
426 void FinishDynamicImportAndReject(ModuleLoadRequest* aRequest,
427 nsresult aResult);
430 * Wrapper for JSAPI FinishDynamicImport function. Takes an optional argument
431 * `aEvaluationPromise` which, if null, exits early.
433 * This is the non-tla version, which works with modules which return
434 * completion records.
436 * @param aCX
437 * The JSContext for the module.
438 * @param aRequest
439 * The module load request for the dynamic module.
440 * @param aResult
441 * The result of running ModuleEvaluate
443 void FinishDynamicImport_NoTLA(JSContext* aCx, ModuleLoadRequest* aRequest,
444 nsresult aResult);
447 * Wrapper for JSAPI FinishDynamicImport function. Takes an optional argument
448 * `aEvaluationPromise` which, if null, exits early.
450 * This is the Top Level Await version, which works with modules which return
451 * promises.
453 * @param aCX
454 * The JSContext for the module.
455 * @param aRequest
456 * The module load request for the dynamic module.
457 * @param aResult
458 * The result of running ModuleEvaluate -- If this is successful, then
459 * we can await the associated EvaluationPromise.
460 * @param aEvaluationPromise
461 * The evaluation promise returned from evaluating the module. If this
462 * is null, JS::FinishDynamicImport will reject the dynamic import
463 * module promise.
465 void FinishDynamicImport(JSContext* aCx, ModuleLoadRequest* aRequest,
466 nsresult aResult,
467 JS::Handle<JSObject*> aEvaluationPromise);
470 * Get the currently active script. This is used as the initiating script when
471 * executing timeout handler scripts.
473 static LoadedScript* GetActiveScript(JSContext* aCx);
475 Document* GetDocument() const { return mDocument; }
478 * Called by shutdown observer.
480 void Shutdown();
482 private:
483 virtual ~ScriptLoader();
485 void EnsureModuleHooksInitialized();
487 ScriptLoadRequest* CreateLoadRequest(ScriptKind aKind, nsIURI* aURI,
488 nsIScriptElement* aElement,
489 nsIPrincipal* aTriggeringPrincipal,
490 mozilla::CORSMode aCORSMode,
491 const SRIMetadata& aIntegrity,
492 ReferrerPolicy aReferrerPolicy);
495 * Unblocks the creator parser of the parser-blocking scripts.
497 void UnblockParser(ScriptLoadRequest* aParserBlockingRequest);
500 * Asynchronously resumes the creator parser of the parser-blocking scripts.
502 void ContinueParserAsync(ScriptLoadRequest* aParserBlockingRequest);
504 bool ProcessExternalScript(nsIScriptElement* aElement, ScriptKind aScriptKind,
505 nsAutoString aTypeAttr,
506 nsIContent* aScriptContent);
508 bool ProcessInlineScript(nsIScriptElement* aElement, ScriptKind aScriptKind);
510 ScriptLoadRequest* LookupPreloadRequest(nsIScriptElement* aElement,
511 ScriptKind aScriptKind,
512 const SRIMetadata& aSRIMetadata);
514 void GetSRIMetadata(const nsAString& aIntegrityAttr,
515 SRIMetadata* aMetadataOut);
518 * Given a script element, get the referrer policy should be applied to load
519 * requests.
521 ReferrerPolicy GetReferrerPolicy(nsIScriptElement* aElement);
524 * Helper function to check the content policy for a given request.
526 static nsresult CheckContentPolicy(Document* aDocument, nsISupports* aContext,
527 const nsAString& aType,
528 ScriptLoadRequest* aRequest);
531 * Helper function to determine whether an about: page loads a chrome: URI.
532 * Please note that this function only returns true if:
533 * * the about: page uses a ContentPrincipal with scheme about:
534 * * the about: page is not linkable from content
535 * (e.g. the function will return false for about:blank or about:srcdoc)
537 static bool IsAboutPageLoadingChromeURI(ScriptLoadRequest* aRequest,
538 Document* aDocument);
541 * Start a load for aRequest's URI.
543 nsresult StartLoad(ScriptLoadRequest* aRequest);
546 * Abort the current stream, and re-start with a new load request from scratch
547 * without requesting any alternate data. Returns NS_BINDING_RETARGETED on
548 * success, as this error code is used to abort the input stream.
550 nsresult RestartLoad(ScriptLoadRequest* aRequest);
552 void HandleLoadError(ScriptLoadRequest* aRequest, nsresult aResult);
555 * Process any pending requests asynchronously (i.e. off an event) if there
556 * are any. Note that this is a no-op if there aren't any currently pending
557 * requests.
559 * This function is virtual to allow cross-library calls to SetEnabled()
561 virtual void ProcessPendingRequestsAsync();
564 * If true, the loader is ready to execute parser-blocking scripts, and so are
565 * all its ancestors. If the loader itself is ready but some ancestor is not,
566 * this function will add an execute blocker and ask the ancestor to remove it
567 * once it becomes ready.
569 bool ReadyToExecuteParserBlockingScripts();
572 * Return whether just this loader is ready to execute parser-blocking
573 * scripts.
575 bool SelfReadyToExecuteParserBlockingScripts() {
576 return ReadyToExecuteScripts() && !mParserBlockingBlockerCount;
580 * Return whether this loader is ready to execute scripts in general.
582 bool ReadyToExecuteScripts() { return mEnabled && !mBlockerCount; }
584 nsresult VerifySRI(ScriptLoadRequest* aRequest,
585 nsIIncrementalStreamLoader* aLoader, nsresult aSRIStatus,
586 SRICheckDataVerifier* aSRIDataVerifier) const;
588 nsresult SaveSRIHash(ScriptLoadRequest* aRequest,
589 SRICheckDataVerifier* aSRIDataVerifier,
590 uint32_t* sriLength) const;
592 void ReportErrorToConsole(ScriptLoadRequest* aRequest,
593 nsresult aResult) const;
594 void ReportPreloadErrorsToConsole(ScriptLoadRequest* aRequest);
596 nsresult AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest,
597 bool* aCouldCompileOut);
598 nsresult ProcessRequest(ScriptLoadRequest* aRequest);
599 void ProcessDynamicImport(ModuleLoadRequest* aRequest);
600 nsresult CompileOffThreadOrProcessRequest(ScriptLoadRequest* aRequest);
601 void FireScriptAvailable(nsresult aResult, ScriptLoadRequest* aRequest);
602 void FireScriptEvaluated(nsresult aResult, ScriptLoadRequest* aRequest);
603 nsresult EvaluateScript(ScriptLoadRequest* aRequest);
606 * Queue the current script load request to be saved, when the page
607 * initialization ends. The page initialization end is defined as being the
608 * time when the load event got received, and when no more scripts are waiting
609 * to be executed.
611 void RegisterForBytecodeEncoding(ScriptLoadRequest* aRequest);
614 * Check if all conditions are met, i-e that the onLoad event fired and that
615 * no more script have to be processed. If all conditions are met, queue an
616 * event to encode all the bytecode and save them on the cache.
618 void MaybeTriggerBytecodeEncoding();
621 * Iterate over all script load request and save the bytecode of executed
622 * functions on the cache provided by the channel.
624 void EncodeBytecode();
625 void EncodeRequestBytecode(JSContext* aCx, ScriptLoadRequest* aRequest);
627 void GiveUpBytecodeEncoding();
629 already_AddRefed<nsIScriptGlobalObject> GetScriptGlobalObject();
630 nsresult FillCompileOptionsForRequest(const mozilla::dom::AutoJSAPI& jsapi,
631 ScriptLoadRequest* aRequest,
632 JS::Handle<JSObject*> aScopeChain,
633 JS::CompileOptions* aOptions);
635 uint32_t NumberOfProcessors();
636 nsresult PrepareLoadedRequest(ScriptLoadRequest* aRequest,
637 nsIIncrementalStreamLoader* aLoader,
638 nsresult aStatus);
640 void AddDeferRequest(ScriptLoadRequest* aRequest);
641 void AddAsyncRequest(ScriptLoadRequest* aRequest);
642 bool MaybeRemovedDeferRequests();
644 bool ShouldCompileOffThread(ScriptLoadRequest* aRequest);
646 void MaybeMoveToLoadedList(ScriptLoadRequest* aRequest);
648 using MaybeSourceText =
649 mozilla::MaybeOneOf<JS::SourceText<char16_t>, JS::SourceText<Utf8Unit>>;
651 // Get source text. On success |aMaybeSource| will contain either UTF-8 or
652 // UTF-16 source; on failure it will remain in its initial state.
653 MOZ_MUST_USE nsresult GetScriptSource(JSContext* aCx,
654 ScriptLoadRequest* aRequest,
655 MaybeSourceText* aMaybeSource);
657 void SetModuleFetchStarted(ModuleLoadRequest* aRequest);
658 void SetModuleFetchFinishedAndResumeWaitingRequests(
659 ModuleLoadRequest* aRequest, nsresult aResult);
661 bool IsFetchingModule(ModuleLoadRequest* aRequest) const;
663 bool ModuleMapContainsURL(nsIURI* aURL) const;
664 RefPtr<mozilla::GenericNonExclusivePromise> WaitForModuleFetch(nsIURI* aURL);
665 ModuleScript* GetFetchedModule(nsIURI* aURL) const;
667 friend JSObject* HostResolveImportedModule(
668 JSContext* aCx, JS::Handle<JS::Value> aReferencingPrivate,
669 JS::Handle<JSString*> aSpecifier);
671 // Returns wether we should save the bytecode of this script after the
672 // execution of the script.
673 static bool ShouldCacheBytecode(ScriptLoadRequest* aRequest);
675 nsresult CreateModuleScript(ModuleLoadRequest* aRequest);
676 nsresult ProcessFetchedModuleSource(ModuleLoadRequest* aRequest);
677 void CheckModuleDependenciesLoaded(ModuleLoadRequest* aRequest);
678 void ProcessLoadedModuleTree(ModuleLoadRequest* aRequest);
679 bool InstantiateModuleTree(ModuleLoadRequest* aRequest);
680 JS::Value FindFirstParseError(ModuleLoadRequest* aRequest);
681 void StartFetchingModuleDependencies(ModuleLoadRequest* aRequest);
683 RefPtr<mozilla::GenericPromise> StartFetchingModuleAndDependencies(
684 ModuleLoadRequest* aParent, nsIURI* aURI);
686 nsresult InitDebuggerDataForModuleTree(JSContext* aCx,
687 ModuleLoadRequest* aRequest);
689 void RunScriptWhenSafe(ScriptLoadRequest* aRequest);
692 * Wait for any unused off thread compilations to finish and then
693 * cancel them.
695 void CancelScriptLoadRequests();
697 Document* mDocument; // [WEAK]
698 nsCOMArray<nsIScriptLoaderObserver> mObservers;
699 ScriptLoadRequestList mNonAsyncExternalScriptInsertedRequests;
700 // mLoadingAsyncRequests holds async requests while they're loading; when they
701 // have been loaded they are moved to mLoadedAsyncRequests.
702 ScriptLoadRequestList mLoadingAsyncRequests;
703 ScriptLoadRequestList mLoadedAsyncRequests;
704 ScriptLoadRequestList mDeferRequests;
705 ScriptLoadRequestList mXSLTRequests;
706 ScriptLoadRequestList mDynamicImportRequests;
707 RefPtr<ScriptLoadRequest> mParserBlockingRequest;
709 // List of script load request that are holding a buffer which has to be saved
710 // on the cache.
711 ScriptLoadRequestList mBytecodeEncodingQueue;
713 // In mRequests, the additional information here is stored by the element.
714 struct PreloadInfo {
715 RefPtr<ScriptLoadRequest> mRequest;
716 nsString mCharset;
719 friend void ImplCycleCollectionUnlink(ScriptLoader::PreloadInfo& aField);
720 friend void ImplCycleCollectionTraverse(
721 nsCycleCollectionTraversalCallback& aCallback,
722 ScriptLoader::PreloadInfo& aField, const char* aName, uint32_t aFlags);
724 struct PreloadRequestComparator {
725 bool Equals(const PreloadInfo& aPi,
726 ScriptLoadRequest* const& aRequest) const {
727 return aRequest == aPi.mRequest;
731 struct PreloadURIComparator {
732 bool Equals(const PreloadInfo& aPi, nsIURI* const& aURI) const;
735 nsTArray<PreloadInfo> mPreloads;
737 nsCOMPtr<nsIScriptElement> mCurrentScript;
738 nsCOMPtr<nsIScriptElement> mCurrentParserInsertedScript;
739 nsTArray<RefPtr<ScriptLoader>> mPendingChildLoaders;
740 uint32_t mParserBlockingBlockerCount;
741 uint32_t mBlockerCount;
742 uint32_t mNumberOfProcessors;
743 bool mEnabled;
744 bool mDeferEnabled;
745 bool mSpeculativeOMTParsingEnabled;
746 bool mDeferCheckpointReached;
747 bool mBlockingDOMContentLoaded;
748 bool mLoadEventFired;
749 bool mGiveUpEncoding;
751 // Module map
752 nsRefPtrHashtable<nsURIHashKey, mozilla::GenericNonExclusivePromise::Private>
753 mFetchingModules;
754 nsRefPtrHashtable<nsURIHashKey, ModuleScript> mFetchedModules;
756 nsCOMPtr<nsIConsoleReportCollector> mReporter;
758 // ShutdownObserver for off thread compilations
759 RefPtr<AsyncCompileShutdownObserver> mShutdownObserver;
761 // Logging
762 public:
763 static LazyLogModule gCspPRLog;
764 static LazyLogModule gScriptLoaderLog;
767 class nsAutoScriptLoaderDisabler {
768 public:
769 explicit nsAutoScriptLoaderDisabler(Document* aDoc);
771 ~nsAutoScriptLoaderDisabler();
773 bool mWasEnabled;
774 RefPtr<ScriptLoader> mLoader;
777 } // namespace dom
778 } // namespace mozilla
780 #endif // mozilla_dom_ScriptLoader_h