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 module keys (URL and module type) we have visited
26 // in the process of loading a module graph.
27 class VisitedURLSet
: public nsTHashtable
<ModuleMapKey
> {
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
, JS::ModuleType aModuleType
,
54 mozilla::dom::ReferrerPolicy aReferrerPolicy
,
55 ScriptFetchOptions
* aFetchOptions
,
56 const SRIMetadata
& aIntegrity
, nsIURI
* aReferrer
,
57 LoadContextBase
* aContext
, bool aIsTopLevel
,
58 bool aIsDynamicImport
, ModuleLoaderBase
* aLoader
,
59 VisitedURLSet
* aVisitedSet
, ModuleLoadRequest
* aRootModule
);
61 static VisitedURLSet
* NewVisitedSetForTopLevelImport(
62 nsIURI
* aURI
, JS::ModuleType aModuleType
);
64 bool IsTopLevel() const override
{ return mIsTopLevel
; }
66 bool IsDynamicImport() const { return mIsDynamicImport
; }
68 bool IsErrored() const;
70 nsIGlobalObject
* GetGlobalObject();
72 void SetReady() override
;
73 void Cancel() override
;
75 void SetDynamicImport(LoadedScript
* aReferencingScript
,
76 JS::Handle
<JSString
*> aSpecifier
,
77 JS::Handle
<JSObject
*> aPromise
);
78 void ClearDynamicImport();
82 void DependenciesLoaded();
85 ModuleLoadRequest
* GetRootModule() {
92 void MarkModuleForBytecodeEncoding() { MarkForBytecodeEncoding(); }
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 ChildModuleUnlinked();
126 void AssertAllImportsFinished() const;
127 void AssertAllImportsCancelled() const;
130 // Is this a request for a top level module script or an import?
131 const bool mIsTopLevel
;
133 // Type of module (JavaScript, JSON)
134 const JS::ModuleType mModuleType
;
136 // Is this the top level request for a dynamic module import?
137 const bool mIsDynamicImport
;
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