Files
Yoshi Cheng-Hao Huang fdfad09834 Bug 2054848 - Part 5: Stop mozJSModuleLoader.h from including ModuleLoaderBase.h. r=arai
Move NonSharedGlobalSyncModuleLoaderScope into its own header. It is the only
class in mozJSModuleLoader.h that genuinely needs the full ModuleLoaderBase.h
(it holds a Maybe<JS::loader::AutoOverrideModuleLoader> by value), and it is only
used by ChromeUtils.cpp and mozJSModuleLoader.cpp. With it gone, mozJSModuleLoader.h
can forward-declare mozilla::loader::SyncModuleLoader instead of including
SyncModuleLoader.h, so the component-registration translation units that only need
mozJSModuleLoader (nsAppRunner, XPCOMInit, StaticComponents, JSActorManager) no
longer pull in ModuleLoaderBase.h.

Include nsTHashMap.h directly in mozJSModuleLoader.h, which it uses for
mImportStacks but was previously getting transitively through the removed include.

Translation Units recompiled:
$ rg -l --no-ignore --hidden --glob '*.o.pp' 'ModuleLoaderBase\.h' obj-x86_64-pc-linux-gnu | wc -l
  Before this patch: 20
  After this patch : 15

Differential Revision: https://phabricator.services.mozilla.com/D312140
2026-07-19 09:32:01 +00:00

223 lines
6.9 KiB
C++

