/* -*- 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/. */ /* JavaScript module (as in, the syntactic construct) operations. */ #ifndef js_Modules_h #define js_Modules_h #include // uint32_t #include "jstypes.h" // JS_PUBLIC_API #include "js/AllocPolicy.h" // js::SystemAllocPolicy #include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin #include "js/CompileOptions.h" // JS::ReadOnlyCompileOptions #include "js/RootingAPI.h" // JS::{Mutable,}Handle #include "js/Value.h" // JS::Value #include "js/Vector.h" // js::Vector struct JS_PUBLIC_API JSContext; class JS_PUBLIC_API JSObject; struct JS_PUBLIC_API JSRuntime; class JS_PUBLIC_API JSString; namespace JS { template class SourceText; } // namespace JS namespace mozilla { union Utf8Unit; } namespace JS { // This enum is used to index into an array, and we assume that we have // sequential numbers starting at zero for the unknown type. enum class ModuleType : uint32_t { Unknown = 0, JavaScript, JSON, CSS, Limit = CSS, }; /** * The HostLoadImportedModule hook. * * See: https://tc39.es/ecma262/#sec-HostLoadImportedModule * * This embedding-defined hook is used to implement module loading. It is called * to get or create a module object corresponding to |moduleRequest| occurring * in the context of the script or module |referrer| with private value * |referencingPrivate|. * * The module specifier string for the request can be obtained by calling * JS::GetModuleRequestSpecifier. * * The private value for a script or module is set with JS::SetScriptPrivate or * JS::SetModulePrivate. It's assumed that the embedding can handle receiving * either here. * * If this call succeeds then the embedding must call * FinishLoadingImportedModule or one of the FinishLoadingImportedModuleFailed * APIs at some point in the future. This is handled by the engine if the call * returns false. * * This hook must obey the restrictions defined in the spec: * - Each time the hook is called with the same (referrer, referencingPrivate) * pair, then it must call FinishLoadingImportedModule with the same result * each time. * - The operation must treat the |payload| argument as an opaque * value to be passed through to FinishLoadingImportedModule. */ using ModuleLoadHook = bool (*)(JSContext* cx, Handle referrer, Handle moduleRequest, Handle hostDefined, Handle payload, uint32_t lineNumber, JS::ColumnNumberOneOrigin columnNumber); /** * Get the HostLoadImportedModule hook for the runtime. */ extern JS_PUBLIC_API ModuleLoadHook GetModuleLoadHook(JSRuntime* rt); /** * Set the HostLoadImportedModule hook for the runtime to the given function. */ extern JS_PUBLIC_API void SetModuleLoadHook(JSRuntime* rt, ModuleLoadHook func); using LoadModuleResolvedCallback = bool (*)(JSContext* cx, JS::Handle); using LoadModuleRejectedCallback = bool (*)(JSContext* cx, JS::Handle hostDefined, Handle error); /** * https://tc39.es/ecma262/#sec-LoadRequestedModules * * Load the dependency module graph of the parameter 'module'. * * The spec defines using 'promise objects' to notify the result. * To address the synchronous loading behavior from mozJSModuleLoader, an * overloaded version that takes function callbacks to notify the result is also * provided. */ extern JS_PUBLIC_API bool LoadRequestedModules( JSContext* cx, Handle module, Handle hostDefined, LoadModuleResolvedCallback resolved, LoadModuleRejectedCallback rejected); extern JS_PUBLIC_API bool LoadRequestedModules( JSContext* cx, Handle module, Handle hostDefined, MutableHandle promiseOut); /** * The module metadata hook. * * See: https://tc39.es/ecma262/#sec-hostgetimportmetaproperties * * Populate the |metaObject| object returned when import.meta is evaluated in * the context of the script or module with private value |privateValue|. * * This is based on the spec's HostGetImportMetaProperties hook but defines * properties on the meta object directly rather than returning a list. */ using ModuleMetadataHook = bool (*)(JSContext* cx, Handle privateValue, Handle metaObject); /** * Get the hook for populating the import.meta metadata object. */ extern JS_PUBLIC_API ModuleMetadataHook GetModuleMetadataHook(JSRuntime* rt); /** * Set the hook for populating the import.meta metadata object to the given * function. */ extern JS_PUBLIC_API void SetModuleMetadataHook(JSRuntime* rt, ModuleMetadataHook func); /** * A function callback called by the host layer to indicate the call of * HostLoadImportedModule has finished. * * See https://tc39.es/ecma262/#sec-FinishLoadingImportedModule */ extern JS_PUBLIC_API bool FinishLoadingImportedModule( JSContext* cx, Handle referrer, Handle moduleRequest, Handle payload, Handle result, bool usePromise); /** * Overloaded version of FinishLoadingImportedModule for error handling. */ extern JS_PUBLIC_API bool FinishLoadingImportedModuleFailed( JSContext* cx, Handle payload, Handle error); extern JS_PUBLIC_API bool FinishLoadingImportedModuleFailedWithPendingException( JSContext* cx, Handle payload); /** * Parse the given source buffer as a module in the scope of the current global * of cx and return a source text module record. */ extern JS_PUBLIC_API JSObject* CompileModule( JSContext* cx, const ReadOnlyCompileOptions& options, SourceText& srcBuf); /** * Parse the given source buffer as a module in the scope of the current global * of cx and return a source text module record. An error is reported if a * UTF-8 encoding error is encountered. */ extern JS_PUBLIC_API JSObject* CompileModule( JSContext* cx, const ReadOnlyCompileOptions& options, SourceText& srcBuf); /** * Parse the given source buffer as a JSON module in the scope of the current * global of cx and return a synthetic module record. */ extern JS_PUBLIC_API JSObject* CompileJsonModule( JSContext* cx, const ReadOnlyCompileOptions& options, SourceText& srcBuf); /** * Parse the given source buffer as a JSON module in the scope of the current * global of cx and return a synthetic module record. An error is reported if a * UTF-8 encoding error is encountered. */ extern JS_PUBLIC_API JSObject* CompileJsonModule( JSContext* cx, const ReadOnlyCompileOptions& options, SourceText& srcBuf); /** * Create a synthetic module record for a CSS module from the provided * CSSStyleSheet in cssValue. There's no capability to parse CSS in * the engine, so this must occur prior to calling this function. */ extern JS_PUBLIC_API JSObject* CreateCssModule( JSContext* cx, const ReadOnlyCompileOptions& options, const Value& cssValue); /** * Set a private value associated with a source text module record. */ extern JS_PUBLIC_API void SetModulePrivate(JSObject* module, const Value& value); /** * Clear the private value associated with a source text module record. * * This is used during unlinking and can be called on a gray module, skipping * the usual checks. */ extern JS_PUBLIC_API void ClearModulePrivate(JSObject* module); /** * Get the private value associated with a source text module record. */ extern JS_PUBLIC_API Value GetModulePrivate(JSObject* module); /** * Checks if the given module is a cyclic module. */ extern JS_PUBLIC_API bool IsCyclicModule(JSObject* module); /* * Perform the ModuleLink operation on the given source text module record. * * This transitively resolves all module dependencies (calling the * HostResolveImportedModule hook) and initializes the environment record for * the module. */ extern JS_PUBLIC_API bool ModuleLink(JSContext* cx, Handle moduleRecord); /* * Perform the ModuleEvaluate operation on the given source text module record * and returns a bool. A result value is returned in result and is either * undefined (and ignored) or a promise (if Top Level Await is enabled). * * If this module has already been evaluated, it returns the evaluation * promise. Otherwise, it transitively evaluates all dependences of this module * and then evaluates this module. * * ModuleLink must have completed prior to calling this. */ extern JS_PUBLIC_API bool ModuleEvaluate(JSContext* cx, Handle moduleRecord, MutableHandleValue rval); enum ModuleErrorBehaviour { // Report module evaluation errors asynchronously when the evaluation promise // is rejected. This is used for web content. ReportModuleErrorsAsync, // Throw module evaluation errors synchronously by setting an exception on the // context. Does not support modules that use top-level await. ThrowModuleErrorsSync }; /* * If a module evaluation fails, unwrap the resulting evaluation promise * and rethrow. * * This does nothing if this module succeeds in evaluation. Otherwise, it * takes the reason for the module throwing, unwraps it and throws it as a * regular error rather than as an uncaught promise. * * ModuleEvaluate must have completed prior to calling this. */ extern JS_PUBLIC_API bool ThrowOnModuleEvaluationFailure( JSContext* cx, Handle evaluationPromise, ModuleErrorBehaviour errorBehaviour = ReportModuleErrorsAsync); /* * Get the module type of a requested module. */ extern JS_PUBLIC_API ModuleType GetRequestedModuleType( JSContext* cx, Handle moduleRecord, uint32_t index); /* * Get the top-level script for a module which has not yet been executed. */ extern JS_PUBLIC_API JSScript* GetModuleScript(Handle moduleRecord); extern JS_PUBLIC_API JSObject* CreateModuleRequest( JSContext* cx, Handle specifierArg, ModuleType moduleType); extern JS_PUBLIC_API JSString* GetModuleRequestSpecifier( JSContext* cx, Handle moduleRequestArg); /* * Get the module type of the specified module request. */ extern JS_PUBLIC_API ModuleType GetModuleRequestType(JSContext* cx, Handle moduleRequestArg); /* * Get the module record for a module script. */ extern JS_PUBLIC_API JSObject* GetModuleObject(Handle moduleScript); /* * Get the namespace object for a module. */ extern JS_PUBLIC_API JSObject* GetModuleNamespace( JSContext* cx, Handle moduleRecord); extern JS_PUBLIC_API JSObject* GetModuleForNamespace( JSContext* cx, Handle moduleNamespace); extern JS_PUBLIC_API JSObject* GetModuleEnvironment( JSContext* cx, Handle moduleObj); /* * Clear all bindings in a module's environment. Used during shutdown. */ extern JS_PUBLIC_API void ClearModuleEnvironment(JSObject* moduleObj); extern JS_PUBLIC_API bool ModuleIsLinked(JSObject* moduleObj); } // namespace JS #endif // js_Modules_h