Serenity Operating System
1/*
2 * Copyright (c) 2022, David Tuin <davidot@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#pragma once
8
9#include <LibJS/Forward.h>
10#include <LibJS/Module.h>
11
12namespace JS {
13
14enum class ModuleStatus {
15 Unlinked,
16 Linking,
17 Linked,
18 Evaluating,
19 EvaluatingAsync,
20 Evaluated
21};
22
23// 16.2.1.5 Cyclic Module Records, https://tc39.es/ecma262/#sec-cyclic-module-records
24class CyclicModule : public Module {
25 JS_CELL(CyclicModule, Module);
26
27public:
28 // Note: Do not call these methods directly unless you are HostResolveImportedModule.
29 // Badges cannot be used because other hosts must be able to call this (and it is called recursively)
30 virtual ThrowCompletionOr<void> link(VM& vm) override;
31 virtual ThrowCompletionOr<Promise*> evaluate(VM& vm) override;
32
33 Vector<ModuleRequest> const& requested_modules() const { return m_requested_modules; }
34
35protected:
36 CyclicModule(Realm& realm, StringView filename, bool has_top_level_await, Vector<ModuleRequest> requested_modules, Script::HostDefined* host_defined);
37
38 virtual void visit_edges(Cell::Visitor&) override;
39
40 virtual ThrowCompletionOr<u32> inner_module_linking(VM& vm, Vector<Module*>& stack, u32 index) override;
41 virtual ThrowCompletionOr<u32> inner_module_evaluation(VM& vm, Vector<Module*>& stack, u32 index) override;
42
43 virtual ThrowCompletionOr<void> initialize_environment(VM& vm);
44 virtual ThrowCompletionOr<void> execute_module(VM& vm, GCPtr<PromiseCapability> capability = {});
45
46 void execute_async_module(VM& vm);
47 void gather_available_ancestors(Vector<CyclicModule*>& exec_list);
48 void async_module_execution_fulfilled(VM& vm);
49 void async_module_execution_rejected(VM& vm, Value error);
50
51 ModuleStatus m_status { ModuleStatus::Unlinked }; // [[Status]]
52 ThrowCompletionOr<void> m_evaluation_error; // [[EvaluationError]]
53 Optional<u32> m_dfs_index; // [[DFSIndex]]
54 Optional<u32> m_dfs_ancestor_index; // [[DFSAncestorIndex]]
55 Vector<ModuleRequest> m_requested_modules; // [[RequestedModules]]
56 CyclicModule* m_cycle_root { nullptr }; // [[CycleRoot]]
57 bool m_has_top_level_await { false }; // [[HasTLA]]
58 bool m_async_evaluation { false }; // [[AsyncEvaluation]]
59 GCPtr<PromiseCapability> m_top_level_capability; // [[TopLevelCapability]]
60 Vector<CyclicModule*> m_async_parent_modules; // [[AsyncParentModules]]
61 Optional<u32> m_pending_async_dependencies; // [[PendingAsyncDependencies]]
62};
63
64}