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_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ModuleLoadRequest
)
24 NS_INTERFACE_MAP_END_INHERITING(ScriptLoadRequest
)
26 NS_IMPL_CYCLE_COLLECTION_MULTI_ZONE_JSHOLDER_CLASS(ModuleLoadRequest
)
28 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ModuleLoadRequest
,
30 NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader
, mModuleScript
, mImports
, mRootModule
)
31 tmp
->ClearDynamicImport();
32 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
34 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ModuleLoadRequest
,
36 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoader
, mModuleScript
, mImports
,
38 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
40 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(ModuleLoadRequest
,
42 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDynamicReferencingPrivate
)
43 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDynamicSpecifier
)
44 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDynamicPromise
)
45 NS_IMPL_CYCLE_COLLECTION_TRACE_END
47 NS_IMPL_ADDREF_INHERITED(ModuleLoadRequest
, ScriptLoadRequest
)
48 NS_IMPL_RELEASE_INHERITED(ModuleLoadRequest
, ScriptLoadRequest
)
51 VisitedURLSet
* ModuleLoadRequest::NewVisitedSetForTopLevelImport(nsIURI
* aURI
) {
52 auto set
= new VisitedURLSet();
57 ModuleLoadRequest::ModuleLoadRequest(
58 nsIURI
* aURI
, ScriptFetchOptions
* aFetchOptions
,
59 const mozilla::dom::SRIMetadata
& aIntegrity
, nsIURI
* aReferrer
,
60 LoadContextBase
* aContext
, bool aIsTopLevel
, bool aIsDynamicImport
,
61 ModuleLoaderBase
* aLoader
, VisitedURLSet
* aVisitedSet
,
62 ModuleLoadRequest
* aRootModule
)
63 : ScriptLoadRequest(ScriptKind::eModule
, aURI
, aFetchOptions
, aIntegrity
,
65 mIsTopLevel(aIsTopLevel
),
66 mIsDynamicImport(aIsDynamicImport
),
68 mRootModule(aRootModule
),
69 mVisitedSet(aVisitedSet
) {
73 nsIGlobalObject
* ModuleLoadRequest::GetGlobalObject() {
74 return mLoader
->GetGlobalObject();
77 void ModuleLoadRequest::Cancel() {
78 ScriptLoadRequest::Cancel();
79 mModuleScript
= nullptr;
81 mReady
.RejectIfExists(NS_ERROR_DOM_ABORT_ERR
, __func__
);
84 void ModuleLoadRequest::CancelImports() {
85 for (size_t i
= 0; i
< mImports
.Length(); i
++) {
86 mImports
[i
]->Cancel();
90 void ModuleLoadRequest::SetReady() {
91 // Mark a module as ready to execute. This means that this module and all it
92 // dependencies have had their source loaded, parsed as a module and the
93 // modules instantiated.
95 // The mReady promise is used to ensure that when all dependencies of a module
96 // have become ready, DependenciesLoaded is called on that module
97 // request. This is set up in StartFetchingModuleDependencies.
100 for (size_t i
= 0; i
< mImports
.Length(); i
++) {
101 MOZ_ASSERT(mImports
[i
]->IsReadyToRun());
105 ScriptLoadRequest::SetReady();
106 mReady
.ResolveIfExists(true, __func__
);
109 void ModuleLoadRequest::ModuleLoaded() {
110 // A module that was found to be marked as fetching in the module map has now
113 LOG(("ScriptLoadRequest (%p): Module loaded", this));
115 mModuleScript
= mLoader
->GetFetchedModule(mURI
);
116 if (!mModuleScript
|| mModuleScript
->HasParseError()) {
121 mLoader
->StartFetchingModuleDependencies(this);
124 void ModuleLoadRequest::ModuleErrored() {
129 LOG(("ScriptLoadRequest (%p): Module errored", this));
131 CheckModuleDependenciesLoaded();
132 MOZ_ASSERT(!mModuleScript
|| mModuleScript
->HasParseError());
139 void ModuleLoadRequest::DependenciesLoaded() {
144 // The module and all of its dependencies have been successfully fetched and
147 LOG(("ScriptLoadRequest (%p): Module dependencies loaded", this));
149 MOZ_ASSERT(mModuleScript
);
151 CheckModuleDependenciesLoaded();
156 void ModuleLoadRequest::CheckModuleDependenciesLoaded() {
157 LOG(("ScriptLoadRequest (%p): Check dependencies loaded", this));
159 if (!mModuleScript
|| mModuleScript
->HasParseError()) {
162 for (const auto& childRequest
: mImports
) {
163 ModuleScript
* childScript
= childRequest
->mModuleScript
;
165 mModuleScript
= nullptr;
166 LOG(("ScriptLoadRequest (%p): %p failed (load error)", this,
167 childRequest
.get()));
172 LOG(("ScriptLoadRequest (%p): all ok", this));
175 void ModuleLoadRequest::LoadFailed() {
176 // We failed to load the source text or an error occurred unrelated to the
177 // content of the module (e.g. OOM).
179 LOG(("ScriptLoadRequest (%p): Module load failed", this));
181 MOZ_ASSERT(!mModuleScript
);
187 void ModuleLoadRequest::LoadFinished() {
188 RefPtr
<ModuleLoadRequest
> request(this);
189 if (IsTopLevel() && IsDynamicImport()) {
190 mLoader
->RemoveDynamicImport(request
);
193 mLoader
->OnModuleLoadComplete(request
);
196 void ModuleLoadRequest::ClearDynamicImport() {
197 mDynamicReferencingPrivate
= JS::UndefinedValue();
198 mDynamicSpecifier
= nullptr;
199 mDynamicPromise
= nullptr;
202 } // namespace JS::loader