Bug 1843838 - Rename ScriptLoadRequest::IsReadyToRun to IsFinished since this returns...
[gecko.git] / js / loader / ModuleLoadRequest.cpp
blob362cb8d5df664bc7e7696316780586435a9910fa
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 {
18 #undef LOG
19 #define LOG(args) \
20 MOZ_LOG(ModuleLoaderBase::gModuleLoaderBaseLog, mozilla::LogLevel::Debug, \
21 args)
23 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(ModuleLoadRequest,
24 ScriptLoadRequest)
26 NS_IMPL_CYCLE_COLLECTION_CLASS(ModuleLoadRequest)
28 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ModuleLoadRequest,
29 ScriptLoadRequest)
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,
36 ScriptLoadRequest)
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,
42 ScriptLoadRequest)
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
48 /* static */
49 VisitedURLSet* ModuleLoadRequest::NewVisitedSetForTopLevelImport(nsIURI* aURI) {
50 auto set = new VisitedURLSet();
51 set->PutEntry(aURI);
52 return set;
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,
62 aReferrer, aContext),
63 mIsTopLevel(aIsTopLevel),
64 mIsDynamicImport(aIsDynamicImport),
65 mLoader(aLoader),
66 mRootModule(aRootModule),
67 mVisitedSet(aVisitedSet) {
68 MOZ_ASSERT(mLoader);
71 nsIGlobalObject* ModuleLoadRequest::GetGlobalObject() {
72 return mLoader->GetGlobalObject();
75 bool ModuleLoadRequest::IsErrored() const {
76 return !mModuleScript || mModuleScript->HasParseError();
79 void ModuleLoadRequest::Cancel() {
80 if (IsCanceled()) {
81 AssertAllImportsCancelled();
82 return;
85 if (IsFinished()) {
86 return;
89 ScriptLoadRequest::Cancel();
91 mModuleScript = nullptr;
92 CancelImports();
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
117 // been loaded.
119 LOG(("ScriptLoadRequest (%p): Module loaded", this));
121 if (IsCanceled()) {
122 AssertAllImportsCancelled();
123 return;
126 MOZ_ASSERT(IsFetching());
128 mModuleScript = mLoader->GetFetchedModule(mURI);
129 if (IsErrored()) {
130 ModuleErrored();
131 return;
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));
143 if (IsCanceled()) {
144 AssertAllImportsCancelled();
145 return;
148 MOZ_ASSERT(IsFetching());
149 MOZ_ASSERT(!mModuleScript);
151 Cancel();
152 LoadFinished();
155 void ModuleLoadRequest::ModuleErrored() {
156 // Parse error, failure to resolve imported modules or error loading import.
158 LOG(("ScriptLoadRequest (%p): Module errored", this));
160 if (IsCanceled()) {
161 return;
164 MOZ_ASSERT(!IsFinished());
166 CheckModuleDependenciesLoaded();
167 MOZ_ASSERT(IsErrored());
169 CancelImports();
170 if (IsFinished()) {
171 // Cancelling an outstanding import will error this request.
172 return;
175 SetReady();
176 LoadFinished();
179 void ModuleLoadRequest::DependenciesLoaded() {
180 // The module and all of its dependencies have been successfully fetched and
181 // compiled.
183 LOG(("ScriptLoadRequest (%p): Module dependencies loaded", this));
185 if (IsCanceled()) {
186 return;
189 MOZ_ASSERT(IsLoadingImports());
190 MOZ_ASSERT(!IsErrored());
192 CheckModuleDependenciesLoaded();
193 SetReady();
194 LoadFinished();
197 void ModuleLoadRequest::CheckModuleDependenciesLoaded() {
198 LOG(("ScriptLoadRequest (%p): Check dependencies loaded", this));
200 if (!mModuleScript || mModuleScript->HasParseError()) {
201 return;
203 for (const auto& childRequest : mImports) {
204 ModuleScript* childScript = childRequest->mModuleScript;
205 if (!childScript) {
206 mModuleScript = nullptr;
207 LOG(("ScriptLoadRequest (%p): %p failed (load error)", this,
208 childRequest.get()));
209 return;
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 {
238 #ifdef DEBUG
239 for (const auto& request : mImports) {
240 MOZ_ASSERT(request->IsFinished());
242 #endif
245 inline void ModuleLoadRequest::AssertAllImportsCancelled() const {
246 #ifdef DEBUG
247 for (const auto& request : mImports) {
248 MOZ_ASSERT(request->IsCanceled());
250 #endif
253 } // namespace JS::loader