tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

mozJSModuleLoader.h (8503B)


      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/. */
      6 
      7 #ifndef mozJSModuleLoader_h
      8 #define mozJSModuleLoader_h
      9 
     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"
     23 
     24 #include "xpcpublic.h"
     25 
     26 class nsIFile;
     27 class ModuleLoaderInfo;
     28 
     29 namespace mozilla {
     30 class ScriptPreloader;
     31 }  // namespace mozilla
     32 
     33 namespace JS::loader {
     34 class ModuleLoadRequest;
     35 }  // namespace JS::loader
     36 
     37 #if defined(NIGHTLY_BUILD) || defined(MOZ_DEV_EDITION) || defined(DEBUG)
     38 #  define STARTUP_RECORDER_ENABLED
     39 #endif
     40 
     41 namespace mozilla::loader {
     42 
     43 class NonSharedGlobalSyncModuleLoaderScope;
     44 
     45 }  // namespace mozilla::loader
     46 
     47 class mozJSModuleLoader final {
     48 public:
     49  NS_INLINE_DECL_REFCOUNTING(mozJSModuleLoader);
     50 
     51  // Returns the list of all ESMs.
     52  nsresult GetLoadedESModules(nsTArray<nsCString>& aLoadedModules);
     53 
     54  nsresult GetModuleImportStack(const nsACString& aLocation,
     55                                nsACString& aRetval);
     56 
     57  void FindTargetObject(JSContext* aCx, JS::MutableHandleObject aTargetObject);
     58 
     59  static void InitStatics();
     60  static void UnloadLoaders();
     61  static void ShutdownLoaders();
     62 
     63  static mozJSModuleLoader* Get() {
     64    MOZ_ASSERT(sSelf, "Should have already created the module loader");
     65    return sSelf;
     66  }
     67 
     68  JSObject* GetSharedGlobal() {
     69    MOZ_ASSERT(mLoaderGlobal);
     70    return mLoaderGlobal;
     71  }
     72 
     73 private:
     74  void InitSharedGlobal(JSContext* aCx);
     75 
     76  void InitSyncModuleLoaderForGlobal(nsIGlobalObject* aGlobal);
     77  void DisconnectSyncModuleLoaderFromGlobal();
     78 
     79  friend class mozilla::loader::NonSharedGlobalSyncModuleLoaderScope;
     80 
     81 public:
     82  static mozJSModuleLoader* GetDevToolsLoader() { return sDevToolsLoader; }
     83  static mozJSModuleLoader* GetOrCreateDevToolsLoader(JSContext* aCx);
     84 
     85  // Synchronously load an ES6 module and all its dependencies.
     86  nsresult ImportESModule(JSContext* aCx, const nsACString& aResourceURI,
     87                          JS::MutableHandleObject aModuleNamespace);
     88 
     89 #ifdef STARTUP_RECORDER_ENABLED
     90  void RecordImportStack(JSContext* aCx,
     91                         JS::loader::ModuleLoadRequest* aRequest);
     92 #endif
     93 
     94  nsresult IsESModuleLoaded(const nsACString& aResourceURI, bool* aRetval);
     95  bool IsLoaderGlobal(JSObject* aObj) { return mLoaderGlobal == aObj; }
     96  bool IsDevToolsLoader() const { return this == sDevToolsLoader; }
     97 
     98  static bool IsSharedSystemGlobal(nsIGlobalObject* aGlobal);
     99  static bool IsDevToolsLoaderGlobal(nsIGlobalObject* aGlobal);
    100 
    101  // Public methods for use from SyncModuleLoader.
    102  static nsresult LoadSingleModuleScript(
    103      mozilla::loader::SyncModuleLoader* aModuleLoader, JSContext* aCx,
    104      JS::loader::ModuleLoadRequest* aRequest,
    105      JS::MutableHandleScript aScriptOut);
    106 
    107 private:
    108  static nsresult ReadScriptOnMainThread(JSContext* aCx,
    109                                         const nsCString& aLocation,
    110                                         nsCString& aData);
    111  static nsresult LoadSingleModuleScriptOnWorker(
    112      mozilla::loader::SyncModuleLoader* aModuleLoader, JSContext* aCx,
    113      JS::loader::ModuleLoadRequest* aRequest,
    114      JS::MutableHandleScript aScriptOut);
    115 
    116 public:
    117  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
    118 
    119  bool DefineJSServices(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
    120 
    121 protected:
    122  mozJSModuleLoader();
    123  ~mozJSModuleLoader();
    124 
    125  friend class XPCJSRuntime;
    126 
    127 private:
    128  static mozilla::StaticRefPtr<mozJSModuleLoader> sSelf;
    129  static mozilla::StaticRefPtr<mozJSModuleLoader> sDevToolsLoader;
    130 
    131  void Unload();
    132  void UnloadModules();
    133 
    134  void CreateLoaderGlobal(JSContext* aCx, const nsACString& aLocation,
    135                          JS::MutableHandleObject aGlobal);
    136  void CreateDevToolsLoaderGlobal(JSContext* aCx, const nsACString& aLocation,
    137                                  JS::MutableHandleObject aGlobal);
    138 
    139  bool CreateJSServices(JSContext* aCx);
    140 
    141  static nsresult GetSourceFile(nsIURI* aResolvedURI, nsIFile** aSourceFileOut);
    142 
    143  static bool LocationIsRealFile(nsIURI* aURI);
    144 
    145  static void SetModuleOptions(JS::CompileOptions& aOptions);
    146 
    147  // Get the script for a given location, either from a cached stencil or by
    148  // compiling it from source.
    149  static nsresult GetScriptForLocation(JSContext* aCx, ModuleLoaderInfo& aInfo,
    150                                       nsIFile* aModuleFile, bool aUseMemMap,
    151                                       JS::MutableHandleScript aScriptOut,
    152                                       char** aLocationOut = nullptr);
    153 
    154  static JSScript* InstantiateStencil(JSContext* aCx, JS::Stencil* aStencil);
    155 
    156  class ModuleEntry {
    157   public:
    158    explicit ModuleEntry(JS::RootingContext* aRootingCx)
    159        : obj(aRootingCx), exports(aRootingCx), thisObjectKey(aRootingCx) {
    160      location = nullptr;
    161    }
    162 
    163    ~ModuleEntry() { Clear(); }
    164 
    165    void Clear() {
    166      if (obj) {
    167        if (JS_HasExtensibleLexicalEnvironment(obj)) {
    168          JS::RootedObject lexicalEnv(mozilla::dom::RootingCx(),
    169                                      JS_ExtensibleLexicalEnvironment(obj));
    170          JS_SetAllNonReservedSlotsToUndefined(lexicalEnv);
    171        }
    172        JS_SetAllNonReservedSlotsToUndefined(obj);
    173        obj = nullptr;
    174        thisObjectKey = nullptr;
    175      }
    176 
    177      if (location) {
    178        free(location);
    179      }
    180 
    181      obj = nullptr;
    182      thisObjectKey = nullptr;
    183      location = nullptr;
    184    }
    185 
    186    size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
    187 
    188    JS::PersistentRootedObject obj;
    189    JS::PersistentRootedObject exports;
    190    JS::PersistentRootedScript thisObjectKey;
    191    char* location;
    192    nsCString resolvedURL;
    193  };
    194 
    195 #ifdef STARTUP_RECORDER_ENABLED
    196  nsTHashMap<nsCStringHashKey, nsCString> mImportStacks;
    197 #endif
    198 
    199  bool mInitialized;
    200  bool mIsUnloaded = false;
    201 #ifdef DEBUG
    202  bool mIsInitializingLoaderGlobal = false;
    203 #endif
    204  JS::PersistentRooted<JSObject*> mLoaderGlobal;
    205  JS::PersistentRooted<JSObject*> mServicesObj;
    206 
    207  RefPtr<mozilla::loader::SyncModuleLoader> mModuleLoader;
    208 };
    209 
    210 namespace mozilla::loader {
    211 
    212 // Automatically allocate and initialize a sync module loader for given
    213 // non-shared global, and override the module loader for the global with sync
    214 // module loader.
    215 //
    216 // This is not re-entrant, and the consumer must check IsActive method before
    217 // allocating this on the stack.
    218 //
    219 // The consumer should ensure the target global's module loader has no
    220 // ongoing fetching modules (ModuleLoaderBase::HasFetchingModules).
    221 // If there's any fetching modules, the consumer should wait for them before
    222 // allocating this class on the stack.
    223 //
    224 // The consumer should also verify that the target global has module loader,
    225 // as a part of the above step.
    226 //
    227 // The loader returned by ActiveLoader can be reused only when
    228 // ActiveLoader's global matches the global the consumer wants to use.
    229 class MOZ_STACK_CLASS NonSharedGlobalSyncModuleLoaderScope {
    230 public:
    231  NonSharedGlobalSyncModuleLoaderScope(JSContext* aCx,
    232                                       nsIGlobalObject* aGlobal);
    233  ~NonSharedGlobalSyncModuleLoaderScope();
    234 
    235  // After successfully importing a module graph, move all imported modules to
    236  // the target global's module loader.
    237  void Finish();
    238 
    239  // Returns true if another instance of NonSharedGlobalSyncModuleLoaderScope
    240  // is on stack.
    241  static bool IsActive();
    242 
    243  static mozJSModuleLoader* ActiveLoader();
    244 
    245  static void InitStatics();
    246 
    247 private:
    248  RefPtr<mozJSModuleLoader> mLoader;
    249 
    250  // Reference to thread-local module loader on the stack.
    251  // This is used by another sync module load during a sync module load is
    252  // ongoing.
    253  static MOZ_THREAD_LOCAL(mozJSModuleLoader*) sTlsActiveLoader;
    254 
    255  // The module loader of the target global.
    256  RefPtr<JS::loader::ModuleLoaderBase> mAsyncModuleLoader;
    257 
    258  mozilla::Maybe<JS::loader::AutoOverrideModuleLoader> mMaybeOverride;
    259 };
    260 
    261 }  // namespace mozilla::loader
    262 
    263 #endif  // mozJSModuleLoader_h