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
19 #include "nsClassHashtable.h"
21 #include "js/CompileOptions.h"
22 #include "js/experimental/JSStencil.h"
24 #include "xpcpublic.h"
27 class ModuleLoaderInfo
;
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
41 namespace mozilla::loader
{
43 class NonSharedGlobalSyncModuleLoaderScope
;
45 } // namespace mozilla::loader
47 class mozJSModuleLoader final
{
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
,
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");
68 JSObject
* GetSharedGlobal() {
69 MOZ_ASSERT(mLoaderGlobal
);
74 void InitSharedGlobal(JSContext
* aCx
);
76 void InitSyncModuleLoaderForGlobal(nsIGlobalObject
* aGlobal
);
77 void DisconnectSyncModuleLoaderFromGlobal();
79 friend class mozilla::loader::NonSharedGlobalSyncModuleLoaderScope
;
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
);
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
);
109 static nsresult
ReadScriptOnMainThread(JSContext
* aCx
,
110 const nsCString
& aLocation
,
112 static nsresult
LoadSingleModuleScriptOnWorker(
113 mozilla::loader::SyncModuleLoader
* aModuleLoader
, JSContext
* aCx
,
114 JS::loader::ModuleLoadRequest
* aRequest
,
115 JS::MutableHandleScript aScriptOut
);
118 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
);
120 bool DefineJSServices(JSContext
* aCx
, JS::Handle
<JSObject
*> aGlobal
);
124 ~mozJSModuleLoader();
126 friend class XPCJSRuntime
;
129 static mozilla::StaticRefPtr
<mozJSModuleLoader
> sSelf
;
130 static mozilla::StaticRefPtr
<mozJSModuleLoader
> sDevToolsLoader
;
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
);
159 explicit ModuleEntry(JS::RootingContext
* aRootingCx
)
160 : obj(aRootingCx
), exports(aRootingCx
), thisObjectKey(aRootingCx
) {
164 ~ModuleEntry() { Clear(); }
168 if (JS_HasExtensibleLexicalEnvironment(obj
)) {
169 JS::RootedObject
lexicalEnv(mozilla::dom::RootingCx(),
170 JS_ExtensibleLexicalEnvironment(obj
));
171 JS_SetAllNonReservedSlotsToUndefined(lexicalEnv
);
173 JS_SetAllNonReservedSlotsToUndefined(obj
);
175 thisObjectKey
= nullptr;
183 thisObjectKey
= nullptr;
187 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const;
189 JS::PersistentRootedObject obj
;
190 JS::PersistentRootedObject exports
;
191 JS::PersistentRootedScript thisObjectKey
;
193 nsCString resolvedURL
;
196 #ifdef STARTUP_RECORDER_ENABLED
197 nsTHashMap
<nsCStringHashKey
, nsCString
> mImportStacks
;
201 bool mIsUnloaded
= false;
203 bool mIsInitializingLoaderGlobal
= false;
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
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
{
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.
240 // Returns true if another instance of NonSharedGlobalSyncModuleLoaderScope
242 static bool IsActive();
244 static mozJSModuleLoader
* ActiveLoader();
246 static void InitStatics();
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
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