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 mDynamicReferencingScript
)
33 tmp
->ClearDynamicImport();
34 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
36 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ModuleLoadRequest
,
38 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoader
, mRootModule
, mModuleScript
,
39 mImports
, mWaitingParentRequest
,
40 mDynamicReferencingScript
)
41 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
43 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(ModuleLoadRequest
,
45 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDynamicSpecifier
)
46 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDynamicPromise
)
47 NS_IMPL_CYCLE_COLLECTION_TRACE_END
50 VisitedURLSet
* ModuleLoadRequest::NewVisitedSetForTopLevelImport(nsIURI
* aURI
) {
51 auto set
= new VisitedURLSet();
56 ModuleLoadRequest::ModuleLoadRequest(
57 nsIURI
* aURI
, mozilla::dom::ReferrerPolicy aReferrerPolicy
,
58 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
, aReferrerPolicy
,
64 aFetchOptions
, aIntegrity
, aReferrer
, aContext
),
65 mIsTopLevel(aIsTopLevel
),
66 mIsDynamicImport(aIsDynamicImport
),
68 mRootModule(aRootModule
),
69 mVisitedSet(aVisitedSet
) {
73 nsIGlobalObject
* ModuleLoadRequest::GetGlobalObject() {
74 return mLoader
->GetGlobalObject();
77 bool ModuleLoadRequest::IsErrored() const {
78 return !mModuleScript
|| mModuleScript
->HasParseError();
81 void ModuleLoadRequest::Cancel() {
83 AssertAllImportsCancelled();
91 ScriptLoadRequest::Cancel();
93 mModuleScript
= nullptr;
96 if (mWaitingParentRequest
) {
97 ChildLoadComplete(false);
101 void ModuleLoadRequest::SetReady() {
102 MOZ_ASSERT(!IsFinished());
104 // Mark a module as ready to execute. This means that this module and all it
105 // dependencies have had their source loaded, parsed as a module and the
106 // modules instantiated.
108 AssertAllImportsFinished();
110 ScriptLoadRequest::SetReady();
112 if (mWaitingParentRequest
) {
113 ChildLoadComplete(true);
117 void ModuleLoadRequest::ModuleLoaded() {
118 // A module that was found to be marked as fetching in the module map has now
121 LOG(("ScriptLoadRequest (%p): Module loaded", this));
124 AssertAllImportsCancelled();
128 MOZ_ASSERT(IsFetching() || IsPendingFetchingError());
130 mModuleScript
= mLoader
->GetFetchedModule(mURI
);
136 mLoader
->StartFetchingModuleDependencies(this);
139 void ModuleLoadRequest::LoadFailed() {
140 // We failed to load the source text or an error occurred unrelated to the
141 // content of the module (e.g. OOM).
143 LOG(("ScriptLoadRequest (%p): Module load failed", this));
146 AssertAllImportsCancelled();
150 MOZ_ASSERT(IsFetching() || IsPendingFetchingError());
151 MOZ_ASSERT(!mModuleScript
);
157 void ModuleLoadRequest::ModuleErrored() {
158 // Parse error, failure to resolve imported modules or error loading import.
160 LOG(("ScriptLoadRequest (%p): Module errored", this));
166 MOZ_ASSERT(!IsFinished());
168 CheckModuleDependenciesLoaded();
169 MOZ_ASSERT(IsErrored());
173 // Cancelling an outstanding import will error this request.
181 void ModuleLoadRequest::DependenciesLoaded() {
182 // The module and all of its dependencies have been successfully fetched and
185 LOG(("ScriptLoadRequest (%p): Module dependencies loaded", this));
191 MOZ_ASSERT(IsLoadingImports());
192 MOZ_ASSERT(!IsErrored());
194 CheckModuleDependenciesLoaded();
199 void ModuleLoadRequest::CheckModuleDependenciesLoaded() {
200 LOG(("ScriptLoadRequest (%p): Check dependencies loaded", this));
202 if (!mModuleScript
|| mModuleScript
->HasParseError()) {
205 for (const auto& childRequest
: mImports
) {
206 ModuleScript
* childScript
= childRequest
->mModuleScript
;
208 mModuleScript
= nullptr;
209 LOG(("ScriptLoadRequest (%p): %p failed (load error)", this,
210 childRequest
.get()));
215 LOG(("ScriptLoadRequest (%p): all ok", this));
218 void ModuleLoadRequest::CancelImports() {
219 for (size_t i
= 0; i
< mImports
.Length(); i
++) {
220 mImports
[i
]->Cancel();
224 void ModuleLoadRequest::LoadFinished() {
225 RefPtr
<ModuleLoadRequest
> request(this);
226 if (IsTopLevel() && IsDynamicImport()) {
227 mLoader
->RemoveDynamicImport(request
);
230 mLoader
->OnModuleLoadComplete(request
);
233 void ModuleLoadRequest::SetDynamicImport(LoadedScript
* aReferencingScript
,
234 JS::Handle
<JSString
*> aSpecifier
,
235 JS::Handle
<JSObject
*> aPromise
) {
236 mDynamicReferencingScript
= aReferencingScript
;
237 mDynamicSpecifier
= aSpecifier
;
238 mDynamicPromise
= aPromise
;
240 mozilla::HoldJSObjects(this);
243 void ModuleLoadRequest::ClearDynamicImport() {
244 mDynamicReferencingScript
= nullptr;
245 mDynamicSpecifier
= nullptr;
246 mDynamicPromise
= nullptr;
249 inline void ModuleLoadRequest::AssertAllImportsFinished() const {
251 for (const auto& request
: mImports
) {
252 MOZ_ASSERT(request
->IsFinished());
257 inline void ModuleLoadRequest::AssertAllImportsCancelled() const {
259 for (const auto& request
: mImports
) {
260 MOZ_ASSERT(request
->IsCanceled());
265 } // namespace JS::loader