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
{
22 class ModuleLoaderBase
;
24 // A reference counted set of URLs we have visited in the process of loading a
26 class VisitedURLSet
: public nsTHashtable
<nsURIHashKey
> {
27 NS_INLINE_DECL_REFCOUNTING(VisitedURLSet
)
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;
47 NS_DECL_ISUPPORTS_INHERITED
48 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ModuleLoadRequest
,
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();
74 void DependenciesLoaded();
77 ModuleLoadRequest
* GetRootModule() {
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
);
99 bool IsRegisteredDynamicImport() const {
100 return IsDynamicImport() && mLoader
->HasDynamicImport(this);
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
);
119 void CancelImports();
120 void CheckModuleDependenciesLoaded();
122 void AssertAllImportsFinished() const;
123 void AssertAllImportsCancelled() const;
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
139 RefPtr
<ModuleLoaderBase
> mLoader
;
141 // Pointer to the top level module of this module graph, nullptr if this is a
143 RefPtr
<ModuleLoadRequest
> mRootModule
;
145 // Set to a module script object after a successful load or nullptr on
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
158 size_t mAwaitingImports
= 0;
160 // Set of module URLs visited while fetching the module graph this request is
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