/* 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/. */
#ifndef mozJSModuleLoader_h
#define mozJSModuleLoader_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/RefPtr.h" // RefPtr, mozilla::StaticRefPtr
#include "mozilla/StaticPtr.h"
#include "mozilla/ThreadLocal.h" // MOZ_THREAD_LOCAL
#include "jsapi.h"
#include "nsClassHashtable.h"
#include "nsIURI.h"
#include "nsTHashMap.h"
#include "SyncModuleLoader.h"
#include "xpcpublic.h"
#include "js/CompileOptions.h"
#include "js/experimental/JSStencil.h"
class nsIFile;
class ModuleLoaderInfo;
namespace mozilla {
class ScriptPreloader;
} // namespace mozilla
namespace JS::loader {
class ModuleLoadRequest;
} // namespace JS::loader
#if defined(NIGHTLY_BUILD) || defined(MOZ_DEV_EDITION) || defined(DEBUG)
# define STARTUP_RECORDER_ENABLED
#endif
namespace mozilla::loader {
class SyncModuleLoader;
class NonSharedGlobalSyncModuleLoaderScope;
} // namespace mozilla::loader
class mozJSModuleLoader final {
public:
NS_INLINE_DECL_REFCOUNTING(mozJSModuleLoader);
// Returns the list of all ESMs.
nsresult GetLoadedESModules(nsTArray<nsCString>& aLoadedModules);
nsresult GetModuleImportStack(const nsACString& aLocation,
nsACString& aRetval);
void FindTargetObject(JSContext* aCx, JS::MutableHandleObject aTargetObject);
static void InitStatics();
static void UnloadLoaders();
static void ShutdownLoaders();
static mozJSModuleLoader* Get() {
MOZ_ASSERT(sSelf, "Should have already created the module loader");
return sSelf;
}
JSObject* GetSharedGlobal() {
MOZ_ASSERT(mLoaderGlobal);
return mLoaderGlobal;
}
private:
void InitSharedGlobal(JSContext* aCx);
void InitSyncModuleLoaderForGlobal(nsIGlobalObject* aGlobal);
void DisconnectSyncModuleLoaderFromGlobal();
friend class mozilla::loader::NonSharedGlobalSyncModuleLoaderScope;
public:
static mozJSModuleLoader* GetDevToolsLoader() { return sDevToolsLoader; }
static mozJSModuleLoader* GetOrCreateDevToolsLoader(JSContext* aCx);
// Synchronously load an ES6 module and all its dependencies.
nsresult ImportESModule(JSContext* aCx, const nsACString& aResourceURI,
JS::MutableHandleObject aModuleNamespace);
#ifdef STARTUP_RECORDER_ENABLED
void RecordImportStack(JSContext* aCx,
JS::loader::ModuleLoadRequest* aRequest);
#endif
nsresult IsESModuleLoaded(const nsACString& aResourceURI, bool* aRetval);
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 nsresult LoadSingleModule(
mozilla::loader::SyncModuleLoader* aModuleLoader, JSContext* aCx,
JS::loader::ModuleLoadRequest* aRequest,
JS::MutableHandle<JSObject*> aModuleOut);
private:
static nsresult ReadScriptOnMainThread(JSContext* aCx,
const nsCString& aLocation,
nsCString& aData);
static nsresult LoadSingleModuleOnWorker(
mozilla::loader::SyncModuleLoader* aModuleLoader, JSContext* aCx,
JS::loader::ModuleLoadRequest* aRequest,
JS::MutableHandle<JSObject*> aModuleOut);
static nsresult CompileJsonModuleFromSource(
JSContext* aCx, const nsACString& aSource, const nsACString& aLocation,
JS::MutableHandle<JSObject*> aModuleOut);
static nsresult CompileCssModuleFromSource(
JSContext* aCx, mozilla::loader::SyncModuleLoader* aModuleLoader,
const nsACString& aSource, nsIURI* aBaseURI,
JS::MutableHandle<JSObject*> aModuleOut);
static nsresult CreateTextModuleFromSource(
JSContext* aCx, const nsACString& aSource, const nsACString& aLocation,
JS::MutableHandle<JSObject*> aModuleOut);
public:
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
bool DefineJSServices(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
protected:
mozJSModuleLoader();
~mozJSModuleLoader();
friend class XPCJSRuntime;
private:
static mozilla::StaticRefPtr<mozJSModuleLoader> sSelf;
static mozilla::StaticRefPtr<mozJSModuleLoader> sDevToolsLoader;
void Unload();
void UnloadModules();
void CreateLoaderGlobal(JSContext* aCx, const nsACString& aLocation,
JS::MutableHandleObject aGlobal);
void CreateDevToolsLoaderGlobal(JSContext* aCx, const nsACString& aLocation,
JS::MutableHandleObject aGlobal);
bool CreateJSServices(JSContext* aCx);
static nsresult GetSourceFile(nsIURI* aResolvedURI, nsIFile** aSourceFileOut);
static bool LocationIsRealFile(nsIURI* aURI);
static void SetModuleOptions(JS::CompileOptions& aOptions);
// Get the script for a given location, either from a cached stencil or by
// compiling it from source.
static nsresult GetScriptForLocation(JSContext* aCx, ModuleLoaderInfo& aInfo,
nsIFile* aModuleFile, bool aUseMemMap,
JS::MutableHandle<JSObject*> aModuleOut,
char** aLocationOut = nullptr);
class ModuleEntry {
public:
explicit ModuleEntry(JS::RootingContext* aRootingCx)
: obj(aRootingCx), exports(aRootingCx), thisObjectKey(aRootingCx) {
location = nullptr;
}
~ModuleEntry() { Clear(); }
void Clear() {
if (obj) {
if (JS_HasExtensibleLexicalEnvironment(obj)) {
JS::RootedObject lexicalEnv(mozilla::dom::RootingCx(),
JS_ExtensibleLexicalEnvironment(obj));
JS_SetAllNonReservedSlotsToUndefined(lexicalEnv);
}
JS_SetAllNonReservedSlotsToUndefined(obj);
obj = nullptr;
thisObjectKey = nullptr;
}
if (location) {
free(location);
}
obj = nullptr;
thisObjectKey = nullptr;
location = nullptr;
}
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
JS::PersistentRootedObject obj;
JS::PersistentRootedObject exports;
JS::PersistentRootedScript thisObjectKey;
char* location;
nsCString resolvedURL;
};
#ifdef STARTUP_RECORDER_ENABLED
nsTHashMap<nsCStringHashKey, nsCString> mImportStacks;
#endif
bool mInitialized;
bool mIsUnloaded = false;
#ifdef DEBUG
bool mIsInitializingLoaderGlobal = false;
#endif
JS::PersistentRooted<JSObject*> mLoaderGlobal;
JS::PersistentRooted<JSObject*> mServicesObj;
RefPtr<mozilla::loader::SyncModuleLoader> mModuleLoader;
};
#endif // mozJSModuleLoader_h