Bug 1843838 - Rename ScriptLoadRequest::IsReadyToRun to IsFinished since this returns...
[gecko.git] / js / loader / ModuleLoadRequest.h
blob6434146212759fc7e1e0bfdff7b1fdedd84f8a13
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_ModuleLoadRequest_h
8 #define js_loader_ModuleLoadRequest_h
10 #include "LoadContextBase.h"
11 #include "ScriptLoadRequest.h"
12 #include "ModuleLoaderBase.h"
13 #include "mozilla/Assertions.h"
14 #include "js/RootingAPI.h"
15 #include "js/Value.h"
16 #include "nsURIHashKey.h"
17 #include "nsTHashtable.h"
19 namespace JS::loader {
21 class ModuleScript;
22 class ModuleLoaderBase;
24 // A reference counted set of URLs we have visited in the process of loading a
25 // module graph.
26 class VisitedURLSet : public nsTHashtable<nsURIHashKey> {
27 NS_INLINE_DECL_REFCOUNTING(VisitedURLSet)
29 private:
30 ~VisitedURLSet() = default;
33 // A load request for a module, created for every top level module script and
34 // every module import. Load request can share an ModuleScript if there are
35 // multiple imports of the same module.
37 class ModuleLoadRequest final : public ScriptLoadRequest {
38 ~ModuleLoadRequest() {
39 MOZ_ASSERT(!mWaitingParentRequest);
40 MOZ_ASSERT(mAwaitingImports == 0);
43 ModuleLoadRequest(const ModuleLoadRequest& aOther) = delete;
44 ModuleLoadRequest(ModuleLoadRequest&& aOther) = delete;
46 public:
47 NS_DECL_ISUPPORTS_INHERITED
48 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ModuleLoadRequest,
49 ScriptLoadRequest)
50 using SRIMetadata = mozilla::dom::SRIMetadata;
52 ModuleLoadRequest(nsIURI* aURI, ScriptFetchOptions* aFetchOptions,
53 const SRIMetadata& aIntegrity, nsIURI* aReferrer,
54 LoadContextBase* aContext, bool aIsTopLevel,
55 bool aIsDynamicImport, ModuleLoaderBase* aLoader,
56 VisitedURLSet* aVisitedSet, ModuleLoadRequest* aRootModule);
58 static VisitedURLSet* NewVisitedSetForTopLevelImport(nsIURI* aURI);
60 bool IsTopLevel() const override { return mIsTopLevel; }
62 bool IsDynamicImport() const { return mIsDynamicImport; }
64 bool IsErrored() const;
66 nsIGlobalObject* GetGlobalObject();
68 void SetReady() override;
69 void Cancel() override;
70 void ClearDynamicImport();
72 void ModuleLoaded();
73 void ModuleErrored();
74 void DependenciesLoaded();
75 void LoadFailed();
77 ModuleLoadRequest* GetRootModule() {
78 if (!mRootModule) {
79 return this;
81 return mRootModule;
84 bool IsModuleMarkedForBytecodeEncoding() const {
85 return mIsMarkedForBytecodeEncoding;
87 void MarkModuleForBytecodeEncoding() {
88 MOZ_ASSERT(!IsModuleMarkedForBytecodeEncoding());
89 mIsMarkedForBytecodeEncoding = true;
92 // Convenience methods to call into the module loader for this request.
94 void CancelDynamicImport(nsresult aResult) {
95 MOZ_ASSERT(IsDynamicImport());
96 mLoader->CancelDynamicImport(this, aResult);
98 #ifdef DEBUG
99 bool IsRegisteredDynamicImport() const {
100 return IsDynamicImport() && mLoader->HasDynamicImport(this);
102 #endif
103 nsresult StartModuleLoad() { return mLoader->StartModuleLoad(this); }
104 nsresult RestartModuleLoad() { return mLoader->RestartModuleLoad(this); }
105 nsresult OnFetchComplete(nsresult aRv) {
106 return mLoader->OnFetchComplete(this, aRv);
108 bool InstantiateModuleGraph() {
109 return mLoader->InstantiateModuleGraph(this);
111 nsresult EvaluateModule() { return mLoader->EvaluateModule(this); }
112 void StartDynamicImport() { mLoader->StartDynamicImport(this); }
113 void ProcessDynamicImport() { mLoader->ProcessDynamicImport(this); }
115 void ChildLoadComplete(bool aSuccess);
117 private:
118 void LoadFinished();
119 void CancelImports();
120 void CheckModuleDependenciesLoaded();
122 void AssertAllImportsFinished() const;
123 void AssertAllImportsCancelled() const;
125 public:
126 // Is this a request for a top level module script or an import?
127 const bool mIsTopLevel;
129 // Is this the top level request for a dynamic module import?
130 const bool mIsDynamicImport;
132 // True if this module is planned to be saved in the bytecode cache.
133 // ModuleLoadRequest doesn't use ScriptLoadRequest::mScriptForBytecodeEncoding
134 // field because the JSScript reference isn't always avaialble for module.
135 bool mIsMarkedForBytecodeEncoding = false;
137 // Pointer to the script loader, used to trigger actions when the module load
138 // finishes.
139 RefPtr<ModuleLoaderBase> mLoader;
141 // Pointer to the top level module of this module graph, nullptr if this is a
142 // top level module
143 RefPtr<ModuleLoadRequest> mRootModule;
145 // Set to a module script object after a successful load or nullptr on
146 // failure.
147 RefPtr<ModuleScript> mModuleScript;
149 // Array of imported modules.
150 nsTArray<RefPtr<ModuleLoadRequest>> mImports;
152 // Parent module (i.e. importer of this module) that is waiting for this
153 // module and its dependencies to load, or null.
154 RefPtr<ModuleLoadRequest> mWaitingParentRequest;
156 // Number of child modules (i.e. imported modules) that this module is waiting
157 // for.
158 size_t mAwaitingImports = 0;
160 // Set of module URLs visited while fetching the module graph this request is
161 // part of.
162 RefPtr<VisitedURLSet> mVisitedSet;
164 // For dynamic imports, the details to pass to FinishDynamicImport.
165 JS::Heap<JS::Value> mDynamicReferencingPrivate;
166 JS::Heap<JSString*> mDynamicSpecifier;
167 JS::Heap<JSObject*> mDynamicPromise;
170 } // namespace JS::loader
172 #endif // js_loader_ModuleLoadRequest_h