Bug 1885489 - Part 5: Add SnapshotIterator::readInt32(). r=iain
[gecko.git] / js / loader / ScriptLoadRequest.h
blob442a456b150bfffe88d063ed889c46d3216e4b20
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 js_loader_ScriptLoadRequest_h
8 #define js_loader_ScriptLoadRequest_h
10 #include "js/RootingAPI.h"
11 #include "js/SourceText.h"
12 #include "js/TypeDecls.h"
13 #include "mozilla/Atomics.h"
14 #include "mozilla/Assertions.h"
15 #include "mozilla/dom/SRIMetadata.h"
16 #include "mozilla/LinkedList.h"
17 #include "mozilla/Maybe.h"
18 #include "mozilla/PreloaderBase.h"
19 #include "mozilla/StaticPrefs_dom.h"
20 #include "mozilla/Variant.h"
21 #include "mozilla/Vector.h"
22 #include "nsCycleCollectionParticipant.h"
23 #include "nsIGlobalObject.h"
24 #include "LoadedScript.h"
25 #include "ScriptKind.h"
26 #include "ScriptFetchOptions.h"
27 #include "nsIScriptElement.h"
29 class nsICacheInfoChannel;
31 namespace mozilla::dom {
33 class ScriptLoadContext;
34 class WorkerLoadContext;
35 class WorkletLoadContext;
36 enum class RequestPriority : uint8_t;
38 } // namespace mozilla::dom
40 namespace mozilla::loader {
41 class SyncLoadContext;
42 } // namespace mozilla::loader
44 namespace JS {
45 namespace loader {
47 class LoadContextBase;
48 class ModuleLoadRequest;
49 class ScriptLoadRequestList;
52 * ScriptLoadRequest
54 * ScriptLoadRequest is a generic representation of a JavaScript script that
55 * will be loaded by a Script/Module loader. This representation is used by the
56 * DOM ScriptLoader and will be used by workers and MOZJSComponentLoader.
58 * The ScriptLoadRequest contains information about the kind of script (classic
59 * or module), the URI, and the ScriptFetchOptions associated with the script.
60 * It is responsible for holding the script data once the fetch is complete, or
61 * if the request is cached, the bytecode.
63 * Relationship to ScriptLoadContext:
65 * ScriptLoadRequest and ScriptLoadContexts have a circular pointer. A
66 * ScriptLoadContext augments the loading of a ScriptLoadRequest by providing
67 * additional information regarding the loading and evaluation behavior (see
68 * the ScriptLoadContext class for details). In terms of responsibility,
69 * the ScriptLoadRequest represents "What" is being loaded, and the
70 * ScriptLoadContext represents "How".
72 * TODO: see if we can use it in the jsshell script loader. We need to either
73 * remove ISUPPORTS or find a way to encorporate that in the jsshell. We would
74 * then only have one implementation of the script loader, and it would be
75 * tested whenever jsshell tests are run. This would mean finding another way to
76 * create ScriptLoadRequest lists.
80 class ScriptLoadRequest : public nsISupports,
81 private mozilla::LinkedListElement<ScriptLoadRequest>,
82 public LoadedScriptDelegate<ScriptLoadRequest> {
83 using super = LinkedListElement<ScriptLoadRequest>;
85 // Allow LinkedListElement<ScriptLoadRequest> to cast us to itself as needed.
86 friend class mozilla::LinkedListElement<ScriptLoadRequest>;
87 friend class ScriptLoadRequestList;
89 protected:
90 virtual ~ScriptLoadRequest();
92 public:
93 using SRIMetadata = mozilla::dom::SRIMetadata;
94 ScriptLoadRequest(ScriptKind aKind, nsIURI* aURI,
95 mozilla::dom::ReferrerPolicy aReferrerPolicy,
96 ScriptFetchOptions* aFetchOptions,
97 const SRIMetadata& aIntegrity, nsIURI* aReferrer,
98 LoadContextBase* aContext);
100 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
101 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ScriptLoadRequest)
103 using super::getNext;
104 using super::isInList;
106 template <typename T, typename D = JS::DeletePolicy<T>>
107 using UniquePtr = mozilla::UniquePtr<T, D>;
109 bool IsModuleRequest() const { return mKind == ScriptKind::eModule; }
110 bool IsImportMapRequest() const { return mKind == ScriptKind::eImportMap; }
112 ModuleLoadRequest* AsModuleRequest();
113 const ModuleLoadRequest* AsModuleRequest() const;
115 virtual bool IsTopLevel() const { return true; };
117 virtual void Cancel();
119 virtual void SetReady();
121 enum class State : uint8_t {
122 CheckingCache,
123 PendingFetchingError,
124 Fetching,
125 Compiling,
126 LoadingImports,
127 Ready,
128 Canceled
131 // Before any attempt at fetching resources from the cache we should first
132 // make sure that the resource does not yet exists in the cache. In which case
133 // we might simply alias its LoadedScript. Otherwise a new one would be
134 // created.
135 bool IsCheckingCache() const { return mState == State::CheckingCache; }
137 // Setup and load resources, to fill the LoadedScript and make it usable by
138 // the JavaScript engine.
139 bool IsFetching() const { return mState == State::Fetching; }
140 bool IsCompiling() const { return mState == State::Compiling; }
141 bool IsLoadingImports() const { return mState == State::LoadingImports; }
142 bool IsCanceled() const { return mState == State::Canceled; }
144 bool IsPendingFetchingError() const {
145 return mState == State::PendingFetchingError;
148 // Return whether the request has been completed, either successfully or
149 // otherwise.
150 bool IsFinished() const {
151 return mState == State::Ready || mState == State::Canceled;
154 mozilla::dom::RequestPriority FetchPriority() const {
155 return mFetchOptions->mFetchPriority;
158 enum mozilla::dom::ReferrerPolicy ReferrerPolicy() const {
159 return mReferrerPolicy;
162 void UpdateReferrerPolicy(mozilla::dom::ReferrerPolicy aReferrerPolicy) {
163 mReferrerPolicy = aReferrerPolicy;
166 enum ParserMetadata ParserMetadata() const {
167 return mFetchOptions->mParserMetadata;
170 const nsString& Nonce() const { return mFetchOptions->mNonce; }
172 nsIPrincipal* TriggeringPrincipal() const {
173 return mFetchOptions->mTriggeringPrincipal;
176 // Convert a CheckingCache ScriptLoadRequest into a Fetching one, by creating
177 // a new LoadedScript which is matching the ScriptKind provided when
178 // constructing this ScriptLoadRequest.
179 void NoCacheEntryFound();
181 void SetPendingFetchingError();
183 void MarkForBytecodeEncoding(JSScript* aScript);
185 bool IsMarkedForBytecodeEncoding() const;
187 mozilla::CORSMode CORSMode() const { return mFetchOptions->mCORSMode; }
189 void DropBytecodeCacheReferences();
191 bool HasLoadContext() const { return mLoadContext; }
192 bool HasScriptLoadContext() const;
193 bool HasWorkerLoadContext() const;
195 mozilla::dom::ScriptLoadContext* GetScriptLoadContext();
197 mozilla::loader::SyncLoadContext* GetSyncLoadContext();
199 mozilla::dom::WorkerLoadContext* GetWorkerLoadContext();
201 mozilla::dom::WorkletLoadContext* GetWorkletLoadContext();
203 const LoadedScript* getLoadedScript() const { return mLoadedScript.get(); }
204 LoadedScript* getLoadedScript() { return mLoadedScript.get(); }
207 * Set the request's mBaseURL, based on aChannel.
208 * aOriginalURI is the result of aChannel->GetOriginalURI.
210 void SetBaseURLFromChannelAndOriginalURI(nsIChannel* aChannel,
211 nsIURI* aOriginalURI);
213 const ScriptKind mKind; // Whether this is a classic script or a module
214 // script.
216 State mState; // Are we still waiting for a load to complete?
217 bool mFetchSourceOnly; // Request source, not cached bytecode.
219 // The referrer policy used for the initial fetch and for fetching any
220 // imported modules
221 enum mozilla::dom::ReferrerPolicy mReferrerPolicy;
222 RefPtr<ScriptFetchOptions> mFetchOptions;
223 const SRIMetadata mIntegrity;
224 const nsCOMPtr<nsIURI> mReferrer;
225 mozilla::Maybe<nsString>
226 mSourceMapURL; // Holds source map url for loaded scripts
228 const nsCOMPtr<nsIURI> mURI;
229 nsCOMPtr<nsIPrincipal> mOriginPrincipal;
231 // Keep the URI's filename alive during off thread parsing.
232 // Also used by workers to report on errors while loading, and used by
233 // worklets as the file name in compile options.
234 nsAutoCString mURL;
236 // The base URL used for resolving relative module imports.
237 nsCOMPtr<nsIURI> mBaseURL;
239 // The loaded script holds the source / bytecode which is loaded.
241 // Currently it is used to hold information which are needed by the Debugger.
242 // Soon it would be used as a way to dissociate the LoadRequest from the
243 // loaded value, such that multiple request referring to the same content
244 // would share the same loaded script.
245 RefPtr<LoadedScript> mLoadedScript;
247 // Holds the top-level JSScript that corresponds to the current source, once
248 // it is parsed, and planned to be saved in the bytecode cache.
250 // NOTE: This field is not used for ModuleLoadRequest.
251 // See ModuleLoadRequest::mIsMarkedForBytecodeEncoding.
252 JS::Heap<JSScript*> mScriptForBytecodeEncoding;
254 // Holds the Cache information, which is used to register the bytecode
255 // on the cache entry, such that we can load it the next time.
256 nsCOMPtr<nsICacheInfoChannel> mCacheInfo;
258 // LoadContext for augmenting the load depending on the loading
259 // context (DOM, Worker, etc.)
260 RefPtr<LoadContextBase> mLoadContext;
262 // EarlyHintRegistrar id to connect the http channel back to the preload, with
263 // a default of value of 0 indicating that this request is not an early hints
264 // preload.
265 uint64_t mEarlyHintPreloaderId;
268 class ScriptLoadRequestList : private mozilla::LinkedList<ScriptLoadRequest> {
269 using super = mozilla::LinkedList<ScriptLoadRequest>;
271 public:
272 ~ScriptLoadRequestList();
274 void CancelRequestsAndClear();
276 #ifdef DEBUG
277 bool Contains(ScriptLoadRequest* aElem) const;
278 #endif // DEBUG
280 using super::getFirst;
281 using super::isEmpty;
283 void AppendElement(ScriptLoadRequest* aElem) {
284 MOZ_ASSERT(!aElem->isInList());
285 NS_ADDREF(aElem);
286 insertBack(aElem);
289 already_AddRefed<ScriptLoadRequest> Steal(ScriptLoadRequest* aElem) {
290 aElem->removeFrom(*this);
291 return dont_AddRef(aElem);
294 already_AddRefed<ScriptLoadRequest> StealFirst() {
295 MOZ_ASSERT(!isEmpty());
296 return Steal(getFirst());
299 void Remove(ScriptLoadRequest* aElem) {
300 aElem->removeFrom(*this);
301 NS_RELEASE(aElem);
305 inline void ImplCycleCollectionUnlink(ScriptLoadRequestList& aField) {
306 while (!aField.isEmpty()) {
307 RefPtr<ScriptLoadRequest> first = aField.StealFirst();
311 inline void ImplCycleCollectionTraverse(
312 nsCycleCollectionTraversalCallback& aCallback,
313 ScriptLoadRequestList& aField, const char* aName, uint32_t aFlags) {
314 for (ScriptLoadRequest* request = aField.getFirst(); request;
315 request = request->getNext()) {
316 CycleCollectionNoteChild(aCallback, request, aName, aFlags);
320 } // namespace loader
321 } // namespace JS
323 #endif // js_loader_ScriptLoadRequest_h