Bug 1874684 - Part 6: Limit day length calculations to safe integers. r=mgaudet
[gecko.git] / dom / script / ScriptLoader.h
blob2fa5721d8c42d81839c900cd22de64a0613e8977
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 "js/Utility.h" // JS::FreePolicy
12 #include "js/loader/LoadedScript.h"
13 #include "js/loader/ScriptKind.h"
14 #include "js/loader/ScriptLoadRequest.h"
15 #include "mozilla/dom/ScriptLoadContext.h"
16 #include "nsCOMPtr.h"
17 #include "nsRefPtrHashtable.h"
18 #include "nsIScriptElement.h"
19 #include "nsCOMArray.h"
20 #include "nsCycleCollectionParticipant.h"
21 #include "nsTArray.h"
22 #include "nsILoadInfo.h" // nsSecurityFlags
23 #include "nsINode.h"
24 #include "nsIObserver.h"
25 #include "nsIScriptLoaderObserver.h"
26 #include "nsURIHashKey.h"
27 #include "mozilla/CORSMode.h"
28 #include "mozilla/dom/JSExecutionContext.h" // JSExecutionContext
29 #include "ModuleLoader.h"
30 #include "mozilla/MaybeOneOf.h"
31 #include "mozilla/MozPromise.h"
33 class nsCycleCollectionTraversalCallback;
34 class nsIChannel;
35 class nsIConsoleReportCollector;
36 class nsIContent;
37 class nsIIncrementalStreamLoader;
38 class nsIPrincipal;
39 class nsIScriptGlobalObject;
40 class nsIURI;
42 namespace JS {
44 class CompileOptions;
46 template <typename UnitT>
47 class SourceText;
49 namespace loader {
51 class LoadedScript;
52 class ScriptLoaderInterface;
53 class ModuleLoadRequest;
54 class ModuleScript;
55 class ScriptLoadRequest;
56 class ScriptLoadRequestList;
58 enum class ParserMetadata;
60 } // namespace loader
61 } // namespace JS
63 namespace mozilla {
65 class LazyLogModule;
66 union Utf8Unit;
68 namespace dom {
70 class AutoJSAPI;
71 class DocGroup;
72 class Document;
73 class ModuleLoader;
74 class SRICheckDataVerifier;
75 class SRIMetadata;
76 class ScriptLoadHandler;
77 class ScriptLoadContext;
78 class ScriptLoader;
79 class ScriptRequestProcessor;
81 enum class ReferrerPolicy : uint8_t;
82 enum class RequestPriority : uint8_t;
84 class AsyncCompileShutdownObserver final : public nsIObserver {
85 ~AsyncCompileShutdownObserver() { Unregister(); }
87 public:
88 explicit AsyncCompileShutdownObserver(ScriptLoader* aLoader)
89 : mScriptLoader(aLoader) {}
91 void OnShutdown();
92 void Unregister();
94 NS_DECL_ISUPPORTS
95 NS_DECL_NSIOBSERVER
97 private:
98 // Defined during registration in ScriptLoader constructor, and
99 // cleared during destructor, ScriptLoader::Destroy() or Shutdown.
100 ScriptLoader* mScriptLoader;
103 //////////////////////////////////////////////////////////////
104 // Script loader implementation
105 //////////////////////////////////////////////////////////////
107 class ScriptLoader final : public JS::loader::ScriptLoaderInterface {
108 class MOZ_STACK_CLASS AutoCurrentScriptUpdater {
109 public:
110 AutoCurrentScriptUpdater(ScriptLoader* aScriptLoader,
111 nsIScriptElement* aCurrentScript)
112 : mOldScript(aScriptLoader->mCurrentScript),
113 mScriptLoader(aScriptLoader) {
114 nsCOMPtr<nsINode> node = do_QueryInterface(aCurrentScript);
115 mScriptLoader->mCurrentScript =
116 node && !node->IsInShadowTree() ? aCurrentScript : nullptr;
119 ~AutoCurrentScriptUpdater() {
120 mScriptLoader->mCurrentScript.swap(mOldScript);
123 private:
124 nsCOMPtr<nsIScriptElement> mOldScript;
125 ScriptLoader* mScriptLoader;
128 friend class JS::loader::ModuleLoadRequest;
129 friend class ScriptRequestProcessor;
130 friend class ModuleLoader;
131 friend class ScriptLoadHandler;
132 friend class AutoCurrentScriptUpdater;
134 public:
135 using MaybeSourceText =
136 mozilla::MaybeOneOf<JS::SourceText<char16_t>, JS::SourceText<Utf8Unit>>;
138 explicit ScriptLoader(Document* aDocument);
140 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
141 NS_DECL_CYCLE_COLLECTION_CLASS(ScriptLoader)
144 * Called when the document that owns this script loader changes global. The
145 * argument is null when the document is detached from a window.
147 void SetGlobalObject(nsIGlobalObject* aGlobalObject);
150 * The loader maintains a weak reference to the document with
151 * which it is initialized. This call forces the reference to
152 * be dropped.
154 void DropDocumentReference() { mDocument = nullptr; }
157 * Add an observer for all scripts loaded through this loader.
159 * @param aObserver observer for all script processing.
161 nsresult AddObserver(nsIScriptLoaderObserver* aObserver) {
162 return mObservers.AppendObject(aObserver) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
166 * Remove an observer.
168 * @param aObserver observer to be removed
170 void RemoveObserver(nsIScriptLoaderObserver* aObserver) {
171 mObservers.RemoveObject(aObserver);
175 * Process a script element. This will include both loading the
176 * source of the element if it is not inline and evaluating
177 * the script itself.
179 * If the script is an inline script that can be executed immediately
180 * (i.e. there are no other scripts pending) then ScriptAvailable
181 * and ScriptEvaluated will be called before the function returns.
183 * If true is returned the script could not be executed immediately.
184 * In this case ScriptAvailable is guaranteed to be called at a later
185 * point (as well as possibly ScriptEvaluated).
187 * @param aElement The element representing the script to be loaded and
188 * evaluated.
190 bool ProcessScriptElement(nsIScriptElement* aElement);
193 * Gets the currently executing script. This is useful if you want to
194 * generate a unique key based on the currently executing script.
196 nsIScriptElement* GetCurrentScript() { return mCurrentScript; }
198 nsIScriptElement* GetCurrentParserInsertedScript() {
199 return mCurrentParserInsertedScript;
203 * Whether the loader is enabled or not.
204 * When disabled, processing of new script elements is disabled.
205 * Any call to ProcessScriptElement() will return false. Note that
206 * this DOES NOT disable currently loading or executing scripts.
208 bool GetEnabled() { return mEnabled; }
210 void SetEnabled(bool aEnabled) {
211 if (!mEnabled && aEnabled) {
212 ProcessPendingRequestsAsync();
214 mEnabled = aEnabled;
217 ModuleLoader* GetModuleLoader() { return mModuleLoader; }
219 void RegisterContentScriptModuleLoader(ModuleLoader* aLoader);
220 void RegisterShadowRealmModuleLoader(ModuleLoader* aLoader);
223 * Check whether to speculatively OMT parse scripts as soon as
224 * they are fetched, even if not a parser blocking request.
225 * Controlled by
226 * dom.script_loader.external_scripts.speculative_omt_parse_enabled
228 bool SpeculativeOMTParsingEnabled() const {
229 return mSpeculativeOMTParsingEnabled;
233 * Add/remove a blocker for parser-blocking scripts (and XSLT
234 * scripts). Blockers will stop such scripts from executing, but not from
235 * loading.
237 void AddParserBlockingScriptExecutionBlocker() {
238 ++mParserBlockingBlockerCount;
241 void RemoveParserBlockingScriptExecutionBlocker() {
242 if (!--mParserBlockingBlockerCount && ReadyToExecuteScripts()) {
243 ProcessPendingRequestsAsync();
248 * Add/remove a blocker for execution of all scripts. Blockers will stop
249 * scripts from executing, but not from loading.
251 void AddExecuteBlocker() { ++mBlockerCount; }
253 void RemoveExecuteBlocker() {
254 MOZ_ASSERT(mBlockerCount);
255 if (!--mBlockerCount) {
256 ProcessPendingRequestsAsync();
261 * Convert the given buffer to a UTF-16 string. If the buffer begins with a
262 * BOM, it is interpreted as that encoding; otherwise the first of |aChannel|,
263 * |aHintCharset|, or |aDocument| that provides a recognized encoding is used,
264 * or Windows-1252 if none of them do.
266 * Encoding errors in the buffer are converted to replacement characters, so
267 * allocation failure is the only way this function can fail.
269 * @param aChannel Channel corresponding to the data. May be null.
270 * @param aData The data to convert
271 * @param aLength Length of the data
272 * @param aHintCharset Character set hint (e.g., from a charset attribute).
273 * @param aDocument Document which the data is loaded for. May be null.
274 * @param aBufOut [out] fresh char16_t array containing data converted to
275 * Unicode.
276 * @param aLengthOut [out] Length of array returned in aBufOut in number
277 * of char16_t code units.
279 static nsresult ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
280 uint32_t aLength,
281 const nsAString& aHintCharset,
282 Document* aDocument,
283 UniquePtr<char16_t[], JS::FreePolicy>& aBufOut,
284 size_t& aLengthOut);
287 * Convert the given buffer to a UTF-8 string. If the buffer begins with a
288 * BOM, it is interpreted as that encoding; otherwise the first of |aChannel|,
289 * |aHintCharset|, or |aDocument| that provides a recognized encoding is used,
290 * or Windows-1252 if none of them do.
292 * Encoding errors in the buffer are converted to replacement characters, so
293 * allocation failure is the only way this function can fail.
295 * @param aChannel Channel corresponding to the data. May be null.
296 * @param aData The data to convert
297 * @param aLength Length of the data
298 * @param aHintCharset Character set hint (e.g., from a charset attribute).
299 * @param aDocument Document which the data is loaded for. May be null.
300 * @param aBufOut [out] fresh Utf8Unit array containing data converted to
301 * Unicode.
302 * @param aLengthOut [out] Length of array returned in aBufOut in UTF-8 code
303 * units (i.e. in bytes).
305 static nsresult ConvertToUTF8(nsIChannel* aChannel, const uint8_t* aData,
306 uint32_t aLength, const nsAString& aHintCharset,
307 Document* aDocument,
308 UniquePtr<Utf8Unit[], JS::FreePolicy>& aBufOut,
309 size_t& aLengthOut);
312 * Handle the completion of a stream. This is called by the
313 * ScriptLoadHandler object which observes the IncrementalStreamLoader
314 * loading the script. The streamed content is expected to be stored on the
315 * aRequest argument.
317 nsresult OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
318 ScriptLoadRequest* aRequest,
319 nsresult aChannelStatus, nsresult aSRIStatus,
320 SRICheckDataVerifier* aSRIDataVerifier);
323 * Returns wether any request is queued, and not executed yet.
325 bool HasPendingRequests() const;
328 * Returns wether there are any dynamic module import requests pending.
330 bool HasPendingDynamicImports() const;
333 * Processes any pending requests that are ready for processing.
335 void ProcessPendingRequests();
338 * Starts deferring deferred scripts and puts them in the mDeferredRequests
339 * queue instead.
341 void BeginDeferringScripts();
344 * Notifies the script loader that parsing is done. If aTerminated is true,
345 * this will drop any pending scripts that haven't run yet, otherwise it will
346 * do nothing.
348 void ParsingComplete(bool aTerminated);
351 * Notifies the script loader that the checkpoint to begin execution of defer
352 * scripts has been reached. This is either the end of of the document parse
353 * or the end of loading of parser-inserted stylesheets, whatever happens
354 * last.
356 * Otherwise, it will stop deferring scripts and immediately processes the
357 * mDeferredRequests queue.
359 * WARNING: This function will synchronously execute content scripts, so be
360 * prepared that the world might change around you.
362 void DeferCheckpointReached();
365 * Returns the number of pending scripts, deferred or not.
367 uint32_t HasPendingOrCurrentScripts() {
368 return mCurrentScript || mParserBlockingRequest;
372 * Adds aURI to the preload list and starts loading it.
374 * @param aURI The URI of the external script.
375 * @param aCharset The charset parameter for the script.
376 * @param aType The type parameter for the script.
377 * @param aCrossOrigin The crossorigin attribute for the script.
378 * Void if not present.
379 * @param aFetchPriority
380 * <https://html.spec.whatwg.org/#the-script-element:attr-script-fetchpriority>.
381 * @param aIntegrity The expect hash url, if avail, of the request
383 * @param aScriptFromHead Whether or not the script was a child of head
385 virtual void PreloadURI(nsIURI* aURI, const nsAString& aCharset,
386 const nsAString& aType, const nsAString& aCrossOrigin,
387 const nsAString& aNonce,
388 const nsAString& aFetchPriority,
389 const nsAString& aIntegrity, bool aScriptFromHead,
390 bool aAsync, bool aDefer, bool aLinkPreload,
391 const ReferrerPolicy aReferrerPolicy,
392 uint64_t aEarlyHintPreloaderId);
395 * Process a request that was deferred so that the script could be compiled
396 * off thread.
398 nsresult ProcessOffThreadRequest(ScriptLoadRequest* aRequest);
400 bool AddPendingChildLoader(ScriptLoader* aChild) {
401 // XXX(Bug 1631371) Check if this should use a fallible operation as it
402 // pretended earlier. Else, change the return type to void.
403 mPendingChildLoaders.AppendElement(aChild);
404 return true;
407 mozilla::dom::DocGroup* GetDocGroup() const;
410 * Register the fact that we saw the load event, and that we need to save the
411 * bytecode at the next loop cycle unless new scripts are waiting in the
412 * pipeline.
414 void LoadEventFired();
417 * Destroy and prevent the ScriptLoader or the ScriptLoadRequests from owning
418 * any references to the JSScript or to the Request which might be used for
419 * caching the encoded bytecode.
421 void Destroy();
424 * Get the currently active script. This is used as the initiating script when
425 * executing timeout handler scripts.
427 static JS::loader::LoadedScript* GetActiveScript(JSContext* aCx);
429 Document* GetDocument() const { return mDocument; }
431 nsIURI* GetBaseURI() const override;
433 private:
434 ~ScriptLoader();
436 already_AddRefed<ScriptLoadRequest> CreateLoadRequest(
437 ScriptKind aKind, nsIURI* aURI, nsIScriptElement* aElement,
438 nsIPrincipal* aTriggeringPrincipal, mozilla::CORSMode aCORSMode,
439 const nsAString& aNonce, RequestPriority aRequestPriority,
440 const SRIMetadata& aIntegrity, ReferrerPolicy aReferrerPolicy,
441 JS::loader::ParserMetadata aParserMetadata);
444 * Unblocks the creator parser of the parser-blocking scripts.
446 void UnblockParser(ScriptLoadRequest* aParserBlockingRequest);
449 * Asynchronously resumes the creator parser of the parser-blocking scripts.
451 void ContinueParserAsync(ScriptLoadRequest* aParserBlockingRequest);
453 bool ProcessExternalScript(nsIScriptElement* aElement, ScriptKind aScriptKind,
454 nsIContent* aScriptContent);
456 bool ProcessInlineScript(nsIScriptElement* aElement, ScriptKind aScriptKind);
458 JS::loader::ScriptLoadRequest* LookupPreloadRequest(
459 nsIScriptElement* aElement, ScriptKind aScriptKind,
460 const SRIMetadata& aSRIMetadata);
462 void GetSRIMetadata(const nsAString& aIntegrityAttr,
463 SRIMetadata* aMetadataOut);
466 * Given a script element, get the referrer policy should be applied to load
467 * requests.
469 ReferrerPolicy GetReferrerPolicy(nsIScriptElement* aElement);
472 * Helper function to check the content policy for a given request.
474 static nsresult CheckContentPolicy(Document* aDocument,
475 nsIScriptElement* aElement,
476 const nsAString& aNonce,
477 ScriptLoadRequest* aRequest);
480 * Helper function to determine whether an about: page loads a chrome: URI.
481 * Please note that this function only returns true if:
482 * * the about: page uses a ContentPrincipal with scheme about:
483 * * the about: page is not linkable from content
484 * (e.g. the function will return false for about:blank or about:srcdoc)
486 static bool IsAboutPageLoadingChromeURI(ScriptLoadRequest* aRequest,
487 Document* aDocument);
490 * Start a load for aRequest's URI.
492 nsresult StartLoad(ScriptLoadRequest* aRequest,
493 const Maybe<nsAutoString>& aCharsetForPreload);
495 * Start a load for a classic script URI.
496 * Sets up the necessary security flags before calling StartLoadInternal.
498 nsresult StartClassicLoad(ScriptLoadRequest* aRequest,
499 const Maybe<nsAutoString>& aCharsetForPreload);
501 static void PrepareCacheInfoChannel(nsIChannel* aChannel,
502 ScriptLoadRequest* aRequest);
504 static void PrepareRequestPriorityAndRequestDependencies(
505 nsIChannel* aChannel, ScriptLoadRequest* aRequest);
507 [[nodiscard]] static nsresult PrepareHttpRequestAndInitiatorType(
508 nsIChannel* aChannel, ScriptLoadRequest* aRequest,
509 const Maybe<nsAutoString>& aCharsetForPreload);
511 [[nodiscard]] nsresult PrepareIncrementalStreamLoader(
512 nsIIncrementalStreamLoader** aOutLoader, ScriptLoadRequest* aRequest);
515 * Start a load for a script (module or classic) URI.
517 * aCharsetForPreload is only needed when this load is a preload (via
518 * ScriptLoader::PreloadURI), because ScriptLoadRequest doesn't
519 * have this information.
521 nsresult StartLoadInternal(ScriptLoadRequest* aRequest,
522 nsSecurityFlags securityFlags,
523 const Maybe<nsAutoString>& aCharsetForPreload);
526 * Abort the current stream, and re-start with a new load request from scratch
527 * without requesting any alternate data. Returns NS_BINDING_RETARGETED on
528 * success, as this error code is used to abort the input stream.
530 nsresult RestartLoad(ScriptLoadRequest* aRequest);
532 void HandleLoadError(ScriptLoadRequest* aRequest, nsresult aResult);
535 * Process any pending requests asynchronously (i.e. off an event) if there
536 * are any. Note that this is a no-op if there aren't any currently pending
537 * requests.
539 * This function is virtual to allow cross-library calls to SetEnabled()
541 virtual void ProcessPendingRequestsAsync();
544 * If true, the loader is ready to execute parser-blocking scripts, and so are
545 * all its ancestors. If the loader itself is ready but some ancestor is not,
546 * this function will add an execute blocker and ask the ancestor to remove it
547 * once it becomes ready.
549 bool ReadyToExecuteParserBlockingScripts();
552 * Return whether just this loader is ready to execute parser-blocking
553 * scripts.
555 bool SelfReadyToExecuteParserBlockingScripts() {
556 return ReadyToExecuteScripts() && !mParserBlockingBlockerCount;
560 * Return whether this loader is ready to execute scripts in general.
562 bool ReadyToExecuteScripts() { return mEnabled && !mBlockerCount; }
564 nsresult VerifySRI(ScriptLoadRequest* aRequest,
565 nsIIncrementalStreamLoader* aLoader, nsresult aSRIStatus,
566 SRICheckDataVerifier* aSRIDataVerifier) const;
568 nsresult SaveSRIHash(ScriptLoadRequest* aRequest,
569 SRICheckDataVerifier* aSRIDataVerifier) const;
571 void ReportErrorToConsole(ScriptLoadRequest* aRequest,
572 nsresult aResult) const override;
574 void ReportWarningToConsole(
575 ScriptLoadRequest* aRequest, const char* aMessageName,
576 const nsTArray<nsString>& aParams = nsTArray<nsString>()) const override;
578 void ReportPreloadErrorsToConsole(ScriptLoadRequest* aRequest);
580 nsresult AttemptOffThreadScriptCompile(ScriptLoadRequest* aRequest,
581 bool* aCouldCompileOut);
583 nsresult CreateOffThreadTask(JSContext* aCx, ScriptLoadRequest* aRequest,
584 JS::CompileOptions& aOptions,
585 CompileOrDecodeTask** aCompileOrDecodeTask);
587 nsresult ProcessRequest(ScriptLoadRequest* aRequest);
588 nsresult CompileOffThreadOrProcessRequest(ScriptLoadRequest* aRequest);
589 void FireScriptAvailable(nsresult aResult, ScriptLoadRequest* aRequest);
590 // TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
591 MOZ_CAN_RUN_SCRIPT_BOUNDARY void FireScriptEvaluated(
592 nsresult aResult, ScriptLoadRequest* aRequest);
594 // Implements https://html.spec.whatwg.org/#execute-the-script-block
595 nsresult EvaluateScriptElement(ScriptLoadRequest* aRequest);
597 // Handles both bytecode and text source scripts; populates exec with a
598 // compiled script
599 nsresult CompileOrDecodeClassicScript(JSContext* aCx,
600 JSExecutionContext& aExec,
601 ScriptLoadRequest* aRequest);
603 static nsCString& BytecodeMimeTypeFor(ScriptLoadRequest* aRequest);
605 // Decide whether to encode bytecode for given script load request,
606 // and store the script into the request if necessary.
608 // This method must be called before executing the script.
609 void MaybePrepareForBytecodeEncodingBeforeExecute(
610 ScriptLoadRequest* aRequest, JS::Handle<JSScript*> aScript);
612 // Queue the script load request for bytecode encoding if we decided to
613 // encode, or cleanup the script load request fields otherwise.
615 // This method must be called after executing the script.
616 nsresult MaybePrepareForBytecodeEncodingAfterExecute(
617 ScriptLoadRequest* aRequest, nsresult aRv);
619 // Returns true if MaybePrepareForBytecodeEncodingAfterExecute is called
620 // for given script load request.
621 bool IsAlreadyHandledForBytecodeEncodingPreparation(
622 ScriptLoadRequest* aRequest);
624 void MaybePrepareModuleForBytecodeEncodingBeforeExecute(
625 JSContext* aCx, ModuleLoadRequest* aRequest) override;
627 nsresult MaybePrepareModuleForBytecodeEncodingAfterExecute(
628 ModuleLoadRequest* aRequest, nsresult aRv) override;
630 // Implements https://html.spec.whatwg.org/#run-a-classic-script
631 nsresult EvaluateScript(nsIGlobalObject* aGlobalObject,
632 ScriptLoadRequest* aRequest);
635 * Queue the current script load request to be saved, when the page
636 * initialization ends. The page initialization end is defined as being the
637 * time when the load event got received, and when no more scripts are waiting
638 * to be executed.
640 void RegisterForBytecodeEncoding(ScriptLoadRequest* aRequest);
643 * Check if all conditions are met, i-e that the onLoad event fired and that
644 * no more script have to be processed. If all conditions are met, queue an
645 * event to encode all the bytecode and save them on the cache.
647 void MaybeTriggerBytecodeEncoding() override;
650 * Iterate over all script load request and save the bytecode of executed
651 * functions on the cache provided by the channel.
653 void EncodeBytecode();
654 void EncodeRequestBytecode(JSContext* aCx, ScriptLoadRequest* aRequest);
656 void GiveUpBytecodeEncoding();
658 already_AddRefed<nsIGlobalObject> GetGlobalForRequest(
659 ScriptLoadRequest* aRequest);
661 already_AddRefed<nsIScriptGlobalObject> GetScriptGlobalObject();
663 // Fill in CompileOptions, as well as produce the introducer script for
664 // subsequent calls to UpdateDebuggerMetadata
665 nsresult FillCompileOptionsForRequest(
666 JSContext* aCx, ScriptLoadRequest* aRequest, JS::CompileOptions* aOptions,
667 JS::MutableHandle<JSScript*> aIntroductionScript) override;
669 uint32_t NumberOfProcessors();
670 int32_t PhysicalSizeOfMemoryInGB();
672 nsresult PrepareLoadedRequest(ScriptLoadRequest* aRequest,
673 nsIIncrementalStreamLoader* aLoader,
674 nsresult aStatus);
676 void AddDeferRequest(ScriptLoadRequest* aRequest);
677 void AddAsyncRequest(ScriptLoadRequest* aRequest);
678 bool MaybeRemovedDeferRequests();
680 bool ShouldApplyDelazifyStrategy(ScriptLoadRequest* aRequest);
681 void ApplyDelazifyStrategy(JS::CompileOptions* aOptions);
683 bool ShouldCompileOffThread(ScriptLoadRequest* aRequest);
685 void MaybeMoveToLoadedList(ScriptLoadRequest* aRequest);
687 // Returns wether we should save the bytecode of this script after the
688 // execution of the script.
689 static bool ShouldCacheBytecode(ScriptLoadRequest* aRequest);
691 void RunScriptWhenSafe(ScriptLoadRequest* aRequest);
694 * Cancel and remove all outstanding load requests, including waiting for any
695 * off thread compilations to finish.
697 void CancelAndClearScriptLoadRequests();
699 Document* mDocument; // [WEAK]
700 nsCOMArray<nsIScriptLoaderObserver> mObservers;
701 ScriptLoadRequestList mNonAsyncExternalScriptInsertedRequests;
702 // mLoadingAsyncRequests holds async requests while they're loading; when they
703 // have been loaded they are moved to mLoadedAsyncRequests.
704 ScriptLoadRequestList mLoadingAsyncRequests;
705 // mLoadedAsyncRequests holds async script requests and dynamic module import
706 // requests, which are processed in the same way.
707 ScriptLoadRequestList mLoadedAsyncRequests;
708 ScriptLoadRequestList mDeferRequests;
709 ScriptLoadRequestList mXSLTRequests;
710 RefPtr<ScriptLoadRequest> mParserBlockingRequest;
711 ScriptLoadRequestList mOffThreadCompilingRequests;
713 // List of script load request that are holding a buffer which has to be saved
714 // on the cache.
715 ScriptLoadRequestList mBytecodeEncodingQueue;
717 // In mRequests, the additional information here is stored by the element.
718 struct PreloadInfo {
719 RefPtr<ScriptLoadRequest> mRequest;
720 nsString mCharset;
723 friend void ImplCycleCollectionUnlink(ScriptLoader::PreloadInfo& aField);
724 friend void ImplCycleCollectionTraverse(
725 nsCycleCollectionTraversalCallback& aCallback,
726 ScriptLoader::PreloadInfo& aField, const char* aName, uint32_t aFlags);
728 struct PreloadRequestComparator {
729 bool Equals(const PreloadInfo& aPi,
730 ScriptLoadRequest* const& aRequest) const {
731 return aRequest == aPi.mRequest;
735 struct PreloadURIComparator {
736 bool Equals(const PreloadInfo& aPi, nsIURI* const& aURI) const;
739 nsTArray<PreloadInfo> mPreloads;
741 nsCOMPtr<nsIScriptElement> mCurrentScript;
742 nsCOMPtr<nsIScriptElement> mCurrentParserInsertedScript;
743 nsTArray<RefPtr<ScriptLoader>> mPendingChildLoaders;
744 uint32_t mParserBlockingBlockerCount;
745 uint32_t mBlockerCount;
746 uint32_t mNumberOfProcessors;
747 uint32_t mTotalFullParseSize;
748 int32_t mPhysicalSizeOfMemory;
749 bool mEnabled;
750 bool mDeferEnabled;
751 bool mSpeculativeOMTParsingEnabled;
752 bool mDeferCheckpointReached;
753 bool mBlockingDOMContentLoaded;
754 bool mLoadEventFired;
755 bool mGiveUpEncoding;
757 TimeDuration mMainThreadParseTime;
759 nsCOMPtr<nsIConsoleReportCollector> mReporter;
761 // ShutdownObserver for off thread compilations
762 RefPtr<AsyncCompileShutdownObserver> mShutdownObserver;
764 RefPtr<ModuleLoader> mModuleLoader;
765 nsTArray<RefPtr<ModuleLoader>> mWebExtModuleLoaders;
766 nsTArray<RefPtr<ModuleLoader>> mShadowRealmModuleLoaders;
768 // Logging
769 public:
770 static LazyLogModule gCspPRLog;
771 static LazyLogModule gScriptLoaderLog;
774 class nsAutoScriptLoaderDisabler {
775 public:
776 explicit nsAutoScriptLoaderDisabler(Document* aDoc);
778 ~nsAutoScriptLoaderDisabler();
780 bool mWasEnabled;
781 RefPtr<ScriptLoader> mLoader;
784 } // namespace dom
785 } // namespace mozilla
787 #endif // mozilla_dom_ScriptLoader_h