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 #include "ModuleLoadRequest.h"
9 #include "mozilla/HoldDropJSObjects.h"
10 #include "mozilla/dom/ScriptLoadContext.h"
12 #include "LoadedScript.h"
13 #include "LoadContextBase.h"
14 #include "ModuleLoaderBase.h"
16 namespace JS::loader
{
20 MOZ_LOG(ModuleLoaderBase::gModuleLoaderBaseLog, mozilla::LogLevel::Debug, \
23 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(ModuleLoadRequest
,
26 NS_IMPL_CYCLE_COLLECTION_CLASS(ModuleLoadRequest
)
28 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ModuleLoadRequest
,
30 NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader
, mRootModule
, mModuleScript
, mImports
,
31 mWaitingParentRequest
)
32 tmp
->ClearDynamicImport();
33 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
35 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ModuleLoadRequest
,
37 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoader
, mRootModule
, mModuleScript
,
38 mImports
, mWaitingParentRequest
)
39 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
41 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(ModuleLoadRequest
,
43 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDynamicReferencingPrivate
)
44 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDynamicSpecifier
)
45 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDynamicPromise
)
46 NS_IMPL_CYCLE_COLLECTION_TRACE_END
49 VisitedURLSet
* ModuleLoadRequest::NewVisitedSetForTopLevelImport(nsIURI
* aURI
) {
50 auto set
= new VisitedURLSet();
55 ModuleLoadRequest::ModuleLoadRequest(
56 nsIURI
* aURI
, ScriptFetchOptions
* aFetchOptions
,
57 const mozilla::dom::SRIMetadata
& aIntegrity
, nsIURI
* aReferrer
,
58 LoadContextBase
* aContext
, bool aIsTopLevel
, bool aIsDynamicImport
,
59 ModuleLoaderBase
* aLoader
, VisitedURLSet
* aVisitedSet
,
60 ModuleLoadRequest
* aRootModule
)
61 : ScriptLoadRequest(ScriptKind::eModule
, aURI
, aFetchOptions
, aIntegrity
,
63 mIsTopLevel(aIsTopLevel
),
64 mIsDynamicImport(aIsDynamicImport
),
66 mRootModule(aRootModule
),
67 mVisitedSet(aVisitedSet
) {
71 nsIGlobalObject
* ModuleLoadRequest::GetGlobalObject() {
72 return mLoader
->GetGlobalObject();
75 bool ModuleLoadRequest::IsErrored() const {
76 return !mModuleScript
|| mModuleScript
->HasParseError();
79 void ModuleLoadRequest::Cancel() {
81 AssertAllImportsCancelled();
89 ScriptLoadRequest::Cancel();
91 mModuleScript
= nullptr;
94 if (mWaitingParentRequest
) {
95 ChildLoadComplete(false);
99 void ModuleLoadRequest::SetReady() {
100 MOZ_ASSERT(!IsFinished());
102 // Mark a module as ready to execute. This means that this module and all it
103 // dependencies have had their source loaded, parsed as a module and the
104 // modules instantiated.
106 AssertAllImportsFinished();
108 ScriptLoadRequest::SetReady();
110 if (mWaitingParentRequest
) {
111 ChildLoadComplete(true);
115 void ModuleLoadRequest::ModuleLoaded() {
116 // A module that was found to be marked as fetching in the module map has now
119 LOG(("ScriptLoadRequest (%p): Module loaded", this));
122 AssertAllImportsCancelled();
126 MOZ_ASSERT(IsFetching());
128 mModuleScript
= mLoader
->GetFetchedModule(mURI
);
134 mLoader
->StartFetchingModuleDependencies(this);
137 void ModuleLoadRequest::LoadFailed() {
138 // We failed to load the source text or an error occurred unrelated to the
139 // content of the module (e.g. OOM).
141 LOG(("ScriptLoadRequest (%p): Module load failed", this));
144 AssertAllImportsCancelled();
148 MOZ_ASSERT(IsFetching());
149 MOZ_ASSERT(!mModuleScript
);
155 void ModuleLoadRequest::ModuleErrored() {
156 // Parse error, failure to resolve imported modules or error loading import.
158 LOG(("ScriptLoadRequest (%p): Module errored", this));
164 MOZ_ASSERT(!IsFinished());
166 CheckModuleDependenciesLoaded();
167 MOZ_ASSERT(IsErrored());
171 // Cancelling an outstanding import will error this request.
179 void ModuleLoadRequest::DependenciesLoaded() {
180 // The module and all of its dependencies have been successfully fetched and
183 LOG(("ScriptLoadRequest (%p): Module dependencies loaded", this));
189 MOZ_ASSERT(IsLoadingImports());
190 MOZ_ASSERT(!IsErrored());
192 CheckModuleDependenciesLoaded();
197 void ModuleLoadRequest::CheckModuleDependenciesLoaded() {
198 LOG(("ScriptLoadRequest (%p): Check dependencies loaded", this));
200 if (!mModuleScript
|| mModuleScript
->HasParseError()) {
203 for (const auto& childRequest
: mImports
) {
204 ModuleScript
* childScript
= childRequest
->mModuleScript
;
206 mModuleScript
= nullptr;
207 LOG(("ScriptLoadRequest (%p): %p failed (load error)", this,
208 childRequest
.get()));
213 LOG(("ScriptLoadRequest (%p): all ok", this));
216 void ModuleLoadRequest::CancelImports() {
217 for (size_t i
= 0; i
< mImports
.Length(); i
++) {
218 mImports
[i
]->Cancel();
222 void ModuleLoadRequest::LoadFinished() {
223 RefPtr
<ModuleLoadRequest
> request(this);
224 if (IsTopLevel() && IsDynamicImport()) {
225 mLoader
->RemoveDynamicImport(request
);
228 mLoader
->OnModuleLoadComplete(request
);
231 void ModuleLoadRequest::ClearDynamicImport() {
232 mDynamicReferencingPrivate
= JS::UndefinedValue();
233 mDynamicSpecifier
= nullptr;
234 mDynamicPromise
= nullptr;
237 inline void ModuleLoadRequest::AssertAllImportsFinished() const {
239 for (const auto& request
: mImports
) {
240 MOZ_ASSERT(request
->IsFinished());
245 inline void ModuleLoadRequest::AssertAllImportsCancelled() const {
247 for (const auto& request
: mImports
) {
248 MOZ_ASSERT(request
->IsCanceled());
253 } // namespace JS::loader