Bug 1852740: add tests for the `fetchpriority` attribute in Link headers. r=necko...
[gecko.git] / js / loader / ModuleLoadRequest.cpp
blob818481a7f30d0e5b5dce6db38a71d682b8bd2157
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, mozilla::dom::ReferrerPolicy aReferrerPolicy,
57 ScriptFetchOptions* aFetchOptions,
58 const mozilla::dom::SRIMetadata& aIntegrity, nsIURI* aReferrer,
59 LoadContextBase* aContext, bool aIsTopLevel, bool aIsDynamicImport,
60 ModuleLoaderBase* aLoader, VisitedURLSet* aVisitedSet,
61 ModuleLoadRequest* aRootModule)
62 : ScriptLoadRequest(ScriptKind::eModule, aURI, aReferrerPolicy,
63 aFetchOptions, aIntegrity, aReferrer, aContext),
64 mIsTopLevel(aIsTopLevel),
65 mIsDynamicImport(aIsDynamicImport),
66 mLoader(aLoader),
67 mRootModule(aRootModule),
68 mVisitedSet(aVisitedSet) {
69 MOZ_ASSERT(mLoader);
72 nsIGlobalObject* ModuleLoadRequest::GetGlobalObject() {
73 return mLoader->GetGlobalObject();
76 bool ModuleLoadRequest::IsErrored() const {
77 return !mModuleScript || mModuleScript->HasParseError();
80 void ModuleLoadRequest::Cancel() {
81 if (IsCanceled()) {
82 AssertAllImportsCancelled();
83 return;
86 if (IsFinished()) {
87 return;
90 ScriptLoadRequest::Cancel();
92 mModuleScript = nullptr;
93 CancelImports();
95 if (mWaitingParentRequest) {
96 ChildLoadComplete(false);
100 void ModuleLoadRequest::SetReady() {
101 MOZ_ASSERT(!IsFinished());
103 // Mark a module as ready to execute. This means that this module and all it
104 // dependencies have had their source loaded, parsed as a module and the
105 // modules instantiated.
107 AssertAllImportsFinished();
109 ScriptLoadRequest::SetReady();
111 if (mWaitingParentRequest) {
112 ChildLoadComplete(true);
116 void ModuleLoadRequest::ModuleLoaded() {
117 // A module that was found to be marked as fetching in the module map has now
118 // been loaded.
120 LOG(("ScriptLoadRequest (%p): Module loaded", this));
122 if (IsCanceled()) {
123 AssertAllImportsCancelled();
124 return;
127 MOZ_ASSERT(IsFetching());
129 mModuleScript = mLoader->GetFetchedModule(mURI);
130 if (IsErrored()) {
131 ModuleErrored();
132 return;
135 mLoader->StartFetchingModuleDependencies(this);
138 void ModuleLoadRequest::LoadFailed() {
139 // We failed to load the source text or an error occurred unrelated to the
140 // content of the module (e.g. OOM).
142 LOG(("ScriptLoadRequest (%p): Module load failed", this));
144 if (IsCanceled()) {
145 AssertAllImportsCancelled();
146 return;
149 MOZ_ASSERT(IsFetching());
150 MOZ_ASSERT(!mModuleScript);
152 Cancel();
153 LoadFinished();
156 void ModuleLoadRequest::ModuleErrored() {
157 // Parse error, failure to resolve imported modules or error loading import.
159 LOG(("ScriptLoadRequest (%p): Module errored", this));
161 if (IsCanceled()) {
162 return;
165 MOZ_ASSERT(!IsFinished());
167 CheckModuleDependenciesLoaded();
168 MOZ_ASSERT(IsErrored());
170 CancelImports();
171 if (IsFinished()) {
172 // Cancelling an outstanding import will error this request.
173 return;
176 SetReady();
177 LoadFinished();
180 void ModuleLoadRequest::DependenciesLoaded() {
181 // The module and all of its dependencies have been successfully fetched and
182 // compiled.
184 LOG(("ScriptLoadRequest (%p): Module dependencies loaded", this));
186 if (IsCanceled()) {
187 return;
190 MOZ_ASSERT(IsLoadingImports());
191 MOZ_ASSERT(!IsErrored());
193 CheckModuleDependenciesLoaded();
194 SetReady();
195 LoadFinished();
198 void ModuleLoadRequest::CheckModuleDependenciesLoaded() {
199 LOG(("ScriptLoadRequest (%p): Check dependencies loaded", this));
201 if (!mModuleScript || mModuleScript->HasParseError()) {
202 return;
204 for (const auto& childRequest : mImports) {
205 ModuleScript* childScript = childRequest->mModuleScript;
206 if (!childScript) {
207 mModuleScript = nullptr;
208 LOG(("ScriptLoadRequest (%p): %p failed (load error)", this,
209 childRequest.get()));
210 return;
214 LOG(("ScriptLoadRequest (%p): all ok", this));
217 void ModuleLoadRequest::CancelImports() {
218 for (size_t i = 0; i < mImports.Length(); i++) {
219 mImports[i]->Cancel();
223 void ModuleLoadRequest::LoadFinished() {
224 RefPtr<ModuleLoadRequest> request(this);
225 if (IsTopLevel() && IsDynamicImport()) {
226 mLoader->RemoveDynamicImport(request);
229 mLoader->OnModuleLoadComplete(request);
232 void ModuleLoadRequest::ClearDynamicImport() {
233 mDynamicReferencingPrivate = JS::UndefinedValue();
234 mDynamicSpecifier = nullptr;
235 mDynamicPromise = nullptr;
238 inline void ModuleLoadRequest::AssertAllImportsFinished() const {
239 #ifdef DEBUG
240 for (const auto& request : mImports) {
241 MOZ_ASSERT(request->IsFinished());
243 #endif
246 inline void ModuleLoadRequest::AssertAllImportsCancelled() const {
247 #ifdef DEBUG
248 for (const auto& request : mImports) {
249 MOZ_ASSERT(request->IsCanceled());
251 #endif
254 } // namespace JS::loader