tor-browser

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

ModuleLoaderBase.h (22539B)


      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 js_loader_ModuleLoaderBase_h
      8 #define js_loader_ModuleLoaderBase_h
      9 
     10 #include "LoadedScript.h"
     11 #include "ScriptLoadRequestList.h"
     12 
     13 #include "ImportMap.h"
     14 #include "js/ColumnNumber.h"  // JS::ColumnNumberOneOrigin
     15 #include "js/TypeDecls.h"     // JS::MutableHandle, JS::Handle, JS::Root
     16 #include "js/Modules.h"
     17 #include "nsRefPtrHashtable.h"
     18 #include "nsCOMArray.h"
     19 #include "nsCOMPtr.h"
     20 #include "nsILoadInfo.h"    // nsSecurityFlags
     21 #include "nsThreadUtils.h"  // GetMainThreadSerialEventTarget
     22 #include "nsURIHashKey.h"
     23 #include "mozilla/Attributes.h"  // MOZ_RAII
     24 #include "mozilla/CORSMode.h"
     25 #include "mozilla/MaybeOneOf.h"
     26 #include "mozilla/UniquePtr.h"
     27 #include "mozilla/dom/ReferrerPolicyBinding.h"
     28 #include "mozilla/StaticPrefs_layout.h"
     29 #include "ResolveResult.h"
     30 
     31 class nsIConsoleReportCollector;
     32 class nsIURI;
     33 
     34 namespace mozilla {
     35 
     36 class LazyLogModule;
     37 union Utf8Unit;
     38 
     39 namespace dom {
     40 class SRIMetadata;
     41 }  // namespace dom
     42 
     43 }  // namespace mozilla
     44 
     45 namespace JS {
     46 
     47 class CompileOptions;
     48 
     49 template <typename UnitT>
     50 class SourceText;
     51 
     52 namespace loader {
     53 
     54 class LoadContextBase;
     55 class ModuleLoaderBase;
     56 class ModuleLoadRequest;
     57 class ModuleScript;
     58 
     59 /*
     60 * [DOMDOC] Shared Classic/Module Script Methods
     61 *
     62 * The ScriptLoaderInterface defines the shared methods needed by both
     63 * ScriptLoaders (loading classic scripts) and ModuleLoaders (loading module
     64 * scripts). These include:
     65 *
     66 *     * Error Logging
     67 *     * Generating the compile options
     68 *     * Optional: Caching
     69 *
     70 * ScriptLoaderInterface does not provide any implementations.
     71 * It enables the ModuleLoaderBase to reference back to the behavior implemented
     72 * by a given ScriptLoader.
     73 *
     74 * Not all methods will be used by all ModuleLoaders. For example, caching
     75 * does not apply to workers, as we only work with source text there.
     76 * Fully virtual methods are implemented by all.
     77 *
     78 */
     79 
     80 class ScriptLoaderInterface : public nsISupports {
     81 public:
     82  // Alias common classes.
     83  using ScriptFetchOptions = JS::loader::ScriptFetchOptions;
     84  using ScriptKind = JS::loader::ScriptKind;
     85  using ScriptLoadRequest = JS::loader::ScriptLoadRequest;
     86  using ScriptLoadRequestList = JS::loader::ScriptLoadRequestList;
     87  using ModuleLoadRequest = JS::loader::ModuleLoadRequest;
     88 
     89  virtual ~ScriptLoaderInterface() = default;
     90 
     91  // In some environments, we will need to default to a base URI
     92  virtual nsIURI* GetBaseURI() const = 0;
     93 
     94  virtual void ReportErrorToConsole(ScriptLoadRequest* aRequest,
     95                                    nsresult aResult) const = 0;
     96 
     97  virtual void ReportWarningToConsole(
     98      ScriptLoadRequest* aRequest, const char* aMessageName,
     99      const nsTArray<nsString>& aParams = nsTArray<nsString>()) const = 0;
    100 
    101  // Similar to Report*ToConsole(), only non-null in dom/script/ScriptLoader
    102  // as we currently only load importmaps there.
    103  virtual nsIConsoleReportCollector* GetConsoleReportCollector() const {
    104    return nullptr;
    105  }
    106 
    107  // Fill in CompileOptions, as well as produce the introducer script for
    108  // subsequent calls to UpdateDebuggerMetadata
    109  virtual nsresult FillCompileOptionsForRequest(
    110      JSContext* cx, ScriptLoadRequest* aRequest, CompileOptions* aOptions,
    111      MutableHandle<JSScript*> aIntroductionScript) = 0;
    112 
    113  virtual nsresult MaybePrepareModuleForDiskCacheAfterExecute(
    114      ModuleLoadRequest* aRequest, nsresult aRv) {
    115    return NS_OK;
    116  }
    117 
    118  virtual void MaybeUpdateDiskCache() {}
    119 };
    120 
    121 class ModuleMapKey : public PLDHashEntryHdr {
    122 public:
    123  using KeyType = const ModuleMapKey&;
    124  using KeyTypePointer = const ModuleMapKey*;
    125 
    126  ModuleMapKey(const nsIURI* aUri, const ModuleType aModuleType)
    127      : mUri(const_cast<nsIURI*>(aUri)), mModuleType(aModuleType) {
    128    MOZ_COUNT_CTOR(ModuleMapKey);
    129    MOZ_ASSERT(aUri);
    130  }
    131  explicit ModuleMapKey(KeyTypePointer aOther)
    132      : mUri(std::move(aOther->mUri)), mModuleType(aOther->mModuleType) {
    133    MOZ_COUNT_CTOR(ModuleMapKey);
    134    MOZ_ASSERT(mUri);
    135  }
    136  ModuleMapKey(ModuleMapKey&& aOther)
    137      : mUri(std::move(aOther.mUri)), mModuleType(aOther.mModuleType) {
    138    MOZ_COUNT_CTOR(ModuleMapKey);
    139    MOZ_ASSERT(mUri);
    140  }
    141  MOZ_COUNTED_DTOR(ModuleMapKey)
    142 
    143  bool KeyEquals(KeyTypePointer aKey) const {
    144    if (mModuleType != aKey->mModuleType) {
    145      return false;
    146    }
    147 
    148    bool eq;
    149    if (NS_SUCCEEDED(mUri->Equals(aKey->mUri, &eq))) {
    150      return eq;
    151    }
    152 
    153    return false;
    154  }
    155 
    156  static KeyTypePointer KeyToPointer(KeyType key) { return &key; }
    157 
    158  static PLDHashNumber HashKey(KeyTypePointer aKey) {
    159    MOZ_ASSERT(aKey->mUri);
    160    nsAutoCString spec;
    161    // This is based on `nsURIHashKey`, and it ignores GetSpec() failures, so
    162    // do the same here.
    163    (void)aKey->mUri->GetSpec(spec);
    164    return mozilla::HashGeneric(mozilla::HashString(spec), aKey->mModuleType);
    165  }
    166 
    167  enum { ALLOW_MEMMOVE = true };
    168 
    169  const nsCOMPtr<nsIURI> mUri;
    170  const ModuleType mModuleType;
    171 };
    172 
    173 /*
    174 * [DOMDOC] Module Loading
    175 *
    176 * ModuleLoaderBase provides support for loading module graphs as defined in the
    177 * EcmaScript specification. A derived module loader class must be created for a
    178 * specific use case (for example loading HTML module scripts). The derived
    179 * class provides operations such as fetching of source code and scheduling of
    180 * module execution.
    181 *
    182 * Module loading works in terms of 'requests' which hold data about modules as
    183 * they move through the loading process. There may be more than one load
    184 * request active for a single module URI, but the module is only loaded
    185 * once. This is achieved by tracking all fetching and fetched modules in the
    186 * module map.
    187 *
    188 * The module map is made up of two parts. A module that has been requested but
    189 * has not finished fetching is represented by an entry in the mFetchingModules
    190 * map. A module which has been fetched and compiled is represented by a
    191 * ModuleScript in the mFetchedModules map.
    192 *
    193 * Module loading typically works as follows:
    194 *
    195 * 1.  The client ensures there is an instance of the derived module loader
    196 *     class for its global or creates one if necessary.
    197 *
    198 * 2.  The client creates a ModuleLoadRequest object for the module to load and
    199 *     calls the loader's StartModuleLoad() method. This is a top-level request,
    200 *     i.e. not an import.
    201 *
    202 * 3.  The module loader calls the virtual method CanStartLoad() to check
    203 *     whether the request should be loaded.
    204 *
    205 * 4.  If the module is not already present in the module map, the loader calls
    206 *     the virtual method StartFetch() to set up an asynchronous operation to
    207 *     fetch the module source.
    208 *
    209 * 5.  When the fetch operation is complete, the derived loader calls
    210 *     OnFetchComplete() passing an error code to indicate success or failure.
    211 *
    212 * 6.  On success, the loader attempts to create a module script by calling the
    213 *     virtual CompileFetchedModule() method.
    214 *
    215 * 7.  If compilation is successful, the loader creates load requests for any
    216 *     imported modules if present. If so, the process repeats from step 3.
    217 *
    218 * 8.  When a load request is completed, the virtual OnModuleLoadComplete()
    219 *     method is called. This is called for the top-level request and import
    220 *     requests.
    221 *
    222 * 9.  The client calls InstantiateModuleGraph() for the top-level request. This
    223 *     links the loaded module graph.
    224 *
    225 * 10. The client calls EvaluateModule() to execute the top-level module.
    226 */
    227 class ModuleLoaderBase : public nsISupports {
    228 public:
    229  // Alias common classes.
    230  using LoadedScript = JS::loader::LoadedScript;
    231  using ScriptFetchOptions = JS::loader::ScriptFetchOptions;
    232  using ScriptLoadRequest = JS::loader::ScriptLoadRequest;
    233  using ModuleLoadRequest = JS::loader::ModuleLoadRequest;
    234 
    235 private:
    236  /*
    237   * Represents an ongoing load operation for a URI initiated for one request
    238   * and which may have other requests waiting for it to complete.
    239   *
    240   * These are tracked in the mFetchingModules map.
    241   */
    242  class LoadingRequest final : public nsISupports {
    243    ~LoadingRequest() = default;
    244 
    245   public:
    246    NS_DECL_CYCLE_COLLECTING_ISUPPORTS_FINAL
    247    NS_DECL_CYCLE_COLLECTION_CLASS(LoadingRequest)
    248 
    249    // The request that initiated the load and which is currently fetching or
    250    // being compiled.
    251    RefPtr<ModuleLoadRequest> mRequest;
    252 
    253    // A list of any other requests for the same URI that are waiting for the
    254    // initial load to complete. These will be resumed by ResumeWaitingRequests
    255    // when that happens.
    256    nsTArray<RefPtr<ModuleLoadRequest>> mWaiting;
    257  };
    258 
    259  // Module map
    260  nsRefPtrHashtable<ModuleMapKey, LoadingRequest> mFetchingModules;
    261  nsRefPtrHashtable<ModuleMapKey, ModuleScript> mFetchedModules;
    262 
    263  // List of dynamic imports that are currently being loaded.
    264  ScriptLoadRequestList mDynamicImportRequests;
    265 
    266  nsCOMPtr<nsIGlobalObject> mGlobalObject;
    267 
    268  // If non-null, this module loader is overridden by the module loader pointed
    269  // by mOverriddenBy.
    270  // See ModuleLoaderBase::GetCurrentModuleLoader for more details.
    271  RefPtr<ModuleLoaderBase> mOverriddenBy;
    272 
    273  // https://html.spec.whatwg.org/multipage/webappapis.html#import-maps-allowed
    274  //
    275  // Each Window has an import maps allowed boolean, initially true.
    276  bool mImportMapsAllowed = true;
    277 
    278 protected:
    279  RefPtr<ScriptLoaderInterface> mLoader;
    280 
    281  mozilla::UniquePtr<ImportMap> mImportMap;
    282 
    283  virtual ~ModuleLoaderBase();
    284 
    285 #ifdef DEBUG
    286  const ScriptLoadRequestList& DynamicImportRequests() const {
    287    return mDynamicImportRequests;
    288  }
    289 #endif
    290 
    291 public:
    292  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    293  NS_DECL_CYCLE_COLLECTION_CLASS(ModuleLoaderBase)
    294  explicit ModuleLoaderBase(ScriptLoaderInterface* aLoader,
    295                            nsIGlobalObject* aGlobalObject);
    296 
    297  void CancelFetchingModules();
    298 
    299  // Called to break cycles during shutdown to prevent memory leaks.
    300  void Shutdown();
    301 
    302  virtual nsIURI* GetBaseURI() const { return mLoader->GetBaseURI(); };
    303 
    304  using MaybeSourceText =
    305      mozilla::MaybeOneOf<SourceText<char16_t>, SourceText<Utf8Unit>>;
    306 
    307  // Methods that must be implemented by an extending class. These are called
    308  // internally by ModuleLoaderBase.
    309 
    310 private:
    311  // Determine the environment's referrer when the referrer script is empty.
    312  //
    313  // https://html.spec.whatwg.org/#hostloadimportedmodule
    314  //   Step 5. Let fetchReferrer be "client".
    315  //
    316  // Then check the referrer policy specification for determining the referrer.
    317  // https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer
    318  virtual nsIURI* GetClientReferrerURI() { return nullptr; }
    319 
    320  // Create default ScriptFetchOptions if the referrer script is empty.
    321  virtual already_AddRefed<JS::loader::ScriptFetchOptions>
    322  CreateDefaultScriptFetchOptions() {
    323    return nullptr;
    324  }
    325 
    326  // Create a ModuleLoadRequest for static/dynamic imports.
    327  virtual already_AddRefed<ModuleLoadRequest> CreateRequest(
    328      JSContext* aCx, nsIURI* aURI, Handle<JSObject*> aModuleRequest,
    329      Handle<Value> aHostDefined, Handle<Value> aPayload, bool aIsDynamicImport,
    330      ScriptFetchOptions* aOptions,
    331      mozilla::dom::ReferrerPolicy aReferrerPolicy, nsIURI* aBaseURL,
    332      const mozilla::dom::SRIMetadata& aSriMetadata) = 0;
    333 
    334  virtual bool IsDynamicImportSupported() { return true; }
    335 
    336  virtual bool IsForServiceWorker() const { return false; }
    337 
    338  // Called when dynamic import started successfully.
    339  virtual void OnDynamicImportStarted(ModuleLoadRequest* aRequest) {}
    340 
    341  // Check whether we can load a module. May return false with |aRvOut| set to
    342  // NS_OK to abort load without returning an error.
    343  virtual bool CanStartLoad(ModuleLoadRequest* aRequest, nsresult* aRvOut) = 0;
    344 
    345  // Start the process of fetching module source or serialized stencil. This is
    346  // only called if CanStartLoad returned true.
    347  virtual nsresult StartFetch(ModuleLoadRequest* aRequest) = 0;
    348 
    349  // Create a JS module for a fetched module request. This might compile source
    350  // text or decode stencil.
    351  virtual nsresult CompileFetchedModule(
    352      JSContext* aCx, Handle<JSObject*> aGlobal, CompileOptions& aOptions,
    353      ModuleLoadRequest* aRequest, MutableHandle<JSObject*> aModuleOut) = 0;
    354 
    355  // Called when a module script has been loaded, including imports.
    356  virtual void OnModuleLoadComplete(ModuleLoadRequest* aRequest) = 0;
    357 
    358  virtual bool IsModuleEvaluationAborted(ModuleLoadRequest* aRequest) {
    359    return false;
    360  }
    361 
    362  // Get the error message when resolving failed. The default is to call
    363  // nsContentUtils::FormatLoalizedString. But currently
    364  // nsContentUtils::FormatLoalizedString cannot be called on a worklet thread,
    365  // see bug 1808301. So WorkletModuleLoader will override this function to
    366  // get the error message.
    367  virtual nsresult GetResolveFailureMessage(ResolveError aError,
    368                                            const nsAString& aSpecifier,
    369                                            nsAString& aResult);
    370 
    371  // Public API methods.
    372 
    373 public:
    374  ScriptLoaderInterface* GetScriptLoaderInterface() const { return mLoader; }
    375 
    376  nsIGlobalObject* GetGlobalObject() const { return mGlobalObject; }
    377 
    378  bool HasFetchingModules() const;
    379 
    380  bool HasPendingDynamicImports() const;
    381  void CancelDynamicImport(ModuleLoadRequest* aRequest, nsresult aResult);
    382 #ifdef DEBUG
    383  bool HasDynamicImport(const ModuleLoadRequest* aRequest) const;
    384 #endif
    385 
    386  // Start a load for a module script URI. Returns immediately if the module is
    387  // already being loaded.
    388  nsresult StartModuleLoad(ModuleLoadRequest* aRequest);
    389  nsresult RestartModuleLoad(ModuleLoadRequest* aRequest);
    390 
    391  // Notify the module loader when a fetch started by StartFetch() completes.
    392  nsresult OnFetchComplete(ModuleLoadRequest* aRequest, nsresult aRv);
    393 
    394  // Link the module and all its imports. This must occur prior to evaluation.
    395  bool InstantiateModuleGraph(ModuleLoadRequest* aRequest);
    396 
    397  // Executes the module.
    398  // Implements https://html.spec.whatwg.org/#run-a-module-script
    399  nsresult EvaluateModule(ModuleLoadRequest* aRequest);
    400 
    401  // Evaluate a module in the given context. Does not push an entry to the
    402  // execution stack.
    403  nsresult EvaluateModuleInContext(JSContext* aCx, ModuleLoadRequest* aRequest,
    404                                   ModuleErrorBehaviour errorBehaviour);
    405 
    406  void AppendDynamicImport(ModuleLoadRequest* aRequest);
    407  void ProcessDynamicImport(ModuleLoadRequest* aRequest);
    408  void CancelAndClearDynamicImports();
    409 
    410  // Process <script type="importmap">
    411  mozilla::UniquePtr<ImportMap> ParseImportMap(ScriptLoadRequest* aRequest);
    412 
    413  // Implements
    414  // https://html.spec.whatwg.org/multipage/webappapis.html#register-an-import-map
    415  void RegisterImportMap(mozilla::UniquePtr<ImportMap> aImportMap);
    416 
    417  bool HasImportMapRegistered() const { return bool(mImportMap); }
    418 
    419  // Getter for mImportMapsAllowed.
    420  bool IsImportMapAllowed() const { return mImportMapsAllowed; }
    421  // https://html.spec.whatwg.org/multipage/webappapis.html#disallow-further-import-maps
    422  void DisallowImportMaps() { mImportMapsAllowed = false; }
    423 
    424  virtual bool IsModuleTypeAllowed(ModuleType aModuleType) {
    425    if (aModuleType == ModuleType::Unknown) {
    426      return false;
    427    }
    428 
    429    if (aModuleType == ModuleType::CSS &&
    430        !mozilla::StaticPrefs::layout_css_module_scripts_enabled()) {
    431      return false;
    432    }
    433 
    434    return true;
    435  }
    436 
    437  // Returns whether there has been an entry in the import map
    438  // for the given aURI.
    439  bool GetImportMapSRI(nsIURI* aURI, nsIURI* aSourceURI,
    440                       nsIConsoleReportCollector* aReporter,
    441                       mozilla::dom::SRIMetadata* aMetadataOut);
    442 
    443  // Returns true if the module for given module key is already fetched.
    444  bool IsModuleFetched(const ModuleMapKey& key) const;
    445 
    446  nsresult GetFetchedModuleURLs(nsTArray<nsCString>& aURLs);
    447 
    448  // Override the module loader with given loader until ResetOverride is called.
    449  // While overridden, ModuleLoaderBase::GetCurrentModuleLoader returns aLoader.
    450  //
    451  // This is used by mozJSModuleLoader to temporarily override the global's
    452  // module loader with SyncModuleLoader while importing a module graph
    453  // synchronously.
    454  void SetOverride(ModuleLoaderBase* aLoader);
    455 
    456  // Returns true if SetOverride was called.
    457  bool IsOverridden();
    458 
    459  // Returns true if SetOverride was called with aLoader.
    460  bool IsOverriddenBy(ModuleLoaderBase* aLoader);
    461 
    462  void ResetOverride();
    463 
    464  // Copy fetched modules to `aDest`.
    465  // `this` shouldn't have any fetching.
    466  // `aDest` shouldn't have any fetching or fetched modules.
    467  //
    468  // This is used when starting sync module load, to replicate the module cache
    469  // in the sync module loader pointed by `aDest`.
    470  void CopyModulesTo(ModuleLoaderBase* aDest);
    471 
    472  // Move all fetched modules to `aDest`.
    473  // Both `this` and `aDest` shouldn't have any fetching.
    474  //
    475  // This is used when finishing sync module load, to reflect the loaded modules
    476  // to the async module loader pointed by `aDest`.
    477  void MoveModulesTo(ModuleLoaderBase* aDest);
    478 
    479  // Internal methods.
    480 
    481 private:
    482  friend class JS::loader::ModuleLoadRequest;
    483 
    484  static ModuleLoaderBase* GetCurrentModuleLoader(JSContext* aCx);
    485  static LoadedScript* GetLoadedScriptOrNull(Handle<JSScript*> aReferrer);
    486 
    487  static void EnsureModuleHooksInitialized();
    488 
    489  static bool HostLoadImportedModule(JSContext* aCx,
    490                                     Handle<JSScript*> aReferrer,
    491                                     Handle<JSObject*> aModuleRequest,
    492                                     Handle<Value> aHostDefined,
    493                                     Handle<Value> aPayload,
    494                                     uint32_t aLineNumber,
    495                                     JS::ColumnNumberOneOrigin aColumnNumber);
    496  static bool FinishLoadingImportedModule(JSContext* aCx,
    497                                          ModuleLoadRequest* aRequest);
    498 
    499  static bool HostPopulateImportMeta(JSContext* aCx,
    500                                     Handle<Value> aReferencingPrivate,
    501                                     Handle<JSObject*> aMetaObject);
    502  static bool ImportMetaResolve(JSContext* cx, unsigned argc, Value* vp);
    503  static JSString* ImportMetaResolveImpl(JSContext* aCx,
    504                                         Handle<Value> aReferencingPrivate,
    505                                         Handle<JSString*> aSpecifier);
    506 
    507  ResolveResult ResolveModuleSpecifier(LoadedScript* aScript,
    508                                       const nsAString& aSpecifier);
    509 
    510  nsresult HandleResolveFailure(JSContext* aCx, LoadedScript* aScript,
    511                                const nsAString& aSpecifier,
    512                                ResolveError aError, uint32_t aLineNumber,
    513                                ColumnNumberOneOrigin aColumnNumber,
    514                                MutableHandle<Value> aErrorOut);
    515 
    516  enum class RestartRequest { No, Yes };
    517  nsresult StartOrRestartModuleLoad(ModuleLoadRequest* aRequest,
    518                                    RestartRequest aRestart);
    519 
    520  bool ModuleMapContainsURL(const ModuleMapKey& key) const;
    521  bool IsModuleFetching(const ModuleMapKey& key) const;
    522  void WaitForModuleFetch(ModuleLoadRequest* aRequest);
    523 
    524 protected:
    525  void SetModuleFetchStarted(ModuleLoadRequest* aRequest);
    526 
    527 private:
    528  ModuleScript* GetFetchedModule(const ModuleMapKey& moduleMapKey) const;
    529 
    530  already_AddRefed<LoadingRequest> SetModuleFetchFinishedAndGetWaitingRequests(
    531      ModuleLoadRequest* aRequest, nsresult aResult);
    532  void ResumeWaitingRequests(LoadingRequest* aLoadingRequest, bool aSuccess);
    533  void ResumeWaitingRequest(ModuleLoadRequest* aRequest, bool aSuccess);
    534 
    535  void StartFetchingModuleDependencies(ModuleLoadRequest* aRequest);
    536 
    537  void InstantiateAndEvaluateDynamicImport(ModuleLoadRequest* aRequest);
    538 
    539  static bool OnLoadRequestedModulesResolved(JSContext* aCx, unsigned aArgc,
    540                                             Value* aVp);
    541  static bool OnLoadRequestedModulesRejected(JSContext* aCx, unsigned aArgc,
    542                                             Value* aVp);
    543  static bool OnLoadRequestedModulesResolved(JSContext* aCx,
    544                                             Handle<Value> aHostDefined);
    545  static bool OnLoadRequestedModulesRejected(JSContext* aCx,
    546                                             Handle<Value> aHostDefined,
    547                                             Handle<Value> aError);
    548  static bool OnLoadRequestedModulesResolved(ModuleLoadRequest* aRequest);
    549  static bool OnLoadRequestedModulesRejected(JSContext* aCx,
    550                                             ModuleLoadRequest* aRequest,
    551                                             Handle<Value> aError);
    552 
    553  void RemoveDynamicImport(ModuleLoadRequest* aRequest);
    554 
    555  nsresult CreateModuleScript(ModuleLoadRequest* aRequest);
    556  void DispatchModuleErrored(ModuleLoadRequest* aRequest);
    557 
    558  void OnFetchSucceeded(ModuleLoadRequest* aRequest);
    559  void OnFetchFailed(ModuleLoadRequest* aRequest);
    560  void Cancel(ModuleLoadRequest* aRequest);
    561 
    562  // The slot stored in ImportMetaResolve function.
    563  enum class ImportMetaSlots : uint32_t { ModulePrivateSlot = 0, SlotCount };
    564 
    565  // The number of args in ImportMetaResolve.
    566  static const uint32_t ImportMetaResolveNumArgs = 1;
    567  // The index of the 'specifier' argument in ImportMetaResolve.
    568  static const uint32_t ImportMetaResolveSpecifierArg = 0;
    569 
    570  // The slot containing the host defined value passed to LoadRequestedModules
    571  // promise reactions.
    572  static const uint32_t LoadReactionHostDefinedSlot = 0;
    573 
    574  // The number of args in OnLoadRequestedModulesResolved/Rejected.
    575  static const uint32_t OnLoadRequestedModulesResolvedNumArgs = 0;
    576  static const uint32_t OnLoadRequestedModulesRejectedNumArgs = 1;
    577 
    578  // The index of the 'error' argument in OnLoadRequestedModulesRejected.
    579  static const uint32_t OnLoadRequestedModulesRejectedErrorArg = 0;
    580 
    581 public:
    582  static mozilla::LazyLogModule gCspPRLog;
    583  static mozilla::LazyLogModule gModuleLoaderBaseLog;
    584 };
    585 
    586 // Override the target module loader with given module loader while this
    587 // instance is on the stack.
    588 class MOZ_RAII AutoOverrideModuleLoader {
    589 public:
    590  AutoOverrideModuleLoader(ModuleLoaderBase* aTarget,
    591                           ModuleLoaderBase* aLoader);
    592  ~AutoOverrideModuleLoader();
    593 
    594 private:
    595  RefPtr<ModuleLoaderBase> mTarget;
    596 };
    597 
    598 }  // namespace loader
    599 }  // namespace JS
    600 
    601 #endif  // js_loader_ModuleLoaderBase_h