mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 07:13:20 +00:00
Bug 1803810 - Part 4: Add mozJSModuleLoader for non-shared global. r=jonco
On the main thread, single mozJSModuleLoader instance is shared across all loads in non-shared global, with resetting the internal state after importing a module graph. NonSharedGlobalSyncModuleLoaderScope manages the lifetime of each usage. Import into the same non-shared global can be nested, but import into the different non-shared gloobal is not allowed while other import for non-shared global is ongoing. Differential Revision: https://phabricator.services.mozilla.com/D199456
This commit is contained in:
parent
a380811687
commit
e379bd0e94
@ -1047,6 +1047,10 @@ void ModuleLoaderBase::Shutdown() {
|
||||
mLoader = nullptr;
|
||||
}
|
||||
|
||||
bool ModuleLoaderBase::HasFetchingModules() const {
|
||||
return !mFetchingModules.IsEmpty();
|
||||
}
|
||||
|
||||
bool ModuleLoaderBase::HasPendingDynamicImports() const {
|
||||
return !mDynamicImportRequests.isEmpty();
|
||||
}
|
||||
|
@ -282,6 +282,8 @@ class ModuleLoaderBase : public nsISupports {
|
||||
|
||||
nsIGlobalObject* GetGlobalObject() const { return mGlobalObject; }
|
||||
|
||||
bool HasFetchingModules() const;
|
||||
|
||||
bool HasPendingDynamicImports() const;
|
||||
void CancelDynamicImport(ModuleLoadRequest* aRequest, nsresult aResult);
|
||||
#ifdef DEBUG
|
||||
|
@ -5,8 +5,10 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ScriptLoadRequest.h"
|
||||
#include "mozilla/Assertions.h" // MOZ_ASSERT, MOZ_ASSERT_IF
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ArrayUtils.h" // mozilla::ArrayLength
|
||||
#include "mozilla/RefPtr.h" // RefPtr, mozilla::StaticRefPtr
|
||||
#include "mozilla/Utf8.h" // mozilla::Utf8Unit
|
||||
|
||||
#include <cstdarg>
|
||||
@ -488,6 +490,35 @@ mozJSModuleLoader* mozJSModuleLoader::GetOrCreateDevToolsLoader() {
|
||||
return sDevToolsLoader;
|
||||
}
|
||||
|
||||
void mozJSModuleLoader::InitSyncModuleLoaderForGlobal(
|
||||
nsIGlobalObject* aGlobal) {
|
||||
MOZ_ASSERT(!mLoaderGlobal);
|
||||
MOZ_ASSERT(!mModuleLoader);
|
||||
|
||||
RefPtr<SyncScriptLoader> scriptLoader = new SyncScriptLoader;
|
||||
mModuleLoader = new SyncModuleLoader(scriptLoader, aGlobal);
|
||||
mLoaderGlobal = aGlobal->GetGlobalJSObject();
|
||||
}
|
||||
|
||||
void mozJSModuleLoader::DisconnectSyncModuleLoaderFromGlobal() {
|
||||
MOZ_ASSERT(mLoaderGlobal);
|
||||
MOZ_ASSERT(mModuleLoader);
|
||||
|
||||
mLoaderGlobal = nullptr;
|
||||
Unload();
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool mozJSModuleLoader::IsSharedSystemGlobal(nsIGlobalObject* aGlobal) {
|
||||
return sSelf->IsLoaderGlobal(aGlobal->GetGlobalJSObject());
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool mozJSModuleLoader::IsDevToolsLoaderGlobal(nsIGlobalObject* aGlobal) {
|
||||
return sDevToolsLoader &&
|
||||
sDevToolsLoader->IsLoaderGlobal(aGlobal->GetGlobalJSObject());
|
||||
}
|
||||
|
||||
// This requires that the keys be strings and the values be pointers.
|
||||
template <class Key, class Data, class UserData, class Converter>
|
||||
static size_t SizeOfTableExcludingThis(
|
||||
@ -695,10 +726,12 @@ nsresult mozJSModuleLoader::LoadSingleModuleScript(
|
||||
#ifdef STARTUP_RECORDER_ENABLED
|
||||
if (aModuleLoader == sSelf->mModuleLoader) {
|
||||
sSelf->RecordImportStack(aCx, aRequest);
|
||||
} else {
|
||||
MOZ_ASSERT(sDevToolsLoader);
|
||||
MOZ_ASSERT(aModuleLoader == sDevToolsLoader->mModuleLoader);
|
||||
} else if (sDevToolsLoader &&
|
||||
aModuleLoader == sDevToolsLoader->mModuleLoader) {
|
||||
sDevToolsLoader->RecordImportStack(aCx, aRequest);
|
||||
} else {
|
||||
// NOTE: Do not record import stack for non-shared globals, given the
|
||||
// loader is associated with the global only while importing.
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1927,6 +1960,58 @@ size_t mozJSModuleLoader::ModuleEntry::SizeOfIncludingThis(
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/* static */
|
||||
mozJSModuleLoader* NonSharedGlobalSyncModuleLoaderScope::sActiveLoader =
|
||||
nullptr;
|
||||
|
||||
NonSharedGlobalSyncModuleLoaderScope::NonSharedGlobalSyncModuleLoaderScope(
|
||||
JSContext* aCx, nsIGlobalObject* aGlobal) {
|
||||
// Only the main thread is supported for now.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mozJSModuleLoader::IsSharedSystemGlobal(aGlobal));
|
||||
MOZ_ASSERT(!mozJSModuleLoader::IsDevToolsLoaderGlobal(aGlobal));
|
||||
|
||||
mAsyncModuleLoader = aGlobal->GetModuleLoader(aCx);
|
||||
MOZ_ASSERT(mAsyncModuleLoader,
|
||||
"The consumer should guarantee the global returns non-null module "
|
||||
"loader");
|
||||
|
||||
mLoader = new mozJSModuleLoader();
|
||||
RegisterWeakMemoryReporter(mLoader);
|
||||
mLoader->InitSyncModuleLoaderForGlobal(aGlobal);
|
||||
|
||||
mAsyncModuleLoader->CopyModulesTo(mLoader->mModuleLoader);
|
||||
|
||||
mMaybeOverride.emplace(mAsyncModuleLoader, mLoader->mModuleLoader);
|
||||
|
||||
MOZ_ASSERT(!sActiveLoader);
|
||||
sActiveLoader = mLoader;
|
||||
}
|
||||
|
||||
NonSharedGlobalSyncModuleLoaderScope::~NonSharedGlobalSyncModuleLoaderScope() {
|
||||
MOZ_ASSERT(sActiveLoader == mLoader);
|
||||
sActiveLoader = nullptr;
|
||||
|
||||
mLoader->DisconnectSyncModuleLoaderFromGlobal();
|
||||
UnregisterWeakMemoryReporter(mLoader);
|
||||
}
|
||||
|
||||
void NonSharedGlobalSyncModuleLoaderScope::Finish() {
|
||||
mLoader->mModuleLoader->MoveModulesTo(mAsyncModuleLoader);
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool NonSharedGlobalSyncModuleLoaderScope::IsActive() {
|
||||
return !!sActiveLoader;
|
||||
}
|
||||
|
||||
/* static */
|
||||
mozJSModuleLoader* NonSharedGlobalSyncModuleLoaderScope::ActiveLoader() {
|
||||
return sActiveLoader;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
JSCLContextHelper::JSCLContextHelper(JSContext* aCx)
|
||||
: mContext(aCx), mBuf(nullptr) {}
|
||||
|
||||
|
@ -8,9 +8,12 @@
|
||||
#define mozJSModuleLoader_h
|
||||
|
||||
#include "SyncModuleLoader.h"
|
||||
#include "mozilla/Attributes.h" // MOZ_STACK_CLASS
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/FileLocation.h"
|
||||
#include "mozilla/Maybe.h" // mozilla::Maybe
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/RefPtr.h" // RefPtr, mozilla::StaticRefPtr
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsISupports.h"
|
||||
@ -37,6 +40,12 @@ class ModuleLoadRequest;
|
||||
# define STARTUP_RECORDER_ENABLED
|
||||
#endif
|
||||
|
||||
namespace mozilla::loader {
|
||||
|
||||
class NonSharedGlobalSyncModuleLoaderScope;
|
||||
|
||||
} // namespace mozilla::loader
|
||||
|
||||
class mozJSModuleLoader final : public nsIMemoryReporter {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
@ -67,6 +76,13 @@ class mozJSModuleLoader final : public nsIMemoryReporter {
|
||||
|
||||
JSObject* GetSharedGlobal(JSContext* aCx);
|
||||
|
||||
private:
|
||||
void InitSyncModuleLoaderForGlobal(nsIGlobalObject* aGlobal);
|
||||
void DisconnectSyncModuleLoaderFromGlobal();
|
||||
|
||||
friend class mozilla::loader::NonSharedGlobalSyncModuleLoaderScope;
|
||||
|
||||
public:
|
||||
static mozJSModuleLoader* GetDevToolsLoader() { return sDevToolsLoader; }
|
||||
static mozJSModuleLoader* GetOrCreateDevToolsLoader();
|
||||
|
||||
@ -117,6 +133,9 @@ class mozJSModuleLoader final : public nsIMemoryReporter {
|
||||
bool IsLoaderGlobal(JSObject* aObj) { return mLoaderGlobal == aObj; }
|
||||
bool IsDevToolsLoader() const { return this == sDevToolsLoader; }
|
||||
|
||||
static bool IsSharedSystemGlobal(nsIGlobalObject* aGlobal);
|
||||
static bool IsDevToolsLoaderGlobal(nsIGlobalObject* aGlobal);
|
||||
|
||||
// Public methods for use from SyncModuleLoader.
|
||||
static bool IsTrustedScheme(nsIURI* aURI);
|
||||
static nsresult LoadSingleModuleScript(
|
||||
@ -261,4 +280,55 @@ class mozJSModuleLoader final : public nsIMemoryReporter {
|
||||
RefPtr<mozilla::loader::SyncModuleLoader> mModuleLoader;
|
||||
};
|
||||
|
||||
#endif
|
||||
namespace mozilla::loader {
|
||||
|
||||
// Automatically allocate and initialize a sync module loader for given
|
||||
// non-shared global, and override the module loader for the global with sync
|
||||
// module loader.
|
||||
//
|
||||
// This is not re-entrant, and the consumer must check IsActive method before
|
||||
// allocating this on the stack.
|
||||
//
|
||||
// The consumer should ensure the target global's module loader has no
|
||||
// ongoing fetching modules (ModuleLoaderBase::HasFetchingModules).
|
||||
// If there's any fetching modules, the consumer should wait for them before
|
||||
// allocating this class on the stack.
|
||||
//
|
||||
// The consumer should also verify that the target global has module loader,
|
||||
// as a part of the above step.
|
||||
//
|
||||
// The loader returned by ActiveLoader can be reused only when
|
||||
// ActiveLoader's global matches the global the consumer wants to use.
|
||||
class MOZ_STACK_CLASS NonSharedGlobalSyncModuleLoaderScope {
|
||||
public:
|
||||
NonSharedGlobalSyncModuleLoaderScope(JSContext* aCx,
|
||||
nsIGlobalObject* aGlobal);
|
||||
~NonSharedGlobalSyncModuleLoaderScope();
|
||||
|
||||
// After successfully importing a module graph, move all imported modules to
|
||||
// the target global's module loader.
|
||||
void Finish();
|
||||
|
||||
// Returns true if another instance of NonSharedGlobalSyncModuleLoaderScope
|
||||
// is on stack.
|
||||
static bool IsActive();
|
||||
|
||||
static mozJSModuleLoader* ActiveLoader();
|
||||
|
||||
private:
|
||||
RefPtr<mozJSModuleLoader> mLoader;
|
||||
|
||||
// The module loader on the stack.
|
||||
// This is used by another sync module load during a sync module load is
|
||||
// ongoing.
|
||||
static mozJSModuleLoader* sActiveLoader;
|
||||
|
||||
// The module loader of the target global.
|
||||
RefPtr<JS::loader::ModuleLoaderBase> mAsyncModuleLoader;
|
||||
|
||||
mozilla::Maybe<JS::loader::AutoOverrideModuleLoader> mMaybeOverride;
|
||||
};
|
||||
|
||||
} // namespace mozilla::loader
|
||||
|
||||
#endif // mozJSModuleLoader_h
|
||||
|
Loading…
Reference in New Issue
Block a user