forked from mirrors/gecko-dev
Bug 1759881 - Part 10: Move the generic parts of the StartLoad method to the module loader base r=yulia
StartModuleLoadImpl moves to the base class and uses to new virtual methods CanStartLoad and StartFetch which are implemented by the derived class. Differential Revision: https://phabricator.services.mozilla.com/D141736
This commit is contained in:
parent
89419ea1f8
commit
9d8474b374
5 changed files with 114 additions and 84 deletions
|
|
@ -55,23 +55,25 @@ ScriptLoader* ModuleLoader::GetScriptLoader() {
|
||||||
return static_cast<ScriptLoader*>(mLoader.get());
|
return static_cast<ScriptLoader*>(mLoader.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult ModuleLoader::StartModuleLoad(ScriptLoadRequest* aRequest) {
|
bool ModuleLoader::CanStartLoad(ModuleLoadRequest* aRequest, nsresult* aRvOut) {
|
||||||
return StartModuleLoadImpl(aRequest, RestartRequest::No);
|
if (!GetScriptLoader()->GetDocument()) {
|
||||||
}
|
*aRvOut = NS_ERROR_NULL_POINTER;
|
||||||
|
return false;
|
||||||
nsresult ModuleLoader::RestartModuleLoad(ScriptLoadRequest* aRequest) {
|
}
|
||||||
return StartModuleLoadImpl(aRequest, RestartRequest::Yes);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult ModuleLoader::StartModuleLoadImpl(ScriptLoadRequest* aRequest,
|
|
||||||
RestartRequest aRestart) {
|
|
||||||
MOZ_ASSERT(aRequest->IsFetching());
|
|
||||||
NS_ENSURE_TRUE(GetScriptLoader()->GetDocument(), NS_ERROR_NULL_POINTER);
|
|
||||||
aRequest->SetUnknownDataType();
|
|
||||||
|
|
||||||
// If this document is sandboxed without 'allow-scripts', abort.
|
// If this document is sandboxed without 'allow-scripts', abort.
|
||||||
if (GetScriptLoader()->GetDocument()->HasScriptsBlockedBySandbox()) {
|
if (GetScriptLoader()->GetDocument()->HasScriptsBlockedBySandbox()) {
|
||||||
return NS_OK;
|
*aRvOut = NS_OK;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// To prevent dynamic code execution, content scripts can only
|
||||||
|
// load moz-extension URLs.
|
||||||
|
nsCOMPtr<nsIPrincipal> principal = aRequest->TriggeringPrincipal();
|
||||||
|
if (BasePrincipal::Cast(principal)->ContentScriptAddonPolicy() &&
|
||||||
|
!aRequest->mURI->SchemeIs("moz-extension")) {
|
||||||
|
*aRvOut = NS_ERROR_DOM_WEBEXT_CONTENT_SCRIPT_URI;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LOG_ENABLED()) {
|
if (LOG_ENABLED()) {
|
||||||
|
|
@ -81,37 +83,10 @@ nsresult ModuleLoader::StartModuleLoadImpl(ScriptLoadRequest* aRequest,
|
||||||
url.get()));
|
url.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// To prevent dynamic code execution, content scripts can only
|
return true;
|
||||||
// load moz-extension URLs.
|
}
|
||||||
nsCOMPtr<nsIPrincipal> principal = aRequest->TriggeringPrincipal();
|
|
||||||
if (BasePrincipal::Cast(principal)->ContentScriptAddonPolicy() &&
|
|
||||||
!aRequest->mURI->SchemeIs("moz-extension")) {
|
|
||||||
return NS_ERROR_DOM_WEBEXT_CONTENT_SCRIPT_URI;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
|
|
||||||
// If we're restarting the request, the module should already be in the
|
|
||||||
// "fetching" map.
|
|
||||||
MOZ_ASSERT_IF(
|
|
||||||
aRestart == RestartRequest::Yes,
|
|
||||||
IsModuleFetching(request->mURI,
|
|
||||||
aRequest->GetLoadContext()->GetWebExtGlobal()));
|
|
||||||
|
|
||||||
if (aRestart == RestartRequest::No &&
|
|
||||||
ModuleMapContainsURL(request->mURI,
|
|
||||||
aRequest->GetLoadContext()->GetWebExtGlobal())) {
|
|
||||||
LOG(("ScriptLoadRequest (%p): Waiting for module fetch", aRequest));
|
|
||||||
WaitForModuleFetch(request->mURI,
|
|
||||||
aRequest->GetLoadContext()->GetWebExtGlobal())
|
|
||||||
->Then(GetMainThreadSerialEventTarget(), __func__, request,
|
|
||||||
&ModuleLoadRequest::ModuleLoaded,
|
|
||||||
&ModuleLoadRequest::LoadFailed);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
nsresult ModuleLoader::StartFetch(ModuleLoadRequest* aRequest) {
|
||||||
nsSecurityFlags securityFlags;
|
nsSecurityFlags securityFlags;
|
||||||
|
|
||||||
// According to the spec, module scripts have different behaviour to classic
|
// According to the spec, module scripts have different behaviour to classic
|
||||||
|
|
@ -135,14 +110,8 @@ nsresult ModuleLoader::StartModuleLoadImpl(ScriptLoadRequest* aRequest,
|
||||||
|
|
||||||
// Delegate Shared Behavior to base ScriptLoader
|
// Delegate Shared Behavior to base ScriptLoader
|
||||||
nsresult rv = GetScriptLoader()->StartLoadInternal(aRequest, securityFlags);
|
nsresult rv = GetScriptLoader()->StartLoadInternal(aRequest, securityFlags);
|
||||||
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
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());
|
|
||||||
}
|
|
||||||
LOG(("ScriptLoadRequest (%p): Start fetching module", aRequest));
|
LOG(("ScriptLoadRequest (%p): Start fetching module", aRequest));
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
|
||||||
|
|
@ -44,20 +44,10 @@ class ModuleLoader final : public JS::loader::ModuleLoaderBase {
|
||||||
|
|
||||||
ScriptLoader* GetScriptLoader();
|
ScriptLoader* GetScriptLoader();
|
||||||
|
|
||||||
/**
|
bool CanStartLoad(ModuleLoadRequest* aRequest, nsresult* aRvOut) override;
|
||||||
* Start a load for a module script URI.
|
|
||||||
* Sets up the necessary security flags before calling StartLoadInternal.
|
|
||||||
* Short-circuits if the module is already being loaded.
|
|
||||||
*/
|
|
||||||
nsresult StartModuleLoad(ScriptLoadRequest* aRequest) override;
|
|
||||||
nsresult RestartModuleLoad(ScriptLoadRequest* aRequest) override;
|
|
||||||
|
|
||||||
private:
|
nsresult StartFetch(ModuleLoadRequest* aRequest) override;
|
||||||
enum class RestartRequest { No, Yes };
|
|
||||||
nsresult StartModuleLoadImpl(ScriptLoadRequest* aRequest,
|
|
||||||
RestartRequest aRestart);
|
|
||||||
|
|
||||||
public:
|
|
||||||
void ProcessLoadedModuleTree(ModuleLoadRequest* aRequest) override;
|
void ProcessLoadedModuleTree(ModuleLoadRequest* aRequest) override;
|
||||||
|
|
||||||
nsresult CompileOrFinishModuleScript(
|
nsresult CompileOrFinishModuleScript(
|
||||||
|
|
|
||||||
|
|
@ -490,7 +490,7 @@ nsresult ScriptLoader::RestartLoad(ScriptLoadRequest* aRequest) {
|
||||||
aRequest->mFetchSourceOnly = true;
|
aRequest->mFetchSourceOnly = true;
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
if (aRequest->IsModuleRequest()) {
|
if (aRequest->IsModuleRequest()) {
|
||||||
rv = mModuleLoader->RestartModuleLoad(aRequest);
|
rv = mModuleLoader->RestartModuleLoad(aRequest->AsModuleRequest());
|
||||||
} else {
|
} else {
|
||||||
rv = StartLoad(aRequest);
|
rv = StartLoad(aRequest);
|
||||||
}
|
}
|
||||||
|
|
@ -504,8 +504,11 @@ nsresult ScriptLoader::RestartLoad(ScriptLoadRequest* aRequest) {
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult ScriptLoader::StartLoad(ScriptLoadRequest* aRequest) {
|
nsresult ScriptLoader::StartLoad(ScriptLoadRequest* aRequest) {
|
||||||
return aRequest->IsModuleRequest() ? mModuleLoader->StartModuleLoad(aRequest)
|
if (aRequest->IsModuleRequest()) {
|
||||||
: StartClassicLoad(aRequest);
|
return mModuleLoader->StartModuleLoad(aRequest->AsModuleRequest());
|
||||||
|
}
|
||||||
|
|
||||||
|
return StartClassicLoad(aRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult ScriptLoader::StartClassicLoad(ScriptLoadRequest* aRequest) {
|
nsresult ScriptLoader::StartClassicLoad(ScriptLoadRequest* aRequest) {
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,12 @@
|
||||||
#include "mozilla/CycleCollectedJSContext.h" // nsAutoMicroTask
|
#include "mozilla/CycleCollectedJSContext.h" // nsAutoMicroTask
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsICacheInfoChannel.h" //nsICacheInfoChannel
|
#include "nsICacheInfoChannel.h" // nsICacheInfoChannel
|
||||||
#include "nsNetUtil.h" // NS_NewURI
|
#include "nsNetUtil.h" // NS_NewURI
|
||||||
|
#include "nsThreadUtils.h" // GetMainThreadSerialEventTarget
|
||||||
#include "xpcpublic.h"
|
#include "xpcpublic.h"
|
||||||
|
|
||||||
|
using mozilla::GetMainThreadSerialEventTarget;
|
||||||
using mozilla::Preferences;
|
using mozilla::Preferences;
|
||||||
using mozilla::dom::AutoJSAPI;
|
using mozilla::dom::AutoJSAPI;
|
||||||
|
|
||||||
|
|
@ -343,6 +345,60 @@ LoadedScript* ModuleLoaderBase::GetLoadedScriptOrNull(
|
||||||
return script;
|
return script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
MOZ_ASSERT(aRequest->IsFetching());
|
||||||
|
aRequest->SetUnknownDataType();
|
||||||
|
|
||||||
|
// If we're restarting the request, the module should already be in the
|
||||||
|
// "fetching" map.
|
||||||
|
MOZ_ASSERT_IF(
|
||||||
|
aRestart == RestartRequest::Yes,
|
||||||
|
IsModuleFetching(aRequest->mURI,
|
||||||
|
aRequest->GetLoadContext()->GetWebExtGlobal()));
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
if (aRestart == RestartRequest::No &&
|
||||||
|
ModuleMapContainsURL(request->mURI,
|
||||||
|
aRequest->GetLoadContext()->GetWebExtGlobal())) {
|
||||||
|
LOG(("ScriptLoadRequest (%p): Waiting for module fetch", aRequest));
|
||||||
|
WaitForModuleFetch(request->mURI,
|
||||||
|
aRequest->GetLoadContext()->GetWebExtGlobal())
|
||||||
|
->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;
|
||||||
|
}
|
||||||
|
|
||||||
bool ModuleLoaderBase::ModuleMapContainsURL(nsIURI* aURL,
|
bool ModuleLoaderBase::ModuleMapContainsURL(nsIURI* aURL,
|
||||||
nsIGlobalObject* aGlobal) const {
|
nsIGlobalObject* aGlobal) const {
|
||||||
// Returns whether we have fetched, or are currently fetching, a module script
|
// Returns whether we have fetched, or are currently fetching, a module script
|
||||||
|
|
|
||||||
|
|
@ -111,18 +111,10 @@ class ModuleLoaderBase : public nsISupports {
|
||||||
using MaybeSourceText =
|
using MaybeSourceText =
|
||||||
mozilla::MaybeOneOf<JS::SourceText<char16_t>, JS::SourceText<Utf8Unit>>;
|
mozilla::MaybeOneOf<JS::SourceText<char16_t>, JS::SourceText<Utf8Unit>>;
|
||||||
|
|
||||||
// Methods that must be overwritten by an extending class. These are called
|
// Methods that must be implemented by an extending class. These are called
|
||||||
// internally by ModuleLoaderBase.
|
// internally by ModuleLoaderBase.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual nsresult StartModuleLoad(ScriptLoadRequest* aRequest) = 0;
|
|
||||||
virtual nsresult RestartModuleLoad(ScriptLoadRequest* aRequest) = 0;
|
|
||||||
virtual void ProcessLoadedModuleTree(ModuleLoadRequest* aRequest) = 0;
|
|
||||||
virtual nsresult CompileOrFinishModuleScript(
|
|
||||||
JSContext* aCx, JS::Handle<JSObject*> aGlobal,
|
|
||||||
JS::CompileOptions& aOptions, ModuleLoadRequest* aRequest,
|
|
||||||
JS::MutableHandle<JSObject*> aModuleScript) = 0;
|
|
||||||
|
|
||||||
// Create a module load request for a static module import.
|
// Create a module load request for a static module import.
|
||||||
virtual already_AddRefed<ModuleLoadRequest> CreateStaticImport(
|
virtual already_AddRefed<ModuleLoadRequest> CreateStaticImport(
|
||||||
nsIURI* aURI, ModuleLoadRequest* aParent) = 0;
|
nsIURI* aURI, ModuleLoadRequest* aParent) = 0;
|
||||||
|
|
@ -133,6 +125,20 @@ class ModuleLoaderBase : public nsISupports {
|
||||||
JS::Handle<JS::Value> aReferencingPrivate,
|
JS::Handle<JS::Value> aReferencingPrivate,
|
||||||
JS::Handle<JSString*> aSpecifier, JS::Handle<JSObject*> aPromise) = 0;
|
JS::Handle<JSString*> aSpecifier, JS::Handle<JSObject*> aPromise) = 0;
|
||||||
|
|
||||||
|
// Check whether we can load a module. May return false with |aRvOut| set to
|
||||||
|
// NS_OK to abort load without returning an error.
|
||||||
|
virtual bool CanStartLoad(ModuleLoadRequest* aRequest, nsresult* aRvOut) = 0;
|
||||||
|
|
||||||
|
// Start the process of fetching module source or bytecode. This is only
|
||||||
|
// called if CanStartLoad returned true.
|
||||||
|
virtual nsresult StartFetch(ModuleLoadRequest* aRequest) = 0;
|
||||||
|
|
||||||
|
virtual void ProcessLoadedModuleTree(ModuleLoadRequest* aRequest) = 0;
|
||||||
|
virtual nsresult CompileOrFinishModuleScript(
|
||||||
|
JSContext* aCx, JS::Handle<JSObject*> aGlobal,
|
||||||
|
JS::CompileOptions& aOptions, ModuleLoadRequest* aRequest,
|
||||||
|
JS::MutableHandle<JSObject*> aModuleScript) = 0;
|
||||||
|
|
||||||
// Public API methods.
|
// Public API methods.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -142,6 +148,11 @@ class ModuleLoaderBase : public nsISupports {
|
||||||
bool HasDynamicImport(ModuleLoadRequest* aRequest) const;
|
bool HasDynamicImport(ModuleLoadRequest* aRequest) const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Start a load for a module script URI. Returns immediately if the module is
|
||||||
|
// already being loaded.
|
||||||
|
nsresult StartModuleLoad(ModuleLoadRequest* aRequest);
|
||||||
|
nsresult RestartModuleLoad(ModuleLoadRequest* aRequest);
|
||||||
|
|
||||||
void SetModuleFetchFinishedAndResumeWaitingRequests(
|
void SetModuleFetchFinishedAndResumeWaitingRequests(
|
||||||
ModuleLoadRequest* aRequest, nsresult aResult);
|
ModuleLoadRequest* aRequest, nsresult aResult);
|
||||||
|
|
||||||
|
|
@ -156,15 +167,6 @@ class ModuleLoaderBase : public nsISupports {
|
||||||
void ProcessDynamicImport(ModuleLoadRequest* aRequest);
|
void ProcessDynamicImport(ModuleLoadRequest* aRequest);
|
||||||
void CancelAndClearDynamicImports();
|
void CancelAndClearDynamicImports();
|
||||||
|
|
||||||
// Protected methods for used by concrete implementation.
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool ModuleMapContainsURL(nsIURI* aURL, nsIGlobalObject* aGlobal) const;
|
|
||||||
bool IsModuleFetching(nsIURI* aURL, nsIGlobalObject* aGlobal) const;
|
|
||||||
RefPtr<GenericNonExclusivePromise> WaitForModuleFetch(
|
|
||||||
nsIURI* aURL, nsIGlobalObject* aGlobal);
|
|
||||||
void SetModuleFetchStarted(ModuleLoadRequest* aRequest);
|
|
||||||
|
|
||||||
// Internal methods.
|
// Internal methods.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -200,6 +202,16 @@ class ModuleLoaderBase : public nsISupports {
|
||||||
uint32_t aColumnNumber,
|
uint32_t aColumnNumber,
|
||||||
JS::MutableHandle<JS::Value> errorOut);
|
JS::MutableHandle<JS::Value> errorOut);
|
||||||
|
|
||||||
|
enum class RestartRequest { No, Yes };
|
||||||
|
nsresult StartOrRestartModuleLoad(ModuleLoadRequest* aRequest,
|
||||||
|
RestartRequest aRestart);
|
||||||
|
|
||||||
|
bool ModuleMapContainsURL(nsIURI* aURL, nsIGlobalObject* aGlobal) const;
|
||||||
|
bool IsModuleFetching(nsIURI* aURL, nsIGlobalObject* aGlobal) const;
|
||||||
|
RefPtr<GenericNonExclusivePromise> WaitForModuleFetch(
|
||||||
|
nsIURI* aURL, nsIGlobalObject* aGlobal);
|
||||||
|
void SetModuleFetchStarted(ModuleLoadRequest* aRequest);
|
||||||
|
|
||||||
ModuleScript* GetFetchedModule(nsIURI* aURL, nsIGlobalObject* aGlobal) const;
|
ModuleScript* GetFetchedModule(nsIURI* aURL, nsIGlobalObject* aGlobal) const;
|
||||||
|
|
||||||
// Helper function to set up the global correctly for dynamic imports.
|
// Helper function to set up the global correctly for dynamic imports.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue