2022-02-17 18:57:51 +03:00
|
|
|
/* -*- 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/. */
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
#include "GeckoProfiler.h"
|
|
|
|
#include "LoadedScript.h"
|
2022-02-21 18:39:09 +03:00
|
|
|
#include "ModuleLoadRequest.h"
|
2022-02-18 01:00:41 +03:00
|
|
|
#include "ScriptLoadRequest.h"
|
2022-02-21 18:39:08 +03:00
|
|
|
#include "mozilla/dom/ScriptTrace.h"
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
#include "js/Array.h" // JS::GetArrayLength
|
|
|
|
#include "js/CompilationAndEvaluation.h"
|
|
|
|
#include "js/ContextOptions.h" // JS::ContextOptionsRef
|
|
|
|
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
|
2022-02-17 18:57:51 +03:00
|
|
|
#include "js/Modules.h" // JS::FinishDynamicModuleImport, JS::{G,S}etModuleResolveHook, JS::Get{ModulePrivate,ModuleScript,RequestedModule{s,Specifier,SourcePos}}, JS::SetModule{DynamicImport,Metadata}Hook
|
|
|
|
#include "js/OffThreadScriptCompilation.h"
|
2022-02-18 01:00:41 +03:00
|
|
|
#include "js/PropertyAndElement.h" // JS_DefineProperty, JS_GetElement
|
2022-02-17 18:57:51 +03:00
|
|
|
#include "js/SourceText.h"
|
2022-03-28 15:38:28 +03:00
|
|
|
#include "mozilla/BasePrincipal.h"
|
2022-02-17 18:57:51 +03:00
|
|
|
#include "mozilla/dom/AutoEntryScript.h"
|
2022-02-18 01:00:41 +03:00
|
|
|
#include "mozilla/CycleCollectedJSContext.h" // nsAutoMicroTask
|
2022-03-28 15:38:28 +03:00
|
|
|
#include "mozilla/Preferences.h"
|
2022-02-18 01:00:41 +03:00
|
|
|
#include "nsContentUtils.h"
|
2022-03-28 18:56:10 +03:00
|
|
|
#include "nsICacheInfoChannel.h" // nsICacheInfoChannel
|
2022-02-18 01:00:41 +03:00
|
|
|
#include "nsNetUtil.h" // NS_NewURI
|
2022-03-28 18:56:10 +03:00
|
|
|
#include "nsThreadUtils.h" // GetMainThreadSerialEventTarget
|
2022-03-28 15:38:28 +03:00
|
|
|
#include "xpcpublic.h"
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-03-28 18:56:10 +03:00
|
|
|
using mozilla::GetMainThreadSerialEventTarget;
|
2022-03-28 15:38:28 +03:00
|
|
|
using mozilla::Preferences;
|
|
|
|
using mozilla::dom::AutoJSAPI;
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-21 18:39:09 +03:00
|
|
|
namespace JS::loader {
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-21 18:39:09 +03:00
|
|
|
mozilla::LazyLogModule ModuleLoaderBase::gCspPRLog("CSP");
|
|
|
|
mozilla::LazyLogModule ModuleLoaderBase::gModuleLoaderBaseLog(
|
|
|
|
"ModuleLoaderBase");
|
2022-02-18 01:00:41 +03:00
|
|
|
|
2022-02-17 18:57:51 +03:00
|
|
|
#undef LOG
|
2022-02-21 18:39:07 +03:00
|
|
|
#define LOG(args) \
|
|
|
|
MOZ_LOG(ModuleLoaderBase::gModuleLoaderBaseLog, mozilla::LogLevel::Debug, \
|
|
|
|
args)
|
2022-02-17 18:57:51 +03:00
|
|
|
|
|
|
|
#define LOG_ENABLED() \
|
2022-02-21 18:39:07 +03:00
|
|
|
MOZ_LOG_TEST(ModuleLoaderBase::gModuleLoaderBaseLog, mozilla::LogLevel::Debug)
|
|
|
|
// ModuleLoaderBase
|
2022-02-18 01:00:41 +03:00
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ModuleLoaderBase)
|
2022-02-18 01:00:41 +03:00
|
|
|
NS_INTERFACE_MAP_END
|
|
|
|
|
2022-04-11 18:35:29 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION(ModuleLoaderBase, mFetchedModules,
|
2022-04-11 18:35:29 +03:00
|
|
|
mDynamicImportRequests, mGlobalObject, mLoader)
|
2022-02-18 01:00:41 +03:00
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(ModuleLoaderBase)
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(ModuleLoaderBase)
|
2022-02-18 01:00:41 +03:00
|
|
|
|
2022-03-28 15:38:28 +03:00
|
|
|
// static
|
|
|
|
void ModuleLoaderBase::EnsureModuleHooksInitialized() {
|
|
|
|
AutoJSAPI jsapi;
|
|
|
|
jsapi.Init();
|
|
|
|
JSRuntime* rt = JS_GetRuntime(jsapi.cx());
|
|
|
|
if (JS::GetModuleResolveHook(rt)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
JS::SetModuleResolveHook(rt, HostResolveImportedModule);
|
|
|
|
JS::SetModuleMetadataHook(rt, HostPopulateImportMeta);
|
|
|
|
JS::SetScriptPrivateReferenceHooks(rt, HostAddRefTopLevelScript,
|
|
|
|
HostReleaseTopLevelScript);
|
|
|
|
JS::SetSupportedAssertionsHook(rt, HostGetSupportedImportAssertions);
|
|
|
|
|
|
|
|
Preferences::RegisterCallbackAndCall(DynamicImportPrefChangedCallback,
|
|
|
|
"javascript.options.dynamicImport",
|
|
|
|
(void*)nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
void ModuleLoaderBase::DynamicImportPrefChangedCallback(const char* aPrefName,
|
|
|
|
void* aClosure) {
|
|
|
|
bool enabled = Preferences::GetBool(aPrefName);
|
|
|
|
JS::ModuleDynamicImportHook hook =
|
|
|
|
enabled ? HostImportModuleDynamically : nullptr;
|
|
|
|
|
|
|
|
AutoJSAPI jsapi;
|
|
|
|
jsapi.Init();
|
|
|
|
JSRuntime* rt = JS_GetRuntime(jsapi.cx());
|
|
|
|
JS::SetModuleDynamicImportHook(rt, hook);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 8.1.3.8.1 HostResolveImportedModule(referencingModule, moduleRequest)
|
|
|
|
/**
|
|
|
|
* Implement the HostResolveImportedModule abstract operation.
|
|
|
|
*
|
|
|
|
* Resolve a module specifier string and look this up in the module
|
|
|
|
* map, returning the result. This is only called for previously
|
|
|
|
* loaded modules and always succeeds.
|
|
|
|
*
|
|
|
|
* @param aReferencingPrivate A JS::Value which is either undefined
|
|
|
|
* or contains a LoadedScript private pointer.
|
|
|
|
* @param aModuleRequest A module request object.
|
|
|
|
* @returns module This is set to the module found.
|
|
|
|
*/
|
|
|
|
// static
|
|
|
|
JSObject* ModuleLoaderBase::HostResolveImportedModule(
|
|
|
|
JSContext* aCx, JS::Handle<JS::Value> aReferencingPrivate,
|
|
|
|
JS::Handle<JSObject*> aModuleRequest) {
|
|
|
|
JS::Rooted<JSObject*> module(aCx);
|
|
|
|
|
|
|
|
{
|
|
|
|
// LoadedScript should only live in this block, otherwise it will be a GC
|
|
|
|
// hazard
|
|
|
|
RefPtr<LoadedScript> script(
|
|
|
|
GetLoadedScriptOrNull(aCx, aReferencingPrivate));
|
|
|
|
|
|
|
|
JS::Rooted<JSString*> specifierString(
|
|
|
|
aCx, JS::GetModuleRequestSpecifier(aCx, aModuleRequest));
|
|
|
|
if (!specifierString) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Let url be the result of resolving a module specifier given referencing
|
|
|
|
// module script and specifier.
|
|
|
|
nsAutoJSString string;
|
|
|
|
if (!string.init(aCx, specifierString)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<ModuleLoaderBase> loader = GetCurrentModuleLoader(aCx);
|
|
|
|
if (!loader) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-04-11 18:35:27 +03:00
|
|
|
nsCOMPtr<nsIURI> uri = loader->ResolveModuleSpecifier(script, string);
|
2022-03-28 15:38:28 +03:00
|
|
|
|
|
|
|
// This cannot fail because resolving a module specifier must have been
|
|
|
|
// previously successful with these same two arguments.
|
|
|
|
MOZ_ASSERT(uri, "Failed to resolve previously-resolved module specifier");
|
|
|
|
|
|
|
|
// Let resolved module script be moduleMap[url]. (This entry must exist for
|
|
|
|
// us to have gotten to this point.)
|
2022-04-11 18:35:29 +03:00
|
|
|
ModuleScript* ms = loader->GetFetchedModule(uri);
|
2022-03-28 15:38:28 +03:00
|
|
|
MOZ_ASSERT(ms, "Resolved module not found in module map");
|
|
|
|
MOZ_ASSERT(!ms->HasParseError());
|
|
|
|
MOZ_ASSERT(ms->ModuleRecord());
|
|
|
|
|
|
|
|
module.set(ms->ModuleRecord());
|
|
|
|
}
|
|
|
|
return module;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
bool ModuleLoaderBase::HostPopulateImportMeta(
|
|
|
|
JSContext* aCx, JS::Handle<JS::Value> aReferencingPrivate,
|
|
|
|
JS::Handle<JSObject*> aMetaObject) {
|
|
|
|
RefPtr<ModuleScript> script =
|
|
|
|
static_cast<ModuleScript*>(aReferencingPrivate.toPrivate());
|
|
|
|
MOZ_ASSERT(script->IsModuleScript());
|
|
|
|
MOZ_ASSERT(JS::GetModulePrivate(script->ModuleRecord()) ==
|
|
|
|
aReferencingPrivate);
|
|
|
|
|
|
|
|
nsAutoCString url;
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(script->BaseURL());
|
|
|
|
MOZ_ALWAYS_SUCCEEDS(script->BaseURL()->GetAsciiSpec(url));
|
|
|
|
|
|
|
|
JS::Rooted<JSString*> urlString(aCx, JS_NewStringCopyZ(aCx, url.get()));
|
|
|
|
if (!urlString) {
|
|
|
|
JS_ReportOutOfMemory(aCx);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return JS_DefineProperty(aCx, aMetaObject, "url", urlString,
|
|
|
|
JSPROP_ENUMERATE);
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
bool ModuleLoaderBase::HostImportModuleDynamically(
|
|
|
|
JSContext* aCx, JS::Handle<JS::Value> aReferencingPrivate,
|
|
|
|
JS::Handle<JSObject*> aModuleRequest, JS::Handle<JSObject*> aPromise) {
|
|
|
|
RefPtr<LoadedScript> script(GetLoadedScriptOrNull(aCx, aReferencingPrivate));
|
|
|
|
|
|
|
|
JS::Rooted<JSString*> specifierString(
|
|
|
|
aCx, JS::GetModuleRequestSpecifier(aCx, aModuleRequest));
|
|
|
|
if (!specifierString) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Attempt to resolve the module specifier.
|
|
|
|
nsAutoJSString specifier;
|
|
|
|
if (!specifier.init(aCx, specifierString)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<ModuleLoaderBase> loader = GetCurrentModuleLoader(aCx);
|
|
|
|
if (!loader) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-04-11 18:35:27 +03:00
|
|
|
nsCOMPtr<nsIURI> uri = loader->ResolveModuleSpecifier(script, specifier);
|
2022-03-28 15:38:28 +03:00
|
|
|
if (!uri) {
|
|
|
|
JS::Rooted<JS::Value> error(aCx);
|
|
|
|
nsresult rv = ModuleLoaderBase::HandleResolveFailure(aCx, script, specifier,
|
|
|
|
0, 0, &error);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
JS_ReportOutOfMemory(aCx);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
JS_SetPendingException(aCx, error);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a new top-level load request.
|
|
|
|
RefPtr<ModuleLoadRequest> request = loader->CreateDynamicImport(
|
|
|
|
aCx, uri, script, aReferencingPrivate, specifierString, aPromise);
|
|
|
|
|
|
|
|
loader->StartDynamicImport(request);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ModuleLoaderBase::HostGetSupportedImportAssertions(
|
|
|
|
JSContext* aCx, JS::ImportAssertionVector& aValues) {
|
|
|
|
MOZ_ASSERT(aValues.empty());
|
|
|
|
|
|
|
|
if (!aValues.reserve(1)) {
|
|
|
|
JS_ReportOutOfMemory(aCx);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
aValues.infallibleAppend(JS::ImportAssertion::Type);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
ModuleLoaderBase* ModuleLoaderBase::GetCurrentModuleLoader(JSContext* aCx) {
|
|
|
|
auto reportError = mozilla::MakeScopeExit([aCx]() {
|
|
|
|
JS_ReportErrorASCII(aCx, "No ScriptLoader found for the current context");
|
|
|
|
});
|
|
|
|
|
|
|
|
JS::Rooted<JSObject*> object(aCx, JS::CurrentGlobalOrNull(aCx));
|
|
|
|
if (!object) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIGlobalObject* global = xpc::NativeGlobal(object);
|
|
|
|
if (!global) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
ModuleLoaderBase* loader = global->GetModuleLoader(aCx);
|
|
|
|
if (!loader) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-04-11 18:35:29 +03:00
|
|
|
MOZ_ASSERT(loader->mGlobalObject == global);
|
|
|
|
|
2022-03-28 15:38:28 +03:00
|
|
|
reportError.release();
|
|
|
|
return loader;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
LoadedScript* ModuleLoaderBase::GetLoadedScriptOrNull(
|
|
|
|
JSContext* aCx, JS::Handle<JS::Value> aReferencingPrivate) {
|
|
|
|
if (aReferencingPrivate.isUndefined()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto* script = static_cast<LoadedScript*>(aReferencingPrivate.toPrivate());
|
|
|
|
if (script->IsEventScript()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT_IF(
|
|
|
|
script->IsModuleScript(),
|
|
|
|
JS::GetModulePrivate(script->AsModuleScript()->ModuleRecord()) ==
|
|
|
|
aReferencingPrivate);
|
|
|
|
|
|
|
|
return script;
|
|
|
|
}
|
|
|
|
|
2022-03-28 18:56:10 +03:00
|
|
|
nsresult ModuleLoaderBase::StartModuleLoad(ModuleLoadRequest* aRequest) {
|
|
|
|
return StartOrRestartModuleLoad(aRequest, RestartRequest::No);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult ModuleLoaderBase::RestartModuleLoad(ModuleLoadRequest* aRequest) {
|
|
|
|
return StartOrRestartModuleLoad(aRequest, RestartRequest::Yes);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult ModuleLoaderBase::StartOrRestartModuleLoad(ModuleLoadRequest* aRequest,
|
|
|
|
RestartRequest aRestart) {
|
2022-04-11 18:35:28 +03:00
|
|
|
MOZ_ASSERT(aRequest->mLoader == this);
|
2022-03-28 18:56:10 +03:00
|
|
|
MOZ_ASSERT(aRequest->IsFetching());
|
2022-04-11 18:35:28 +03:00
|
|
|
|
2022-03-28 18:56:10 +03:00
|
|
|
aRequest->SetUnknownDataType();
|
|
|
|
|
|
|
|
// If we're restarting the request, the module should already be in the
|
|
|
|
// "fetching" map.
|
2022-04-11 18:35:29 +03:00
|
|
|
MOZ_ASSERT_IF(aRestart == RestartRequest::Yes,
|
|
|
|
IsModuleFetching(aRequest->mURI));
|
2022-03-28 18:56:10 +03:00
|
|
|
|
|
|
|
// Check with the derived class whether we should load this module.
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
if (!CanStartLoad(aRequest, &rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether the module has been fetched or is currently being fetched,
|
|
|
|
// and if so wait for it rather than starting a new fetch.
|
|
|
|
ModuleLoadRequest* request = aRequest->AsModuleRequest();
|
|
|
|
|
2022-04-11 18:35:29 +03:00
|
|
|
if (aRestart == RestartRequest::No && ModuleMapContainsURL(request->mURI)) {
|
2022-03-28 18:56:10 +03:00
|
|
|
LOG(("ScriptLoadRequest (%p): Waiting for module fetch", aRequest));
|
2022-04-11 18:35:29 +03:00
|
|
|
WaitForModuleFetch(request->mURI)
|
2022-03-28 18:56:10 +03:00
|
|
|
->Then(GetMainThreadSerialEventTarget(), __func__, request,
|
|
|
|
&ModuleLoadRequest::ModuleLoaded,
|
|
|
|
&ModuleLoadRequest::LoadFailed);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = StartFetch(aRequest);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
// We successfully started fetching a module so put its URL in the module
|
|
|
|
// map and mark it as fetching.
|
|
|
|
if (aRestart == RestartRequest::No) {
|
|
|
|
SetModuleFetchStarted(aRequest->AsModuleRequest());
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2022-04-11 18:35:29 +03:00
|
|
|
bool ModuleLoaderBase::ModuleMapContainsURL(nsIURI* aURL) const {
|
2022-02-18 01:00:41 +03:00
|
|
|
// Returns whether we have fetched, or are currently fetching, a module script
|
|
|
|
// for a URL.
|
2022-04-11 18:35:29 +03:00
|
|
|
return mFetchingModules.Contains(aURL) || mFetchedModules.Contains(aURL);
|
2022-02-18 01:00:41 +03:00
|
|
|
}
|
|
|
|
|
2022-04-11 18:35:29 +03:00
|
|
|
bool ModuleLoaderBase::IsModuleFetching(nsIURI* aURL) const {
|
|
|
|
return mFetchingModules.Contains(aURL);
|
2022-03-15 22:05:57 +03:00
|
|
|
}
|
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
void ModuleLoaderBase::SetModuleFetchStarted(ModuleLoadRequest* aRequest) {
|
2022-02-18 01:00:41 +03:00
|
|
|
// Update the module map to indicate that a module is currently being fetched.
|
|
|
|
|
2022-03-25 13:54:17 +03:00
|
|
|
MOZ_ASSERT(aRequest->IsFetching());
|
2022-04-11 18:35:29 +03:00
|
|
|
MOZ_ASSERT(!ModuleMapContainsURL(aRequest->mURI));
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
mFetchingModules.InsertOrUpdate(
|
2022-04-11 18:35:29 +03:00
|
|
|
aRequest->mURI, RefPtr<mozilla::GenericNonExclusivePromise::Private>{});
|
2022-02-18 01:00:41 +03:00
|
|
|
}
|
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
void ModuleLoaderBase::SetModuleFetchFinishedAndResumeWaitingRequests(
|
2022-02-18 01:00:41 +03:00
|
|
|
ModuleLoadRequest* aRequest, nsresult aResult) {
|
|
|
|
// Update module map with the result of fetching a single module script.
|
|
|
|
//
|
|
|
|
// If any requests for the same URL are waiting on this one to complete, they
|
|
|
|
// will have ModuleLoaded or LoadFailed on them when the promise is
|
|
|
|
// resolved/rejected. This is set up in StartLoad.
|
|
|
|
|
2022-04-11 18:35:28 +03:00
|
|
|
MOZ_ASSERT(aRequest->mLoader == this);
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
LOG(
|
|
|
|
("ScriptLoadRequest (%p): Module fetch finished (script == %p, result == "
|
|
|
|
"%u)",
|
|
|
|
aRequest, aRequest->mModuleScript.get(), unsigned(aResult)));
|
|
|
|
|
2022-02-21 18:39:09 +03:00
|
|
|
RefPtr<mozilla::GenericNonExclusivePromise::Private> promise;
|
2022-04-11 18:35:29 +03:00
|
|
|
if (!mFetchingModules.Remove(aRequest->mURI, getter_AddRefs(promise))) {
|
2022-02-21 18:39:04 +03:00
|
|
|
LOG(
|
|
|
|
("ScriptLoadRequest (%p): Key not found in mFetchingModules, "
|
|
|
|
"assuming we have an inline module or have finished fetching already",
|
2022-02-18 01:00:41 +03:00
|
|
|
aRequest));
|
|
|
|
return;
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
RefPtr<ModuleScript> moduleScript(aRequest->mModuleScript);
|
|
|
|
MOZ_ASSERT(NS_FAILED(aResult) == !moduleScript);
|
|
|
|
|
2022-04-11 18:35:29 +03:00
|
|
|
mFetchedModules.InsertOrUpdate(aRequest->mURI, RefPtr{moduleScript});
|
2022-02-18 01:00:41 +03:00
|
|
|
|
|
|
|
if (promise) {
|
|
|
|
if (moduleScript) {
|
|
|
|
LOG(("ScriptLoadRequest (%p): resolving %p", aRequest, promise.get()));
|
|
|
|
promise->Resolve(true, __func__);
|
|
|
|
} else {
|
|
|
|
LOG(("ScriptLoadRequest (%p): rejecting %p", aRequest, promise.get()));
|
|
|
|
promise->Reject(aResult, __func__);
|
|
|
|
}
|
|
|
|
}
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-21 18:39:09 +03:00
|
|
|
RefPtr<mozilla::GenericNonExclusivePromise>
|
2022-04-11 18:35:29 +03:00
|
|
|
ModuleLoaderBase::WaitForModuleFetch(nsIURI* aURL) {
|
|
|
|
MOZ_ASSERT(ModuleMapContainsURL(aURL));
|
2022-02-18 01:00:41 +03:00
|
|
|
|
2022-04-11 18:35:29 +03:00
|
|
|
nsURIHashKey key(aURL);
|
|
|
|
if (auto entry = mFetchingModules.Lookup(aURL)) {
|
2022-02-18 01:00:41 +03:00
|
|
|
if (!entry.Data()) {
|
2022-02-21 18:39:09 +03:00
|
|
|
entry.Data() = new mozilla::GenericNonExclusivePromise::Private(__func__);
|
2022-02-18 01:00:41 +03:00
|
|
|
}
|
|
|
|
return entry.Data();
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
RefPtr<ModuleScript> ms;
|
2022-04-11 18:35:29 +03:00
|
|
|
MOZ_ALWAYS_TRUE(mFetchedModules.Get(aURL, getter_AddRefs(ms)));
|
2022-02-18 01:00:41 +03:00
|
|
|
if (!ms) {
|
2022-02-21 18:39:09 +03:00
|
|
|
return mozilla::GenericNonExclusivePromise::CreateAndReject(
|
|
|
|
NS_ERROR_FAILURE, __func__);
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-21 18:39:09 +03:00
|
|
|
return mozilla::GenericNonExclusivePromise::CreateAndResolve(true, __func__);
|
2022-02-18 01:00:41 +03:00
|
|
|
}
|
|
|
|
|
2022-04-11 18:35:29 +03:00
|
|
|
ModuleScript* ModuleLoaderBase::GetFetchedModule(nsIURI* aURL) const {
|
2022-02-18 01:00:41 +03:00
|
|
|
if (LOG_ENABLED()) {
|
|
|
|
nsAutoCString url;
|
|
|
|
aURL->GetAsciiSpec(url);
|
2022-04-11 18:35:29 +03:00
|
|
|
LOG(("GetFetchedModule %s", url.get()));
|
2022-02-18 01:00:41 +03:00
|
|
|
}
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
bool found;
|
2022-04-11 18:35:29 +03:00
|
|
|
ModuleScript* ms = mFetchedModules.GetWeak(aURL, &found);
|
2022-02-18 01:00:41 +03:00
|
|
|
MOZ_ASSERT(found);
|
|
|
|
return ms;
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
nsresult ModuleLoaderBase::ProcessFetchedModuleSource(
|
|
|
|
ModuleLoadRequest* aRequest) {
|
2022-04-11 18:35:28 +03:00
|
|
|
MOZ_ASSERT(aRequest->mLoader == this);
|
2022-02-18 01:00:41 +03:00
|
|
|
MOZ_ASSERT(!aRequest->mModuleScript);
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
nsresult rv = CreateModuleScript(aRequest);
|
|
|
|
MOZ_ASSERT(NS_FAILED(rv) == !aRequest->mModuleScript);
|
|
|
|
|
|
|
|
aRequest->ClearScriptSource();
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
aRequest->LoadFailed();
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2022-02-21 18:39:04 +03:00
|
|
|
SetModuleFetchFinishedAndResumeWaitingRequests(aRequest, rv);
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
if (!aRequest->mModuleScript->HasParseError()) {
|
|
|
|
StartFetchingModuleDependencies(aRequest);
|
|
|
|
}
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
return NS_OK;
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
nsresult ModuleLoaderBase::CreateModuleScript(ModuleLoadRequest* aRequest) {
|
2022-02-18 01:00:41 +03:00
|
|
|
MOZ_ASSERT(!aRequest->mModuleScript);
|
|
|
|
MOZ_ASSERT(aRequest->mBaseURL);
|
|
|
|
|
|
|
|
LOG(("ScriptLoadRequest (%p): Create module script", aRequest));
|
|
|
|
|
2022-03-28 15:38:28 +03:00
|
|
|
AutoJSAPI jsapi;
|
2022-04-11 18:35:30 +03:00
|
|
|
if (!jsapi.Init(mGlobalObject)) {
|
2022-03-17 18:22:17 +03:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2022-02-18 01:00:41 +03:00
|
|
|
|
|
|
|
nsresult rv;
|
2022-02-17 18:57:51 +03:00
|
|
|
{
|
2022-03-17 18:22:17 +03:00
|
|
|
JSContext* cx = jsapi.cx();
|
2022-02-18 01:00:41 +03:00
|
|
|
JS::Rooted<JSObject*> module(cx);
|
|
|
|
|
|
|
|
JS::CompileOptions options(cx);
|
|
|
|
JS::RootedScript introductionScript(cx);
|
2022-03-17 18:22:17 +03:00
|
|
|
rv = mLoader->FillCompileOptionsForRequest(cx, aRequest, &options,
|
2022-02-18 01:00:41 +03:00
|
|
|
&introductionScript);
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2022-04-11 18:35:30 +03:00
|
|
|
JS::Rooted<JSObject*> global(cx, mGlobalObject->GetGlobalJSObject());
|
2022-02-21 18:39:07 +03:00
|
|
|
rv = CompileOrFinishModuleScript(cx, global, options, aRequest, &module);
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
MOZ_ASSERT(NS_SUCCEEDED(rv) == (module != nullptr));
|
|
|
|
|
|
|
|
if (module) {
|
|
|
|
JS::RootedValue privateValue(cx);
|
|
|
|
JS::RootedScript moduleScript(cx, JS::GetModuleScript(module));
|
|
|
|
JS::InstantiateOptions instantiateOptions(options);
|
|
|
|
if (!JS::UpdateDebugMetadata(cx, moduleScript, instantiateOptions,
|
|
|
|
privateValue, nullptr, introductionScript,
|
|
|
|
nullptr)) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
RefPtr<ModuleScript> moduleScript =
|
2022-04-21 12:53:34 +03:00
|
|
|
new ModuleScript(aRequest->mFetchOptions, aRequest->mBaseURL);
|
2022-02-18 01:00:41 +03:00
|
|
|
aRequest->mModuleScript = moduleScript;
|
|
|
|
|
|
|
|
if (!module) {
|
|
|
|
LOG(("ScriptLoadRequest (%p): compilation failed (%d)", aRequest,
|
|
|
|
unsigned(rv)));
|
|
|
|
|
2022-03-17 18:22:17 +03:00
|
|
|
MOZ_ASSERT(jsapi.HasException());
|
2022-02-18 01:00:41 +03:00
|
|
|
JS::Rooted<JS::Value> error(cx);
|
2022-03-17 18:22:17 +03:00
|
|
|
if (!jsapi.StealException(&error)) {
|
2022-02-18 01:00:41 +03:00
|
|
|
aRequest->mModuleScript = nullptr;
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
moduleScript->SetParseError(error);
|
|
|
|
aRequest->ModuleErrored();
|
|
|
|
return NS_OK;
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
moduleScript->SetModuleRecord(module);
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
// Validate requested modules and treat failure to resolve module specifiers
|
|
|
|
// the same as a parse error.
|
2022-02-21 18:39:07 +03:00
|
|
|
rv = ResolveRequestedModules(aRequest, nullptr);
|
2022-02-18 01:00:41 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
aRequest->ModuleErrored();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
2022-02-18 01:00:41 +03:00
|
|
|
|
|
|
|
LOG(("ScriptLoadRequest (%p): module script == %p", aRequest,
|
|
|
|
aRequest->mModuleScript.get()));
|
|
|
|
|
|
|
|
return rv;
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
nsresult ModuleLoaderBase::HandleResolveFailure(
|
2022-02-18 01:00:41 +03:00
|
|
|
JSContext* aCx, LoadedScript* aScript, const nsAString& aSpecifier,
|
|
|
|
uint32_t aLineNumber, uint32_t aColumnNumber,
|
|
|
|
JS::MutableHandle<JS::Value> errorOut) {
|
|
|
|
JS::Rooted<JSString*> filename(aCx);
|
|
|
|
if (aScript) {
|
|
|
|
nsAutoCString url;
|
|
|
|
aScript->BaseURL()->GetAsciiSpec(url);
|
|
|
|
filename = JS_NewStringCopyZ(aCx, url.get());
|
|
|
|
} else {
|
|
|
|
filename = JS_NewStringCopyZ(aCx, "(unknown)");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!filename) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
AutoTArray<nsString, 1> errorParams;
|
|
|
|
errorParams.AppendElement(aSpecifier);
|
|
|
|
|
|
|
|
nsAutoString errorText;
|
|
|
|
nsresult rv = nsContentUtils::FormatLocalizedString(
|
|
|
|
nsContentUtils::eDOM_PROPERTIES, "ModuleResolveFailure", errorParams,
|
|
|
|
errorText);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
JS::Rooted<JSString*> string(aCx, JS_NewUCStringCopyZ(aCx, errorText.get()));
|
|
|
|
if (!string) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
if (!JS::CreateError(aCx, JSEXN_TYPEERR, nullptr, filename, aLineNumber,
|
|
|
|
aColumnNumber, nullptr, string, JS::NothingHandleValue,
|
|
|
|
errorOut)) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
already_AddRefed<nsIURI> ModuleLoaderBase::ResolveModuleSpecifier(
|
2022-04-11 18:35:27 +03:00
|
|
|
LoadedScript* aScript, const nsAString& aSpecifier) {
|
2022-02-18 01:00:41 +03:00
|
|
|
// The following module specifiers are allowed by the spec:
|
|
|
|
// - a valid absolute URL
|
|
|
|
// - a valid relative URL that starts with "/", "./" or "../"
|
|
|
|
//
|
|
|
|
// Bareword module specifiers are currently disallowed as these may be given
|
|
|
|
// special meanings in the future.
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
nsresult rv = NS_NewURI(getter_AddRefs(uri), aSpecifier);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
return uri.forget();
|
|
|
|
}
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
if (rv != NS_ERROR_MALFORMED_URI) {
|
|
|
|
return nullptr;
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
if (!StringBeginsWith(aSpecifier, u"/"_ns) &&
|
|
|
|
!StringBeginsWith(aSpecifier, u"./"_ns) &&
|
|
|
|
!StringBeginsWith(aSpecifier, u"../"_ns)) {
|
|
|
|
return nullptr;
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
// Get the document's base URL if we don't have a referencing script here.
|
|
|
|
nsCOMPtr<nsIURI> baseURL;
|
|
|
|
if (aScript) {
|
|
|
|
baseURL = aScript->BaseURL();
|
|
|
|
} else {
|
2022-04-11 18:35:27 +03:00
|
|
|
baseURL = mLoader->GetBaseURI();
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
rv = NS_NewURI(getter_AddRefs(uri), aSpecifier, nullptr, baseURL);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
return uri.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
nsresult ModuleLoaderBase::ResolveRequestedModules(
|
|
|
|
ModuleLoadRequest* aRequest, nsCOMArray<nsIURI>* aUrlsOut) {
|
2022-02-18 01:00:41 +03:00
|
|
|
ModuleScript* ms = aRequest->mModuleScript;
|
|
|
|
|
2022-03-28 15:38:28 +03:00
|
|
|
AutoJSAPI jsapi;
|
2022-02-18 01:00:41 +03:00
|
|
|
if (!jsapi.Init(ms->ModuleRecord())) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSContext* cx = jsapi.cx();
|
|
|
|
JS::Rooted<JSObject*> moduleRecord(cx, ms->ModuleRecord());
|
|
|
|
JS::Rooted<JSObject*> requestedModules(cx);
|
|
|
|
requestedModules = JS::GetRequestedModules(cx, moduleRecord);
|
|
|
|
MOZ_ASSERT(requestedModules);
|
|
|
|
|
|
|
|
uint32_t length;
|
|
|
|
if (!JS::GetArrayLength(cx, requestedModules, &length)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
JS::Rooted<JS::Value> element(cx);
|
|
|
|
for (uint32_t i = 0; i < length; i++) {
|
|
|
|
if (!JS_GetElement(cx, requestedModules, i, &element)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
JS::Rooted<JSString*> str(cx, JS::GetRequestedModuleSpecifier(cx, element));
|
|
|
|
MOZ_ASSERT(str);
|
|
|
|
|
|
|
|
nsAutoJSString specifier;
|
|
|
|
if (!specifier.init(cx, str)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Let url be the result of resolving a module specifier given module script
|
|
|
|
// and requested.
|
2022-04-11 18:35:27 +03:00
|
|
|
ModuleLoaderBase* loader = aRequest->mLoader;
|
|
|
|
nsCOMPtr<nsIURI> uri = loader->ResolveModuleSpecifier(ms, specifier);
|
2022-02-18 01:00:41 +03:00
|
|
|
if (!uri) {
|
|
|
|
uint32_t lineNumber = 0;
|
|
|
|
uint32_t columnNumber = 0;
|
|
|
|
JS::GetRequestedModuleSourcePos(cx, element, &lineNumber, &columnNumber);
|
|
|
|
|
|
|
|
JS::Rooted<JS::Value> error(cx);
|
|
|
|
nsresult rv = HandleResolveFailure(cx, ms, specifier, lineNumber,
|
|
|
|
columnNumber, &error);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
ms->SetParseError(error);
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aUrlsOut) {
|
|
|
|
aUrlsOut->AppendElement(uri.forget());
|
|
|
|
}
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
void ModuleLoaderBase::StartFetchingModuleDependencies(
|
2022-02-18 01:00:41 +03:00
|
|
|
ModuleLoadRequest* aRequest) {
|
|
|
|
LOG(("ScriptLoadRequest (%p): Start fetching module dependencies", aRequest));
|
|
|
|
|
|
|
|
if (aRequest->IsCanceled()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(aRequest->mModuleScript);
|
|
|
|
MOZ_ASSERT(!aRequest->mModuleScript->HasParseError());
|
|
|
|
MOZ_ASSERT(!aRequest->IsReadyToRun());
|
|
|
|
|
|
|
|
auto visitedSet = aRequest->mVisitedSet;
|
|
|
|
MOZ_ASSERT(visitedSet->Contains(aRequest->mURI));
|
|
|
|
|
2022-03-25 13:54:16 +03:00
|
|
|
aRequest->mState = ModuleLoadRequest::State::LoadingImports;
|
2022-02-18 01:00:41 +03:00
|
|
|
|
|
|
|
nsCOMArray<nsIURI> urls;
|
2022-02-21 18:39:07 +03:00
|
|
|
nsresult rv = ResolveRequestedModules(aRequest, &urls);
|
2022-02-18 01:00:41 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
aRequest->mModuleScript = nullptr;
|
|
|
|
aRequest->ModuleErrored();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove already visited URLs from the list. Put unvisited URLs into the
|
|
|
|
// visited set.
|
|
|
|
int32_t i = 0;
|
|
|
|
while (i < urls.Count()) {
|
|
|
|
nsIURI* url = urls[i];
|
|
|
|
if (visitedSet->Contains(url)) {
|
|
|
|
urls.RemoveObjectAt(i);
|
2022-02-17 18:57:51 +03:00
|
|
|
} else {
|
2022-02-18 01:00:41 +03:00
|
|
|
visitedSet->PutEntry(url);
|
|
|
|
i++;
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
2022-02-18 01:00:41 +03:00
|
|
|
}
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
if (urls.Count() == 0) {
|
|
|
|
// There are no descendants to load so this request is ready.
|
|
|
|
aRequest->DependenciesLoaded();
|
|
|
|
return;
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
// For each url in urls, fetch a module script tree given url, module script's
|
|
|
|
// CORS setting, and module script's settings object.
|
2022-02-21 18:39:09 +03:00
|
|
|
nsTArray<RefPtr<mozilla::GenericPromise>> importsReady;
|
2022-02-18 01:00:41 +03:00
|
|
|
for (auto* url : urls) {
|
2022-02-21 18:39:09 +03:00
|
|
|
RefPtr<mozilla::GenericPromise> childReady =
|
2022-02-18 01:00:41 +03:00
|
|
|
StartFetchingModuleAndDependencies(aRequest, url);
|
|
|
|
importsReady.AppendElement(childReady);
|
|
|
|
}
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
// Wait for all imports to become ready.
|
2022-02-21 18:39:09 +03:00
|
|
|
RefPtr<mozilla::GenericPromise::AllPromiseType> allReady =
|
|
|
|
mozilla::GenericPromise::All(mozilla::GetMainThreadSerialEventTarget(),
|
|
|
|
importsReady);
|
|
|
|
allReady->Then(mozilla::GetMainThreadSerialEventTarget(), __func__, aRequest,
|
2022-02-18 01:00:41 +03:00
|
|
|
&ModuleLoadRequest::DependenciesLoaded,
|
|
|
|
&ModuleLoadRequest::ModuleErrored);
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-21 18:39:09 +03:00
|
|
|
RefPtr<mozilla::GenericPromise>
|
|
|
|
ModuleLoaderBase::StartFetchingModuleAndDependencies(ModuleLoadRequest* aParent,
|
|
|
|
nsIURI* aURI) {
|
2022-02-18 01:00:41 +03:00
|
|
|
MOZ_ASSERT(aURI);
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
RefPtr<ModuleLoadRequest> childRequest = CreateStaticImport(aURI, aParent);
|
2022-02-18 01:00:41 +03:00
|
|
|
|
|
|
|
aParent->mImports.AppendElement(childRequest);
|
|
|
|
|
|
|
|
if (LOG_ENABLED()) {
|
|
|
|
nsAutoCString url1;
|
|
|
|
aParent->mURI->GetAsciiSpec(url1);
|
|
|
|
|
|
|
|
nsAutoCString url2;
|
|
|
|
aURI->GetAsciiSpec(url2);
|
|
|
|
|
|
|
|
LOG(("ScriptLoadRequest (%p): Start fetching dependency %p", aParent,
|
|
|
|
childRequest.get()));
|
|
|
|
LOG(("StartFetchingModuleAndDependencies \"%s\" -> \"%s\"", url1.get(),
|
|
|
|
url2.get()));
|
|
|
|
}
|
|
|
|
|
2022-02-21 18:39:09 +03:00
|
|
|
RefPtr<mozilla::GenericPromise> ready = childRequest->mReady.Ensure(__func__);
|
2022-02-18 01:00:41 +03:00
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
nsresult rv = StartModuleLoad(childRequest);
|
2022-02-18 01:00:41 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
MOZ_ASSERT(!childRequest->mModuleScript);
|
|
|
|
LOG(("ScriptLoadRequest (%p): rejecting %p", aParent,
|
|
|
|
&childRequest->mReady));
|
|
|
|
|
|
|
|
mLoader->ReportErrorToConsole(childRequest, rv);
|
|
|
|
childRequest->mReady.Reject(rv, __func__);
|
|
|
|
return ready;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ready;
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
void ModuleLoaderBase::StartDynamicImport(ModuleLoadRequest* aRequest) {
|
2022-04-11 18:35:28 +03:00
|
|
|
MOZ_ASSERT(aRequest->mLoader == this);
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
LOG(("ScriptLoadRequest (%p): Start dynamic import", aRequest));
|
|
|
|
|
|
|
|
mDynamicImportRequests.AppendElement(aRequest);
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
nsresult rv = StartModuleLoad(aRequest);
|
2022-02-18 01:00:41 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
mLoader->ReportErrorToConsole(aRequest, rv);
|
|
|
|
FinishDynamicImportAndReject(aRequest, rv);
|
|
|
|
}
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
void ModuleLoaderBase::FinishDynamicImportAndReject(ModuleLoadRequest* aRequest,
|
|
|
|
nsresult aResult) {
|
2022-03-28 15:38:28 +03:00
|
|
|
AutoJSAPI jsapi;
|
2022-02-18 01:00:41 +03:00
|
|
|
MOZ_ASSERT(NS_FAILED(aResult));
|
|
|
|
MOZ_ALWAYS_TRUE(jsapi.Init(aRequest->mDynamicPromise));
|
|
|
|
FinishDynamicImport(jsapi.cx(), aRequest, aResult, nullptr);
|
|
|
|
}
|
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
void ModuleLoaderBase::FinishDynamicImport(
|
2022-02-18 01:00:41 +03:00
|
|
|
JSContext* aCx, ModuleLoadRequest* aRequest, nsresult aResult,
|
|
|
|
JS::Handle<JSObject*> aEvaluationPromise) {
|
|
|
|
// If aResult is a failed result, we don't have an EvaluationPromise. If it
|
|
|
|
// succeeded, evaluationPromise may still be null, but in this case it will
|
|
|
|
// be handled by rejecting the dynamic module import promise in the JSAPI.
|
|
|
|
MOZ_ASSERT_IF(NS_FAILED(aResult), !aEvaluationPromise);
|
|
|
|
LOG(("ScriptLoadRequest (%p): Finish dynamic import %x %d", aRequest,
|
|
|
|
unsigned(aResult), JS_IsExceptionPending(aCx)));
|
|
|
|
|
|
|
|
// Complete the dynamic import, report failures indicated by aResult or as a
|
|
|
|
// pending exception on the context.
|
|
|
|
|
|
|
|
if (NS_FAILED(aResult) &&
|
|
|
|
aResult != NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW_UNCATCHABLE) {
|
|
|
|
MOZ_ASSERT(!JS_IsExceptionPending(aCx));
|
|
|
|
JS_ReportErrorNumberUC(aCx, js::GetErrorMessage, nullptr,
|
|
|
|
JSMSG_DYNAMIC_IMPORT_FAILED);
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
JS::Rooted<JS::Value> referencingScript(aCx,
|
|
|
|
aRequest->mDynamicReferencingPrivate);
|
|
|
|
JS::Rooted<JSString*> specifier(aCx, aRequest->mDynamicSpecifier);
|
|
|
|
JS::Rooted<JSObject*> promise(aCx, aRequest->mDynamicPromise);
|
|
|
|
|
|
|
|
JS::Rooted<JSObject*> moduleRequest(aCx,
|
|
|
|
JS::CreateModuleRequest(aCx, specifier));
|
|
|
|
|
|
|
|
JS::FinishDynamicModuleImport(aCx, aEvaluationPromise, referencingScript,
|
|
|
|
moduleRequest, promise);
|
|
|
|
|
|
|
|
// FinishDynamicModuleImport clears any pending exception.
|
|
|
|
MOZ_ASSERT(!JS_IsExceptionPending(aCx));
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
aRequest->ClearDynamicImport();
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-04-11 18:35:29 +03:00
|
|
|
ModuleLoaderBase::ModuleLoaderBase(ScriptLoaderInterface* aLoader,
|
|
|
|
nsIGlobalObject* aGlobalObject)
|
|
|
|
: mGlobalObject(aGlobalObject), mLoader(aLoader) {
|
|
|
|
MOZ_ASSERT(mGlobalObject);
|
|
|
|
MOZ_ASSERT(mLoader);
|
|
|
|
|
2022-03-28 15:38:28 +03:00
|
|
|
EnsureModuleHooksInitialized();
|
|
|
|
}
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
ModuleLoaderBase::~ModuleLoaderBase() {
|
2022-02-18 01:00:41 +03:00
|
|
|
mDynamicImportRequests.CancelRequestsAndClear();
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
LOG(("ModuleLoaderBase::~ModuleLoaderBase %p", this));
|
2022-02-18 01:00:41 +03:00
|
|
|
}
|
|
|
|
|
2022-03-17 18:22:16 +03:00
|
|
|
bool ModuleLoaderBase::HasPendingDynamicImports() const {
|
|
|
|
return !mDynamicImportRequests.isEmpty();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ModuleLoaderBase::CancelDynamicImport(ModuleLoadRequest* aRequest,
|
|
|
|
nsresult aResult) {
|
2022-04-11 18:35:28 +03:00
|
|
|
MOZ_ASSERT(aRequest->mLoader == this);
|
|
|
|
|
2022-03-17 18:22:16 +03:00
|
|
|
RefPtr<ScriptLoadRequest> req = mDynamicImportRequests.Steal(aRequest);
|
|
|
|
aRequest->Cancel();
|
|
|
|
// FinishDynamicImport must happen exactly once for each dynamic import
|
|
|
|
// request. If the load is aborted we do it when we remove the request
|
|
|
|
// from mDynamicImportRequests.
|
|
|
|
FinishDynamicImportAndReject(aRequest, aResult);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ModuleLoaderBase::RemoveDynamicImport(ModuleLoadRequest* aRequest) {
|
|
|
|
MOZ_ASSERT(aRequest->IsDynamicImport());
|
|
|
|
mDynamicImportRequests.Remove(aRequest);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2022-04-11 18:35:28 +03:00
|
|
|
bool ModuleLoaderBase::HasDynamicImport(
|
|
|
|
const ModuleLoadRequest* aRequest) const {
|
|
|
|
MOZ_ASSERT(aRequest->mLoader == this);
|
|
|
|
return mDynamicImportRequests.Contains(
|
|
|
|
const_cast<ModuleLoadRequest*>(aRequest));
|
2022-03-17 18:22:16 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
JS::Value ModuleLoaderBase::FindFirstParseError(ModuleLoadRequest* aRequest) {
|
2022-02-18 01:00:41 +03:00
|
|
|
MOZ_ASSERT(aRequest);
|
|
|
|
|
|
|
|
ModuleScript* moduleScript = aRequest->mModuleScript;
|
|
|
|
MOZ_ASSERT(moduleScript);
|
|
|
|
|
|
|
|
if (moduleScript->HasParseError()) {
|
|
|
|
return moduleScript->ParseError();
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
for (ModuleLoadRequest* childRequest : aRequest->mImports) {
|
|
|
|
JS::Value error = FindFirstParseError(childRequest);
|
|
|
|
if (!error.isUndefined()) {
|
|
|
|
return error;
|
|
|
|
}
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
return JS::UndefinedValue();
|
|
|
|
}
|
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
bool ModuleLoaderBase::InstantiateModuleTree(ModuleLoadRequest* aRequest) {
|
2022-02-18 01:00:41 +03:00
|
|
|
// Instantiate a top-level module and record any error.
|
|
|
|
|
|
|
|
MOZ_ASSERT(aRequest);
|
2022-04-11 18:35:28 +03:00
|
|
|
MOZ_ASSERT(aRequest->mLoader == this);
|
2022-02-18 01:00:41 +03:00
|
|
|
MOZ_ASSERT(aRequest->IsTopLevel());
|
|
|
|
|
|
|
|
LOG(("ScriptLoadRequest (%p): Instantiate module tree", aRequest));
|
|
|
|
|
2022-03-17 18:22:18 +03:00
|
|
|
AUTO_PROFILER_LABEL("ModuleLoaderBase::InstantiateModuleTree", JS);
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
ModuleScript* moduleScript = aRequest->mModuleScript;
|
|
|
|
MOZ_ASSERT(moduleScript);
|
|
|
|
|
|
|
|
JS::Value parseError = FindFirstParseError(aRequest);
|
|
|
|
if (!parseError.isUndefined()) {
|
|
|
|
moduleScript->SetErrorToRethrow(parseError);
|
|
|
|
LOG(("ScriptLoadRequest (%p): found parse error", aRequest));
|
|
|
|
return true;
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
MOZ_ASSERT(moduleScript->ModuleRecord());
|
|
|
|
|
2022-03-28 15:38:28 +03:00
|
|
|
AutoJSAPI jsapi;
|
2022-02-18 01:00:41 +03:00
|
|
|
if (NS_WARN_IF(!jsapi.Init(moduleScript->ModuleRecord()))) {
|
|
|
|
return false;
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
JS::Rooted<JSObject*> module(jsapi.cx(), moduleScript->ModuleRecord());
|
2022-03-17 18:22:18 +03:00
|
|
|
if (!xpc::Scriptability::Get(module).Allowed()) {
|
|
|
|
return true;
|
|
|
|
}
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-03-17 18:22:18 +03:00
|
|
|
if (!JS::ModuleInstantiate(jsapi.cx(), module)) {
|
2022-02-18 01:00:41 +03:00
|
|
|
LOG(("ScriptLoadRequest (%p): Instantiate failed", aRequest));
|
|
|
|
MOZ_ASSERT(jsapi.HasException());
|
|
|
|
JS::RootedValue exception(jsapi.cx());
|
|
|
|
if (!jsapi.StealException(&exception)) {
|
|
|
|
return false;
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
2022-02-18 01:00:41 +03:00
|
|
|
MOZ_ASSERT(!exception.isUndefined());
|
|
|
|
moduleScript->SetErrorToRethrow(exception);
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
return true;
|
|
|
|
}
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
nsresult ModuleLoaderBase::InitDebuggerDataForModuleTree(
|
2022-02-18 01:00:41 +03:00
|
|
|
JSContext* aCx, ModuleLoadRequest* aRequest) {
|
|
|
|
// JS scripts can be associated with a DOM element for use by the debugger,
|
|
|
|
// but preloading can cause scripts to be compiled before DOM script element
|
|
|
|
// nodes have been created. This method ensures that this association takes
|
|
|
|
// place before the first time a module script is run.
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
MOZ_ASSERT(aRequest);
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
ModuleScript* moduleScript = aRequest->mModuleScript;
|
|
|
|
if (moduleScript->DebuggerDataInitialized()) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (ModuleLoadRequest* childRequest : aRequest->mImports) {
|
|
|
|
nsresult rv = InitDebuggerDataForModuleTree(aCx, childRequest);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
JS::Rooted<JSObject*> module(aCx, moduleScript->ModuleRecord());
|
|
|
|
MOZ_ASSERT(module);
|
|
|
|
|
|
|
|
// The script is now ready to be exposed to the debugger.
|
|
|
|
JS::Rooted<JSScript*> script(aCx, JS::GetModuleScript(module));
|
|
|
|
JS::ExposeScriptToDebugger(aCx, script);
|
|
|
|
|
|
|
|
moduleScript->SetDebuggerDataInitialized();
|
2022-02-17 18:57:51 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
void ModuleLoaderBase::ProcessDynamicImport(ModuleLoadRequest* aRequest) {
|
2022-04-11 18:35:28 +03:00
|
|
|
MOZ_ASSERT(aRequest->mLoader == this);
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
if (aRequest->mModuleScript) {
|
|
|
|
if (!InstantiateModuleTree(aRequest)) {
|
|
|
|
aRequest->mModuleScript = nullptr;
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
if (aRequest->mModuleScript) {
|
|
|
|
rv = EvaluateModule(aRequest);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
FinishDynamicImportAndReject(aRequest, rv);
|
|
|
|
}
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-04-11 18:35:30 +03:00
|
|
|
nsresult ModuleLoaderBase::EvaluateModule(ModuleLoadRequest* aRequest) {
|
2022-04-11 18:35:28 +03:00
|
|
|
MOZ_ASSERT(aRequest->mLoader == this);
|
|
|
|
|
2022-03-17 18:22:18 +03:00
|
|
|
AUTO_PROFILER_LABEL("ModuleLoaderBase::EvaluateModule", JS);
|
|
|
|
|
2022-02-21 18:39:09 +03:00
|
|
|
mozilla::nsAutoMicroTask mt;
|
2022-04-11 18:35:30 +03:00
|
|
|
mozilla::dom::AutoEntryScript aes(mGlobalObject, "EvaluateModule", true);
|
2022-02-18 01:00:41 +03:00
|
|
|
JSContext* cx = aes.cx();
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
nsAutoCString profilerLabelString;
|
2022-02-21 18:39:04 +03:00
|
|
|
if (aRequest->HasLoadContext()) {
|
|
|
|
aRequest->GetLoadContext()->GetProfilerLabel(profilerLabelString);
|
|
|
|
}
|
2022-02-18 01:00:41 +03:00
|
|
|
|
|
|
|
LOG(("ScriptLoadRequest (%p): Evaluate Module", aRequest));
|
|
|
|
AUTO_PROFILER_MARKER_TEXT("ModuleEvaluation", JS,
|
|
|
|
MarkerInnerWindowIdFromJSContext(cx),
|
|
|
|
profilerLabelString);
|
|
|
|
|
|
|
|
ModuleLoadRequest* request = aRequest->AsModuleRequest();
|
|
|
|
MOZ_ASSERT(request->mModuleScript);
|
2022-02-21 18:39:04 +03:00
|
|
|
MOZ_ASSERT_IF(request->HasLoadContext(),
|
|
|
|
!request->GetLoadContext()->mOffThreadToken);
|
2022-02-18 01:00:41 +03:00
|
|
|
|
|
|
|
ModuleScript* moduleScript = request->mModuleScript;
|
|
|
|
if (moduleScript->HasErrorToRethrow()) {
|
|
|
|
LOG(("ScriptLoadRequest (%p): module has error to rethrow", aRequest));
|
|
|
|
JS::Rooted<JS::Value> error(cx, moduleScript->ErrorToRethrow());
|
|
|
|
JS_SetPendingException(cx, error);
|
|
|
|
// For a dynamic import, the promise is rejected. Otherwise an error
|
|
|
|
// is either reported by AutoEntryScript.
|
|
|
|
if (request->IsDynamicImport()) {
|
|
|
|
FinishDynamicImport(cx, request, NS_OK, nullptr);
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
2022-02-18 01:00:41 +03:00
|
|
|
return NS_OK;
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
JS::Rooted<JSObject*> module(cx, moduleScript->ModuleRecord());
|
|
|
|
MOZ_ASSERT(module);
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-03-17 18:22:18 +03:00
|
|
|
if (!xpc::Scriptability::Get(module).Allowed()) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
nsresult rv = InitDebuggerDataForModuleTree(cx, request);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2022-02-21 18:39:04 +03:00
|
|
|
if (request->HasLoadContext()) {
|
|
|
|
TRACE_FOR_TEST(aRequest->GetLoadContext()->GetScriptElement(),
|
|
|
|
"scriptloader_evaluate_module");
|
|
|
|
}
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
JS::Rooted<JS::Value> rval(cx);
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-03-15 22:05:56 +03:00
|
|
|
mLoader->MaybePrepareModuleForBytecodeEncodingBeforeExecute(cx, request);
|
|
|
|
|
2022-03-17 18:22:18 +03:00
|
|
|
if (JS::ModuleEvaluate(cx, module, &rval)) {
|
2022-02-18 01:00:41 +03:00
|
|
|
// If we have an infinite loop in a module, which is stopped by the
|
|
|
|
// user, the module evaluation will fail, but we will not have an
|
|
|
|
// AutoEntryScript exception.
|
|
|
|
MOZ_ASSERT(!aes.HasException());
|
2022-03-17 18:22:18 +03:00
|
|
|
} else {
|
2022-02-18 01:00:41 +03:00
|
|
|
LOG(("ScriptLoadRequest (%p): evaluation failed", aRequest));
|
2022-03-17 18:22:18 +03:00
|
|
|
// For a dynamic import, the promise is rejected. Otherwise an error is
|
|
|
|
// reported by AutoEntryScript.
|
2022-02-18 01:00:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
JS::Rooted<JSObject*> aEvaluationPromise(cx);
|
|
|
|
if (rval.isObject()) {
|
|
|
|
// If the user cancels the evaluation on an infinite loop, we need
|
|
|
|
// to skip this step. In that case, ModuleEvaluate will not return a
|
|
|
|
// promise, rval will be undefined. We should treat it as a failed
|
|
|
|
// evaluation, and reject appropriately.
|
|
|
|
aEvaluationPromise.set(&rval.toObject());
|
|
|
|
}
|
|
|
|
if (request->IsDynamicImport()) {
|
2022-03-17 18:22:18 +03:00
|
|
|
FinishDynamicImport(cx, request, NS_OK, aEvaluationPromise);
|
2022-02-18 01:00:41 +03:00
|
|
|
} else {
|
|
|
|
// If this is not a dynamic import, and if the promise is rejected,
|
|
|
|
// the value is unwrapped from the promise value.
|
|
|
|
if (!JS::ThrowOnModuleEvaluationFailure(cx, aEvaluationPromise)) {
|
|
|
|
LOG(("ScriptLoadRequest (%p): evaluation failed on throw", aRequest));
|
2022-03-17 18:22:18 +03:00
|
|
|
// For a dynamic import, the promise is rejected. Otherwise an error is
|
|
|
|
// reported by AutoEntryScript.
|
2022-02-18 01:00:41 +03:00
|
|
|
}
|
|
|
|
}
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-03-17 18:22:18 +03:00
|
|
|
rv = mLoader->MaybePrepareModuleForBytecodeEncodingAfterExecute(request,
|
|
|
|
NS_OK);
|
2022-03-15 22:05:56 +03:00
|
|
|
|
|
|
|
mLoader->MaybeTriggerBytecodeEncoding();
|
|
|
|
|
2022-02-18 01:00:41 +03:00
|
|
|
return rv;
|
|
|
|
}
|
2022-02-17 18:57:51 +03:00
|
|
|
|
2022-02-21 18:39:07 +03:00
|
|
|
void ModuleLoaderBase::CancelAndClearDynamicImports() {
|
2022-02-18 01:00:41 +03:00
|
|
|
for (ScriptLoadRequest* req = mDynamicImportRequests.getFirst(); req;
|
|
|
|
req = req->getNext()) {
|
|
|
|
req->Cancel();
|
|
|
|
// FinishDynamicImport must happen exactly once for each dynamic import
|
|
|
|
// request. If the load is aborted we do it when we remove the request
|
|
|
|
// from mDynamicImportRequests.
|
|
|
|
FinishDynamicImportAndReject(req->AsModuleRequest(), NS_ERROR_ABORT);
|
|
|
|
}
|
|
|
|
mDynamicImportRequests.CancelRequestsAndClear();
|
2022-02-17 18:57:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#undef LOG
|
|
|
|
#undef LOG_ENABLED
|
|
|
|
|
2022-02-21 18:39:09 +03:00
|
|
|
} // namespace JS::loader
|