/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
class ModuleLoaderBase; class ModuleLoadRequest; class ModuleScript;
/* * [DOMDOC] Shared Classic/Module Script Methods * * The ScriptLoaderInterface defines the shared methods needed by both * ScriptLoaders (loading classic scripts) and ModuleLoaders (loading module * scripts). These include: * * * Error Logging * * Generating the compile options * * Optional: Bytecode Encoding * * ScriptLoaderInterface does not provide any implementations. * It enables the ModuleLoaderBase to reference back to the behavior implemented * by a given ScriptLoader. * * Not all methods will be used by all ModuleLoaders. For example, Bytecode * Encoding does not apply to workers, as we only work with source text there. * Fully virtual methods are implemented by all. *
*/
class ScriptLoaderInterface : public nsISupports { public: // Alias common classes. using ScriptFetchOptions = JS::loader::ScriptFetchOptions; using ScriptKind = JS::loader::ScriptKind; using ScriptLoadRequest = JS::loader::ScriptLoadRequest; using ScriptLoadRequestList = JS::loader::ScriptLoadRequestList; using ModuleLoadRequest = JS::loader::ModuleLoadRequest;
virtual ~ScriptLoaderInterface() = default;
// In some environments, we will need to default to a base URI virtual nsIURI* GetBaseURI() const = 0;
// Fill in CompileOptions, as well as produce the introducer script for // subsequent calls to UpdateDebuggerMetadata virtual nsresult FillCompileOptionsForRequest(
JSContext* cx, ScriptLoadRequest* aRequest, JS::CompileOptions* aOptions,
JS::MutableHandle<JSScript*> aIntroductionScript) = 0;
static PLDHashNumber HashKey(KeyTypePointer aKey) {
MOZ_ASSERT(aKey->mUri);
nsAutoCString spec; // This is based on `nsURIHashKey`, and it ignores GetSpec() failures, so // do the same here.
(void)aKey->mUri->GetSpec(spec); return mozilla::HashGeneric(mozilla::HashString(spec), aKey->mModuleType);
}
/* * [DOMDOC] Module Loading * * ModuleLoaderBase provides support for loading module graphs as defined in the * EcmaScript specification. A derived module loader class must be created for a * specific use case (for example loading HTML module scripts). The derived * class provides operations such as fetching of source code and scheduling of * module execution. * * Module loading works in terms of 'requests' which hold data about modules as * they move through the loading process. There may be more than one load * request active for a single module URI, but the module is only loaded * once. This is achieved by tracking all fetching and fetched modules in the * module map. * * The module map is made up of two parts. A module that has been requested but * has not finished fetching is represented by an entry in the mFetchingModules * map. A module which has been fetched and compiled is represented by a * ModuleScript in the mFetchedModules map. * * Module loading typically works as follows: * * 1. The client ensures there is an instance of the derived module loader * class for its global or creates one if necessary. * * 2. The client creates a ModuleLoadRequest object for the module to load and * calls the loader's StartModuleLoad() method. This is a top-level request, * i.e. not an import. * * 3. The module loader calls the virtual method CanStartLoad() to check * whether the request should be loaded. * * 4. If the module is not already present in the module map, the loader calls * the virtual method StartFetch() to set up an asynchronous operation to * fetch the module source. * * 5. When the fetch operation is complete, the derived loader calls * OnFetchComplete() passing an error code to indicate success or failure. * * 6. On success, the loader attempts to create a module script by calling the * virtual CompileFetchedModule() method. * * 7. If compilation is successful, the loader creates load requests for any * imported modules if present. If so, the process repeats from step 3. * * 8. When a load request is completed, the virtual OnModuleLoadComplete() * method is called. This is called for the top-level request and import * requests. * * 9. The client calls InstantiateModuleGraph() for the top-level request. This * links the loaded module graph. * * 10. The client calls EvaluateModule() to execute the top-level module.
*/ class ModuleLoaderBase : public nsISupports { public: // Alias common classes. using LoadedScript = JS::loader::LoadedScript; using ScriptFetchOptions = JS::loader::ScriptFetchOptions; using ScriptLoadRequest = JS::loader::ScriptLoadRequest; using ModuleLoadRequest = JS::loader::ModuleLoadRequest;
private: /* * Represents an ongoing load operation for a URI initiated for one request * and which may have other requests waiting for it to complete. * * These are tracked in the mFetchingModules map.
*/ class LoadingRequest final : public nsISupports { virtual ~LoadingRequest() = default;
// The request that initiated the load and which is currently fetching or // being compiled.
RefPtr<ModuleLoadRequest> mRequest;
// A list of any other requests for the same URI that are waiting for the // initial load to complete. These will be resumed by ResumeWaitingRequests // when that happens.
nsTArray<RefPtr<ModuleLoadRequest>> mWaiting;
};
// List of dynamic imports that are currently being loaded.
ScriptLoadRequestList mDynamicImportRequests;
nsCOMPtr<nsIGlobalObject> mGlobalObject;
// If non-null, this module loader is overridden by the module loader pointed // by mOverriddenBy. // See ModuleLoaderBase::GetCurrentModuleLoader for more details.
RefPtr<ModuleLoaderBase> mOverriddenBy;
// Called when dynamic import started successfully. virtualvoid OnDynamicImportStarted(ModuleLoadRequest* aRequest) {}
// Check whether we can load a module. May return false with |aRvOut| set to // NS_OK to abort load without returning an error. virtualbool CanStartLoad(ModuleLoadRequest* aRequest, nsresult* aRvOut) = 0;
// Start the process of fetching module source (or bytecode). This is only // called if CanStartLoad returned true. virtual nsresult StartFetch(ModuleLoadRequest* aRequest) = 0;
// Create a JS module for a fetched module request. This might compile source // text or decode cached bytecode. virtual nsresult CompileFetchedModule(
JSContext* aCx, JS::Handle<JSObject*> aGlobal,
JS::CompileOptions& aOptions, ModuleLoadRequest* aRequest,
JS::MutableHandle<JSObject*> aModuleOut) = 0;
// Called when a module script has been loaded, including imports. virtualvoid OnModuleLoadComplete(ModuleLoadRequest* aRequest) = 0;
// Get the error message when resolving failed. The default is to call // nsContentUtils::FormatLoalizedString. But currently // nsContentUtils::FormatLoalizedString cannot be called on a worklet thread, // see bug 1808301. So WorkletModuleLoader will override this function to // get the error message. virtual nsresult GetResolveFailureMessage(ResolveError aError, const nsAString& aSpecifier,
nsAString& aResult);
// Start a load for a module script URI. Returns immediately if the module is // already being loaded.
nsresult StartModuleLoad(ModuleLoadRequest* aRequest);
nsresult RestartModuleLoad(ModuleLoadRequest* aRequest);
// Notify the module loader when a fetch started by StartFetch() completes.
nsresult OnFetchComplete(ModuleLoadRequest* aRequest, nsresult aRv);
// Link the module and all its imports. This must occur prior to evaluation. bool InstantiateModuleGraph(ModuleLoadRequest* aRequest);
// Evaluate a module in the given context. Does not push an entry to the // execution stack.
nsresult EvaluateModuleInContext(JSContext* aCx, ModuleLoadRequest* aRequest,
JS::ModuleErrorBehaviour errorBehaviour);
// Override the module loader with given loader until ResetOverride is called. // While overridden, ModuleLoaderBase::GetCurrentModuleLoader returns aLoader. // // This is used by mozJSModuleLoader to temporarily override the global's // module loader with SyncModuleLoader while importing a module graph // synchronously. void SetOverride(ModuleLoaderBase* aLoader);
// Returns true if SetOverride was called. bool IsOverridden();
// Returns true if SetOverride was called with aLoader. bool IsOverriddenBy(ModuleLoaderBase* aLoader);
void ResetOverride();
// Copy fetched modules to `aDest`. // `this` shouldn't have any fetching. // `aDest` shouldn't have any fetching or fetched modules. // // This is used when starting sync module load, to replicate the module cache // in the sync module loader pointed by `aDest`. void CopyModulesTo(ModuleLoaderBase* aDest);
// Move all fetched modules to `aDest`. // Both `this` and `aDest` shouldn't have any fetching. // // This is used when finishing sync module load, to reflect the loaded modules // to the async module loader pointed by `aDest`. void MoveModulesTo(ModuleLoaderBase* aDest);
/** * Shorthand Wrapper for JSAPI FinishDynamicImport function for the reject * case where we do not have `aEvaluationPromise`. As there is no evaluation * Promise, JS::FinishDynamicImport will always reject. * * @param aRequest * The module load request for the dynamic module. * @param aResult * The result of running ModuleEvaluate -- If this is successful, then * we can await the associated EvaluationPromise.
*/ void FinishDynamicImportAndReject(ModuleLoadRequest* aRequest,
nsresult aResult);
/** * Wrapper for JSAPI FinishDynamicImport function. Takes an optional argument * `aEvaluationPromise` which, if null, exits early. * * This is the Top Level Await version, which works with modules which return * promises. * * @param aCX * The JSContext for the module. * @param aRequest * The module load request for the dynamic module. * @param aResult * The result of running ModuleEvaluate -- If this is successful, then * we can await the associated EvaluationPromise. * @param aEvaluationPromise * The evaluation promise returned from evaluating the module. If this * is null, JS::FinishDynamicImport will reject the dynamic import * module promise.
*/ staticvoid FinishDynamicImport(JSContext* aCx, ModuleLoadRequest* aRequest,
nsresult aResult,
JS::Handle<JSObject*> aEvaluationPromise);
// The slot stored in ImportMetaResolve function. enum { ModulePrivateSlot = 0, SlotCount };
// The number of args in ImportMetaResolve. staticconst uint32_t ImportMetaResolveNumArgs = 1; // The index of the 'specifier' argument in ImportMetaResolve. staticconst uint32_t ImportMetaResolveSpecifierArg = 0;
// Override the target module loader with given module loader while this // instance is on the stack. class MOZ_RAII AutoOverrideModuleLoader { public:
AutoOverrideModuleLoader(ModuleLoaderBase* aTarget,
ModuleLoaderBase* aLoader);
~AutoOverrideModuleLoader();
private:
RefPtr<ModuleLoaderBase> mTarget;
};
} // namespace loader
} // namespace JS
#endif// js_loader_ModuleLoaderBase_h
¤ Dauer der Verarbeitung: 0.30 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.