/* * Copyright (c) 2021, Andreas Kling * Copyright (c) 2022, David Tuin * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include namespace JS { struct ResolvedBinding { enum Type { BindingName, Namespace, Ambiguous, Null, }; static ResolvedBinding null() { return {}; } static ResolvedBinding ambiguous() { ResolvedBinding binding; binding.type = Ambiguous; return binding; } Type type { Null }; GCPtr module; DeprecatedFlyString export_name; bool is_valid() const { return type == BindingName || type == Namespace; } bool is_namespace() const { return type == Namespace; } bool is_ambiguous() const { return type == Ambiguous; } }; // 16.2.1.4 Abstract Module Records, https://tc39.es/ecma262/#sec-abstract-module-records class Module : public Cell { JS_CELL(Module, Cell); public: virtual ~Module() override; Realm& realm() { return *m_realm; } Realm const& realm() const { return *m_realm; } StringView filename() const { return m_filename; } Environment* environment() { return m_environment; } Script::HostDefined* host_defined() const { return m_host_defined; } ThrowCompletionOr get_module_namespace(VM& vm); virtual ThrowCompletionOr link(VM& vm) = 0; virtual ThrowCompletionOr evaluate(VM& vm) = 0; virtual ThrowCompletionOr> get_exported_names(VM& vm, Vector export_star_set = {}) = 0; virtual ThrowCompletionOr resolve_export(VM& vm, DeprecatedFlyString const& export_name, Vector resolve_set = {}) = 0; virtual ThrowCompletionOr inner_module_linking(VM& vm, Vector& stack, u32 index); virtual ThrowCompletionOr inner_module_evaluation(VM& vm, Vector& stack, u32 index); protected: Module(Realm&, DeprecatedString filename, Script::HostDefined* host_defined = nullptr); virtual void visit_edges(Cell::Visitor&) override; void set_environment(Environment* environment) { m_environment = environment; } private: Object* module_namespace_create(VM& vm, Vector unambiguous_names); // These handles are only safe as long as the VM they live in is valid. // But evaluated modules SHOULD be stored in the VM so unless you intentionally // destroy the VM but keep the modules this should not happen. Because VM // stores modules with a RefPtr we cannot just store the VM as that leads to // cycles. GCPtr m_realm; // [[Realm]] GCPtr m_environment; // [[Environment]] GCPtr m_namespace; // [[Namespace]] Script::HostDefined* m_host_defined { nullptr }; // [[HostDefined]] // Needed for potential lookups of modules. DeprecatedString m_filename; }; }