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"
16 #include "nsURIHashKey.h"
17 #include "nsTHashtable.h"
19 namespace JS::loader
{
23 class ModuleLoaderBase
;
25 // A reference counted set of URLs we have visited in the process of loading a
27 class VisitedURLSet
: public nsTHashtable
<nsURIHashKey
> {
28 NS_INLINE_DECL_REFCOUNTING(VisitedURLSet
)
31 ~VisitedURLSet() = default;
34 // A load request for a module, created for every top level module script and
35 // every module import. Load request can share an ModuleScript if there are
36 // multiple imports of the same module.
38 class ModuleLoadRequest final
: public ScriptLoadRequest
{
39 ~ModuleLoadRequest() {
40 MOZ_ASSERT(!mWaitingParentRequest
);
41 MOZ_ASSERT(mAwaitingImports
== 0);
44 ModuleLoadRequest(const ModuleLoadRequest
& aOther
) = delete;
45 ModuleLoadRequest(ModuleLoadRequest
&& aOther
) = delete;
48 NS_DECL_ISUPPORTS_INHERITED
49 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ModuleLoadRequest
,
51 using SRIMetadata
= mozilla::dom::SRIMetadata
;
53 ModuleLoadRequest(nsIURI
* aURI
, mozilla::dom::ReferrerPolicy aReferrerPolicy
,
54 ScriptFetchOptions
* aFetchOptions
,
55 const SRIMetadata
& aIntegrity
, nsIURI
* aReferrer
,
56 LoadContextBase
* aContext
, bool aIsTopLevel
,
57 bool aIsDynamicImport
, ModuleLoaderBase
* aLoader
,
58 VisitedURLSet
* aVisitedSet
, ModuleLoadRequest
* aRootModule
);
60 static VisitedURLSet
* NewVisitedSetForTopLevelImport(nsIURI
* aURI
);
62 bool IsTopLevel() const override
{ return mIsTopLevel
; }
64 bool IsDynamicImport() const { return mIsDynamicImport
; }
66 bool IsErrored() const;
68 nsIGlobalObject
* GetGlobalObject();
70 void SetReady() override
;
71 void Cancel() override
;
72 void ClearDynamicImport();
76 void DependenciesLoaded();
79 ModuleLoadRequest
* GetRootModule() {
86 bool IsModuleMarkedForBytecodeEncoding() const {
87 return mIsMarkedForBytecodeEncoding
;
89 void MarkModuleForBytecodeEncoding() {
90 MOZ_ASSERT(!IsModuleMarkedForBytecodeEncoding());
91 mIsMarkedForBytecodeEncoding
= true;
94 // Convenience methods to call into the module loader for this request.
96 void CancelDynamicImport(nsresult aResult
) {
97 MOZ_ASSERT(IsDynamicImport());
98 mLoader
->CancelDynamicImport(this, aResult
);
101 bool IsRegisteredDynamicImport() const {
102 return IsDynamicImport() && mLoader
->HasDynamicImport(this);
105 nsresult
StartModuleLoad() { return mLoader
->StartModuleLoad(this); }
106 nsresult
RestartModuleLoad() { return mLoader
->RestartModuleLoad(this); }
107 nsresult
OnFetchComplete(nsresult aRv
) {
108 return mLoader
->OnFetchComplete(this, aRv
);
110 bool InstantiateModuleGraph() {
111 return mLoader
->InstantiateModuleGraph(this);
113 nsresult
EvaluateModule() { return mLoader
->EvaluateModule(this); }
114 void StartDynamicImport() { mLoader
->StartDynamicImport(this); }
115 void ProcessDynamicImport() { mLoader
->ProcessDynamicImport(this); }
117 void ChildLoadComplete(bool aSuccess
);
121 void CancelImports();
122 void CheckModuleDependenciesLoaded();
124 void AssertAllImportsFinished() const;
125 void AssertAllImportsCancelled() const;
128 // Is this a request for a top level module script or an import?
129 const bool mIsTopLevel
;
131 // Is this the top level request for a dynamic module import?
132 const bool mIsDynamicImport
;
134 // True if this module is planned to be saved in the bytecode cache.
135 // ModuleLoadRequest doesn't use ScriptLoadRequest::mScriptForBytecodeEncoding
136 // field because the JSScript reference isn't always avaialble for module.
137 bool mIsMarkedForBytecodeEncoding
= false;
139 // Pointer to the script loader, used to trigger actions when the module load
141 RefPtr
<ModuleLoaderBase
> mLoader
;
143 // Pointer to the top level module of this module graph, nullptr if this is a
145 RefPtr
<ModuleLoadRequest
> mRootModule
;
147 // Set to a module script object after a successful load or nullptr on
149 RefPtr
<ModuleScript
> mModuleScript
;
151 // Array of imported modules.
152 nsTArray
<RefPtr
<ModuleLoadRequest
>> mImports
;
154 // Parent module (i.e. importer of this module) that is waiting for this
155 // module and its dependencies to load, or null.
156 RefPtr
<ModuleLoadRequest
> mWaitingParentRequest
;
158 // Number of child modules (i.e. imported modules) that this module is waiting
160 size_t mAwaitingImports
= 0;
162 // Set of module URLs visited while fetching the module graph this request is
164 RefPtr
<VisitedURLSet
> mVisitedSet
;
166 // For dynamic imports, the details to pass to FinishDynamicImport.
167 RefPtr
<LoadedScript
> mDynamicReferencingScript
;
168 JS::Heap
<JSString
*> mDynamicSpecifier
;
169 JS::Heap
<JSObject
*> mDynamicPromise
;
172 } // namespace JS::loader
174 #endif // js_loader_ModuleLoadRequest_h