CyclicModule.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /*
  2. * Copyright (c) 2022, David Tuin <davidot@serenityos.org>
  3. * Copyright (c) 2023, networkException <networkexception@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #pragma once
  8. #include <LibJS/Forward.h>
  9. #include <LibJS/Module.h>
  10. namespace JS {
  11. enum class ModuleStatus {
  12. New,
  13. Unlinked,
  14. Linking,
  15. Linked,
  16. Evaluating,
  17. EvaluatingAsync,
  18. Evaluated
  19. };
  20. class CyclicModule;
  21. // https://tc39.es/ecma262/#graphloadingstate-record
  22. struct GraphLoadingState : public Cell {
  23. JS_CELL(GraphLoadingState, Cell);
  24. public:
  25. struct HostDefined : Cell {
  26. JS_CELL(HostDefined, Cell);
  27. public:
  28. virtual ~HostDefined() = default;
  29. };
  30. GCPtr<PromiseCapability> promise_capability; // [[PromiseCapability]]
  31. bool is_loading { false }; // [[IsLoading]]
  32. size_t pending_module_count { 0 }; // [[PendingModulesCount]]
  33. HashTable<CyclicModule*> visited; // [[Visited]]
  34. GCPtr<HostDefined> host_defined; // [[HostDefined]]
  35. private:
  36. GraphLoadingState(GCPtr<PromiseCapability> promise_capability, bool is_loading, size_t pending_module_count, HashTable<CyclicModule*> visited, GCPtr<HostDefined> host_defined)
  37. : promise_capability(move(promise_capability))
  38. , is_loading(is_loading)
  39. , pending_module_count(pending_module_count)
  40. , visited(move(visited))
  41. , host_defined(move(host_defined))
  42. {
  43. }
  44. virtual void visit_edges(Cell::Visitor&) override;
  45. };
  46. // 16.2.1.5 Cyclic Module Records, https://tc39.es/ecma262/#cyclic-module-record
  47. class CyclicModule : public Module {
  48. JS_CELL(CyclicModule, Module);
  49. JS_DECLARE_ALLOCATOR(CyclicModule);
  50. public:
  51. // Note: Do not call these methods directly unless you are HostResolveImportedModule.
  52. // Badges cannot be used because other hosts must be able to call this (and it is called recursively)
  53. virtual ThrowCompletionOr<void> link(VM& vm) override final;
  54. virtual ThrowCompletionOr<Promise*> evaluate(VM& vm) override final;
  55. virtual PromiseCapability& load_requested_modules(Realm&, GCPtr<GraphLoadingState::HostDefined>);
  56. virtual void inner_module_loading(GraphLoadingState& state);
  57. Vector<ModuleRequest> const& requested_modules() const { return m_requested_modules; }
  58. Vector<ModuleWithSpecifier> const& loaded_modules() const { return m_loaded_modules; }
  59. protected:
  60. CyclicModule(Realm& realm, StringView filename, bool has_top_level_await, Vector<ModuleRequest> requested_modules, Script::HostDefined* host_defined);
  61. virtual void visit_edges(Cell::Visitor&) override;
  62. virtual ThrowCompletionOr<u32> inner_module_linking(VM& vm, Vector<Module*>& stack, u32 index) override final;
  63. virtual ThrowCompletionOr<u32> inner_module_evaluation(VM& vm, Vector<Module*>& stack, u32 index) override final;
  64. virtual ThrowCompletionOr<void> initialize_environment(VM& vm);
  65. virtual ThrowCompletionOr<void> execute_module(VM& vm, GCPtr<PromiseCapability> capability = {});
  66. [[nodiscard]] NonnullGCPtr<Module> get_imported_module(ModuleRequest const&);
  67. void execute_async_module(VM& vm);
  68. void gather_available_ancestors(Vector<CyclicModule*>& exec_list);
  69. void async_module_execution_fulfilled(VM& vm);
  70. void async_module_execution_rejected(VM& vm, Value error);
  71. ModuleStatus m_status { ModuleStatus::New }; // [[Status]]
  72. ThrowCompletionOr<void> m_evaluation_error; // [[EvaluationError]]
  73. Optional<u32> m_dfs_index; // [[DFSIndex]]
  74. Optional<u32> m_dfs_ancestor_index; // [[DFSAncestorIndex]]
  75. Vector<ModuleRequest> m_requested_modules; // [[RequestedModules]]
  76. Vector<ModuleWithSpecifier> m_loaded_modules; // [[LoadedModules]]
  77. GCPtr<CyclicModule> m_cycle_root; // [[CycleRoot]]
  78. bool m_has_top_level_await { false }; // [[HasTLA]]
  79. bool m_async_evaluation { false }; // [[AsyncEvaluation]]
  80. GCPtr<PromiseCapability> m_top_level_capability; // [[TopLevelCapability]]
  81. Vector<GCPtr<CyclicModule>> m_async_parent_modules; // [[AsyncParentModules]]
  82. Optional<u32> m_pending_async_dependencies; // [[PendingAsyncDependencies]]
  83. };
  84. void continue_module_loading(Realm&, GraphLoadingState& state, ThrowCompletionOr<Module*> const&);
  85. }