/* * Copyright (c) 2022, David Tuin * Copyright (c) 2023, networkException * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include namespace JS { enum class ModuleStatus { New, Unlinked, Linking, Linked, Evaluating, EvaluatingAsync, Evaluated }; // 16.2.1.5 Cyclic Module Records, https://tc39.es/ecma262/#cyclic-module-record class CyclicModule : public Module { GC_CELL(CyclicModule, Module); GC_DECLARE_ALLOCATOR(CyclicModule); public: virtual ~CyclicModule() override; // Note: Do not call these methods directly unless you are HostResolveImportedModule. // Badges cannot be used because other hosts must be able to call this (and it is called recursively) virtual ThrowCompletionOr link(VM& vm) override final; virtual ThrowCompletionOr evaluate(VM& vm) override final; virtual PromiseCapability& load_requested_modules(GC::Ptr) override; virtual void inner_module_loading(GraphLoadingState& state); Vector const& requested_modules() const { return m_requested_modules; } Vector const& loaded_modules() const { return m_loaded_modules; } Vector& loaded_modules() { return m_loaded_modules; } protected: CyclicModule(Realm& realm, StringView filename, bool has_top_level_await, Vector requested_modules, Script::HostDefined* host_defined); virtual void visit_edges(Cell::Visitor&) override; virtual ThrowCompletionOr inner_module_linking(VM& vm, Vector& stack, u32 index) override final; virtual ThrowCompletionOr inner_module_evaluation(VM& vm, Vector& stack, u32 index) override final; virtual ThrowCompletionOr initialize_environment(VM& vm); virtual ThrowCompletionOr execute_module(VM& vm, GC::Ptr capability = {}); [[nodiscard]] GC::Ref get_imported_module(ModuleRequest const&); void execute_async_module(VM& vm); void gather_available_ancestors(Vector& exec_list); void async_module_execution_fulfilled(VM& vm); void async_module_execution_rejected(VM& vm, Value error); ModuleStatus m_status { ModuleStatus::New }; // [[Status]] ThrowCompletionOr m_evaluation_error; // [[EvaluationError]] Optional m_dfs_index; // [[DFSIndex]] Optional m_dfs_ancestor_index; // [[DFSAncestorIndex]] Vector m_requested_modules; // [[RequestedModules]] Vector m_loaded_modules; // [[LoadedModules]] GC::Ptr m_cycle_root; // [[CycleRoot]] bool m_has_top_level_await { false }; // [[HasTLA]] bool m_async_evaluation { false }; // [[AsyncEvaluation]] GC::Ptr m_top_level_capability; // [[TopLevelCapability]] Vector> m_async_parent_modules; // [[AsyncParentModules]] Optional m_pending_async_dependencies; // [[PendingAsyncDependencies]] }; void continue_module_loading(GraphLoadingState&, ThrowCompletionOr> const&); void continue_dynamic_import(GC::Ref, ThrowCompletionOr> const& module_completion); }