Bug 1943761 - Add class alignment to the mozsearch analysis file. r=asuth
[gecko.git] / js / xpconnect / loader / mozJSModuleLoader.h
blobe2dd1d6fb2da95be6938890c1ebe0602477fddc7
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozJSModuleLoader_h
8 #define mozJSModuleLoader_h
10 #include "SyncModuleLoader.h"
11 #include "mozilla/Attributes.h" // MOZ_STACK_CLASS
12 #include "mozilla/dom/ScriptSettings.h"
13 #include "mozilla/FileLocation.h"
14 #include "mozilla/Maybe.h" // mozilla::Maybe
15 #include "mozilla/RefPtr.h" // RefPtr, mozilla::StaticRefPtr
16 #include "mozilla/StaticPtr.h"
17 #include "mozilla/ThreadLocal.h" // MOZ_THREAD_LOCAL
18 #include "nsIURI.h"
19 #include "nsClassHashtable.h"
20 #include "jsapi.h"
21 #include "js/CompileOptions.h"
22 #include "js/experimental/JSStencil.h"
24 #include "xpcpublic.h"
26 class nsIFile;
27 class ModuleLoaderInfo;
29 namespace mozilla {
30 class ScriptPreloader;
31 } // namespace mozilla
33 namespace JS::loader {
34 class ModuleLoadRequest;
35 } // namespace JS::loader
37 #if defined(NIGHTLY_BUILD) || defined(MOZ_DEV_EDITION) || defined(DEBUG)
38 # define STARTUP_RECORDER_ENABLED
39 #endif
41 namespace mozilla::loader {
43 class NonSharedGlobalSyncModuleLoaderScope;
45 } // namespace mozilla::loader
47 class mozJSModuleLoader final {
48 public:
49 NS_INLINE_DECL_REFCOUNTING(mozJSModuleLoader);
51 // Returns the list of all ESMs.
52 nsresult GetLoadedESModules(nsTArray<nsCString>& aLoadedModules);
54 nsresult GetModuleImportStack(const nsACString& aLocation,
55 nsACString& aRetval);
57 void FindTargetObject(JSContext* aCx, JS::MutableHandleObject aTargetObject);
59 static void InitStatics();
60 static void UnloadLoaders();
61 static void ShutdownLoaders();
63 static mozJSModuleLoader* Get() {
64 MOZ_ASSERT(sSelf, "Should have already created the module loader");
65 return sSelf;
68 JSObject* GetSharedGlobal() {
69 MOZ_ASSERT(mLoaderGlobal);
70 return mLoaderGlobal;
73 private:
74 void InitSharedGlobal(JSContext* aCx);
76 void InitSyncModuleLoaderForGlobal(nsIGlobalObject* aGlobal);
77 void DisconnectSyncModuleLoaderFromGlobal();
79 friend class mozilla::loader::NonSharedGlobalSyncModuleLoaderScope;
81 public:
82 static mozJSModuleLoader* GetDevToolsLoader() { return sDevToolsLoader; }
83 static mozJSModuleLoader* GetOrCreateDevToolsLoader(JSContext* aCx);
85 // Synchronously load an ES6 module and all its dependencies.
86 nsresult ImportESModule(JSContext* aCx, const nsACString& aResourceURI,
87 JS::MutableHandleObject aModuleNamespace);
89 #ifdef STARTUP_RECORDER_ENABLED
90 void RecordImportStack(JSContext* aCx,
91 JS::loader::ModuleLoadRequest* aRequest);
92 #endif
94 nsresult IsESModuleLoaded(const nsACString& aResourceURI, bool* aRetval);
95 bool IsLoaderGlobal(JSObject* aObj) { return mLoaderGlobal == aObj; }
96 bool IsDevToolsLoader() const { return this == sDevToolsLoader; }
98 static bool IsSharedSystemGlobal(nsIGlobalObject* aGlobal);
99 static bool IsDevToolsLoaderGlobal(nsIGlobalObject* aGlobal);
101 // Public methods for use from SyncModuleLoader.
102 static bool IsTrustedScheme(nsIURI* aURI);
103 static nsresult LoadSingleModuleScript(
104 mozilla::loader::SyncModuleLoader* aModuleLoader, JSContext* aCx,
105 JS::loader::ModuleLoadRequest* aRequest,
106 JS::MutableHandleScript aScriptOut);
108 private:
109 static nsresult ReadScriptOnMainThread(JSContext* aCx,
110 const nsCString& aLocation,
111 nsCString& aData);
112 static nsresult LoadSingleModuleScriptOnWorker(
113 mozilla::loader::SyncModuleLoader* aModuleLoader, JSContext* aCx,
114 JS::loader::ModuleLoadRequest* aRequest,
115 JS::MutableHandleScript aScriptOut);
117 public:
118 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
120 bool DefineJSServices(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
122 protected:
123 mozJSModuleLoader();
124 ~mozJSModuleLoader();
126 friend class XPCJSRuntime;
128 private:
129 static mozilla::StaticRefPtr<mozJSModuleLoader> sSelf;
130 static mozilla::StaticRefPtr<mozJSModuleLoader> sDevToolsLoader;
132 void Unload();
133 void UnloadModules();
135 void CreateLoaderGlobal(JSContext* aCx, const nsACString& aLocation,
136 JS::MutableHandleObject aGlobal);
137 void CreateDevToolsLoaderGlobal(JSContext* aCx, const nsACString& aLocation,
138 JS::MutableHandleObject aGlobal);
140 bool CreateJSServices(JSContext* aCx);
142 static nsresult GetSourceFile(nsIURI* aResolvedURI, nsIFile** aSourceFileOut);
144 static bool LocationIsRealFile(nsIURI* aURI);
146 static void SetModuleOptions(JS::CompileOptions& aOptions);
148 // Get the script for a given location, either from a cached stencil or by
149 // compiling it from source.
150 static nsresult GetScriptForLocation(JSContext* aCx, ModuleLoaderInfo& aInfo,
151 nsIFile* aModuleFile, bool aUseMemMap,
152 JS::MutableHandleScript aScriptOut,
153 char** aLocationOut = nullptr);
155 static JSScript* InstantiateStencil(JSContext* aCx, JS::Stencil* aStencil);
157 class ModuleEntry {
158 public:
159 explicit ModuleEntry(JS::RootingContext* aRootingCx)
160 : obj(aRootingCx), exports(aRootingCx), thisObjectKey(aRootingCx) {
161 location = nullptr;
164 ~ModuleEntry() { Clear(); }
166 void Clear() {
167 if (obj) {
168 if (JS_HasExtensibleLexicalEnvironment(obj)) {
169 JS::RootedObject lexicalEnv(mozilla::dom::RootingCx(),
170 JS_ExtensibleLexicalEnvironment(obj));
171 JS_SetAllNonReservedSlotsToUndefined(lexicalEnv);
173 JS_SetAllNonReservedSlotsToUndefined(obj);
174 obj = nullptr;
175 thisObjectKey = nullptr;
178 if (location) {
179 free(location);
182 obj = nullptr;
183 thisObjectKey = nullptr;
184 location = nullptr;
187 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
189 JS::PersistentRootedObject obj;
190 JS::PersistentRootedObject exports;
191 JS::PersistentRootedScript thisObjectKey;
192 char* location;
193 nsCString resolvedURL;
196 #ifdef STARTUP_RECORDER_ENABLED
197 nsTHashMap<nsCStringHashKey, nsCString> mImportStacks;
198 #endif
200 bool mInitialized;
201 bool mIsUnloaded = false;
202 #ifdef DEBUG
203 bool mIsInitializingLoaderGlobal = false;
204 #endif
205 JS::PersistentRooted<JSObject*> mLoaderGlobal;
206 JS::PersistentRooted<JSObject*> mServicesObj;
208 RefPtr<mozilla::loader::SyncModuleLoader> mModuleLoader;
211 namespace mozilla::loader {
213 // Automatically allocate and initialize a sync module loader for given
214 // non-shared global, and override the module loader for the global with sync
215 // module loader.
217 // This is not re-entrant, and the consumer must check IsActive method before
218 // allocating this on the stack.
220 // The consumer should ensure the target global's module loader has no
221 // ongoing fetching modules (ModuleLoaderBase::HasFetchingModules).
222 // If there's any fetching modules, the consumer should wait for them before
223 // allocating this class on the stack.
225 // The consumer should also verify that the target global has module loader,
226 // as a part of the above step.
228 // The loader returned by ActiveLoader can be reused only when
229 // ActiveLoader's global matches the global the consumer wants to use.
230 class MOZ_STACK_CLASS NonSharedGlobalSyncModuleLoaderScope {
231 public:
232 NonSharedGlobalSyncModuleLoaderScope(JSContext* aCx,
233 nsIGlobalObject* aGlobal);
234 ~NonSharedGlobalSyncModuleLoaderScope();
236 // After successfully importing a module graph, move all imported modules to
237 // the target global's module loader.
238 void Finish();
240 // Returns true if another instance of NonSharedGlobalSyncModuleLoaderScope
241 // is on stack.
242 static bool IsActive();
244 static mozJSModuleLoader* ActiveLoader();
246 static void InitStatics();
248 private:
249 RefPtr<mozJSModuleLoader> mLoader;
251 // Reference to thread-local module loader on the stack.
252 // This is used by another sync module load during a sync module load is
253 // ongoing.
254 static MOZ_THREAD_LOCAL(mozJSModuleLoader*) sTlsActiveLoader;
256 // The module loader of the target global.
257 RefPtr<JS::loader::ModuleLoaderBase> mAsyncModuleLoader;
259 mozilla::Maybe<JS::loader::AutoOverrideModuleLoader> mMaybeOverride;
262 } // namespace mozilla::loader
264 #endif // mozJSModuleLoader_h