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