summaryrefslogtreecommitdiffstats
path: root/dom/script/ModuleLoadRequest.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/script/ModuleLoadRequest.cpp218
1 files changed, 218 insertions, 0 deletions
diff --git a/dom/script/ModuleLoadRequest.cpp b/dom/script/ModuleLoadRequest.cpp
new file mode 100644
index 0000000000..c2771e6d46
--- /dev/null
+++ b/dom/script/ModuleLoadRequest.cpp
@@ -0,0 +1,218 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ModuleLoadRequest.h"
+
+#include "mozilla/HoldDropJSObjects.h"
+
+#include "LoadedScript.h"
+#include "ScriptLoader.h"
+
+namespace mozilla {
+namespace dom {
+
+#undef LOG
+#define LOG(args) \
+ MOZ_LOG(ScriptLoader::gScriptLoaderLog, mozilla::LogLevel::Debug, args)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ModuleLoadRequest)
+NS_INTERFACE_MAP_END_INHERITING(ScriptLoadRequest)
+
+NS_IMPL_CYCLE_COLLECTION_MULTI_ZONE_JSHOLDER_CLASS(ModuleLoadRequest)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ModuleLoadRequest,
+ ScriptLoadRequest)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader, mModuleScript, mImports)
+ tmp->ClearDynamicImport();
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ModuleLoadRequest,
+ ScriptLoadRequest)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoader, mModuleScript, mImports)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(ModuleLoadRequest,
+ ScriptLoadRequest)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDynamicReferencingPrivate)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDynamicSpecifier)
+ NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDynamicPromise)
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_ADDREF_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
+NS_IMPL_RELEASE_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
+
+static VisitedURLSet* NewVisitedSetForTopLevelImport(nsIURI* aURI) {
+ auto set = new VisitedURLSet();
+ set->PutEntry(aURI);
+ return set;
+}
+
+/* static */
+ModuleLoadRequest* ModuleLoadRequest::CreateTopLevel(
+ nsIURI* aURI, ScriptFetchOptions* aFetchOptions,
+ const SRIMetadata& aIntegrity, nsIURI* aReferrer, ScriptLoader* aLoader) {
+ return new ModuleLoadRequest(aURI, aFetchOptions, aIntegrity, aReferrer,
+ true, /* is top level */
+ false, /* is dynamic import */
+ aLoader, NewVisitedSetForTopLevelImport(aURI));
+}
+
+/* static */
+ModuleLoadRequest* ModuleLoadRequest::CreateStaticImport(
+ nsIURI* aURI, ModuleLoadRequest* aParent) {
+ auto request =
+ new ModuleLoadRequest(aURI, aParent->mFetchOptions, SRIMetadata(),
+ aParent->mURI, false, /* is top level */
+ false, /* is dynamic import */
+ aParent->mLoader, aParent->mVisitedSet);
+
+ request->mIsInline = false;
+ request->mScriptMode = aParent->mScriptMode;
+
+ return request;
+}
+
+/* static */
+ModuleLoadRequest* ModuleLoadRequest::CreateDynamicImport(
+ nsIURI* aURI, ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL,
+ ScriptLoader* aLoader, JS::Handle<JS::Value> aReferencingPrivate,
+ JS::Handle<JSString*> aSpecifier, JS::Handle<JSObject*> aPromise) {
+ MOZ_ASSERT(aSpecifier);
+ MOZ_ASSERT(aPromise);
+
+ auto request = new ModuleLoadRequest(
+ aURI, aFetchOptions, SRIMetadata(), aBaseURL, true, /* is top level */
+ true, /* is dynamic import */
+ aLoader, NewVisitedSetForTopLevelImport(aURI));
+
+ request->mIsInline = false;
+ request->mScriptMode = ScriptMode::eAsync;
+ request->mDynamicReferencingPrivate = aReferencingPrivate;
+ request->mDynamicSpecifier = aSpecifier;
+ request->mDynamicPromise = aPromise;
+
+ HoldJSObjects(request);
+
+ return request;
+}
+
+ModuleLoadRequest::ModuleLoadRequest(
+ nsIURI* aURI, ScriptFetchOptions* aFetchOptions,
+ const SRIMetadata& aIntegrity, nsIURI* aReferrer, bool aIsTopLevel,
+ bool aIsDynamicImport, ScriptLoader* aLoader, VisitedURLSet* aVisitedSet)
+ : ScriptLoadRequest(ScriptKind::eModule, aURI, aFetchOptions, aIntegrity,
+ aReferrer),
+ mIsTopLevel(aIsTopLevel),
+ mIsDynamicImport(aIsDynamicImport),
+ mLoader(aLoader),
+ mVisitedSet(aVisitedSet) {}
+
+void ModuleLoadRequest::Cancel() {
+ ScriptLoadRequest::Cancel();
+ mModuleScript = nullptr;
+ mProgress = ScriptLoadRequest::Progress::eReady;
+ CancelImports();
+ mReady.RejectIfExists(NS_ERROR_DOM_ABORT_ERR, __func__);
+}
+
+void ModuleLoadRequest::CancelImports() {
+ for (size_t i = 0; i < mImports.Length(); i++) {
+ mImports[i]->Cancel();
+ }
+}
+
+void ModuleLoadRequest::SetReady() {
+ // Mark a module as ready to execute. This means that this module and all it
+ // dependencies have had their source loaded, parsed as a module and the
+ // modules instantiated.
+ //
+ // The mReady promise is used to ensure that when all dependencies of a module
+ // have become ready, DependenciesLoaded is called on that module
+ // request. This is set up in StartFetchingModuleDependencies.
+
+#ifdef DEBUG
+ for (size_t i = 0; i < mImports.Length(); i++) {
+ MOZ_ASSERT(mImports[i]->IsReadyToRun());
+ }
+#endif
+
+ ScriptLoadRequest::SetReady();
+ mReady.ResolveIfExists(true, __func__);
+}
+
+void ModuleLoadRequest::ModuleLoaded() {
+ // A module that was found to be marked as fetching in the module map has now
+ // been loaded.
+
+ LOG(("ScriptLoadRequest (%p): Module loaded", this));
+
+ mModuleScript = mLoader->GetFetchedModule(mURI);
+ if (!mModuleScript || mModuleScript->HasParseError()) {
+ ModuleErrored();
+ return;
+ }
+
+ mLoader->StartFetchingModuleDependencies(this);
+}
+
+void ModuleLoadRequest::ModuleErrored() {
+ if (IsCanceled()) {
+ return;
+ }
+
+ LOG(("ScriptLoadRequest (%p): Module errored", this));
+
+ mLoader->CheckModuleDependenciesLoaded(this);
+ MOZ_ASSERT(!mModuleScript || mModuleScript->HasParseError());
+
+ CancelImports();
+ SetReady();
+ LoadFinished();
+}
+
+void ModuleLoadRequest::DependenciesLoaded() {
+ if (IsCanceled()) {
+ return;
+ }
+
+ // The module and all of its dependencies have been successfully fetched and
+ // compiled.
+
+ LOG(("ScriptLoadRequest (%p): Module dependencies loaded", this));
+
+ MOZ_ASSERT(mModuleScript);
+
+ mLoader->CheckModuleDependenciesLoaded(this);
+ SetReady();
+ LoadFinished();
+}
+
+void ModuleLoadRequest::LoadFailed() {
+ // We failed to load the source text or an error occurred unrelated to the
+ // content of the module (e.g. OOM).
+
+ LOG(("ScriptLoadRequest (%p): Module load failed", this));
+
+ MOZ_ASSERT(!mModuleScript);
+
+ Cancel();
+ LoadFinished();
+}
+
+void ModuleLoadRequest::LoadFinished() {
+ mLoader->ProcessLoadedModuleTree(this);
+
+ mLoader = nullptr;
+}
+
+void ModuleLoadRequest::ClearDynamicImport() {
+ mDynamicReferencingPrivate = JS::UndefinedValue();
+ mDynamicSpecifier = nullptr;
+ mDynamicPromise = nullptr;
+}
+
+} // namespace dom
+} // namespace mozilla