| 
									
										
										
										
											2020-04-15 21:58:22 +02:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2024-10-04 13:19:50 +02:00
										 |  |  |  * Copyright (c) 2020-2021, Andreas Kling <andreas@ladybird.org> | 
					
						
							| 
									
										
										
										
											2020-04-15 21:58:22 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2020-04-15 21:58:22 +02:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-18 18:08:02 -05:00
										 |  |  | #include <AK/FlyString.h>
 | 
					
						
							| 
									
										
										
										
											2020-04-15 21:58:22 +02:00
										 |  |  | #include <AK/HashMap.h>
 | 
					
						
							| 
									
										
										
										
											2022-12-20 22:09:57 +01:00
										 |  |  | #include <LibJS/Runtime/AbstractOperations.h>
 | 
					
						
							| 
									
										
										
										
											2021-10-09 17:07:32 +01:00
										 |  |  | #include <LibJS/Runtime/Completion.h>
 | 
					
						
							| 
									
										
										
										
											2021-07-01 12:24:46 +02:00
										 |  |  | #include <LibJS/Runtime/Environment.h>
 | 
					
						
							| 
									
										
										
										
											2020-04-15 21:58:22 +02:00
										 |  |  | #include <LibJS/Runtime/Value.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace JS { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-01 12:24:46 +02:00
										 |  |  | class DeclarativeEnvironment : public Environment { | 
					
						
							|  |  |  |     JS_ENVIRONMENT(DeclarativeEnvironment, Environment); | 
					
						
							| 
									
										
										
										
											2024-11-15 04:01:23 +13:00
										 |  |  |     GC_DECLARE_ALLOCATOR(DeclarativeEnvironment); | 
					
						
							| 
									
										
										
										
											2020-04-15 21:58:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 15:37:10 -05:00
										 |  |  |     struct Binding { | 
					
						
							| 
									
										
										
										
											2025-03-18 18:08:02 -05:00
										 |  |  |         FlyString name; | 
					
						
							| 
									
										
										
										
											2022-03-09 15:37:10 -05:00
										 |  |  |         Value value; | 
					
						
							|  |  |  |         bool strict { false }; | 
					
						
							|  |  |  |         bool mutable_ { false }; | 
					
						
							|  |  |  |         bool can_be_deleted { false }; | 
					
						
							|  |  |  |         bool initialized { false }; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 21:58:22 +02:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2022-03-09 15:37:10 -05:00
										 |  |  |     static DeclarativeEnvironment* create_for_per_iteration_bindings(Badge<ForStatement>, DeclarativeEnvironment& other, size_t bindings_size); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-14 10:25:06 -06:00
										 |  |  |     virtual ~DeclarativeEnvironment() override = default; | 
					
						
							| 
									
										
										
										
											2020-04-15 21:58:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-18 18:08:02 -05:00
										 |  |  |     virtual ThrowCompletionOr<bool> has_binding(FlyString const& name, Optional<size_t>* = nullptr) const override final; | 
					
						
							|  |  |  |     virtual ThrowCompletionOr<void> create_mutable_binding(VM&, FlyString const& name, bool can_be_deleted) override final; | 
					
						
							|  |  |  |     virtual ThrowCompletionOr<void> create_immutable_binding(VM&, FlyString const& name, bool strict) override final; | 
					
						
							|  |  |  |     virtual ThrowCompletionOr<void> initialize_binding(VM&, FlyString const& name, Value, InitializeBindingHint) override final; | 
					
						
							|  |  |  |     virtual ThrowCompletionOr<void> set_mutable_binding(VM&, FlyString const& name, Value, bool strict) override final; | 
					
						
							|  |  |  |     virtual ThrowCompletionOr<Value> get_binding_value(VM&, FlyString const& name, bool strict) override; | 
					
						
							|  |  |  |     virtual ThrowCompletionOr<bool> delete_binding(VM&, FlyString const& name) override; | 
					
						
							| 
									
										
										
										
											2021-06-23 12:26:37 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-18 18:08:02 -05:00
										 |  |  |     void initialize_or_set_mutable_binding(Badge<ScopeNode>, VM&, FlyString const& name, Value value); | 
					
						
							|  |  |  |     ThrowCompletionOr<void> initialize_or_set_mutable_binding(VM&, FlyString const& name, Value value); | 
					
						
							| 
									
										
										
										
											2021-09-22 12:44:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-03 13:20:15 +02:00
										 |  |  |     // This is not a method defined in the spec! Do not use this in any LibJS (or other spec related) code.
 | 
					
						
							| 
									
										
										
										
											2025-03-18 18:08:02 -05:00
										 |  |  |     [[nodiscard]] Vector<FlyString> bindings() const | 
					
						
							| 
									
										
										
										
											2022-03-08 11:56:42 -05:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2025-03-18 18:08:02 -05:00
										 |  |  |         Vector<FlyString> names; | 
					
						
							| 
									
										
										
										
											2022-03-08 11:56:42 -05:00
										 |  |  |         names.ensure_capacity(m_bindings.size()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (auto const& binding : m_bindings) | 
					
						
							|  |  |  |             names.unchecked_append(binding.name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return names; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-03 13:20:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-13 22:03:52 +02:00
										 |  |  |     ThrowCompletionOr<void> initialize_binding_direct(VM&, size_t index, Value, InitializeBindingHint); | 
					
						
							| 
									
										
										
										
											2022-08-21 15:12:43 +01:00
										 |  |  |     ThrowCompletionOr<void> set_mutable_binding_direct(VM&, size_t index, Value, bool strict); | 
					
						
							| 
									
										
										
										
											2024-05-11 17:22:59 +02:00
										 |  |  |     ThrowCompletionOr<Value> get_binding_value_direct(VM&, size_t index) const; | 
					
						
							| 
									
										
										
										
											2025-05-04 01:41:49 +02:00
										 |  |  |     Value get_initialized_binding_value_direct(size_t index) const { return m_bindings[index].value; } | 
					
						
							| 
									
										
										
										
											2022-09-01 23:22:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-26 20:33:52 +01:00
										 |  |  |     void shrink_to_fit(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-20 01:32:07 +02:00
										 |  |  |     void ensure_capacity(size_t needed_capacity) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_bindings.ensure_capacity(needed_capacity); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-12 14:30:51 +02:00
										 |  |  |     [[nodiscard]] u64 environment_serial_number() const { return m_environment_serial_number; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-16 16:51:26 -05:00
										 |  |  |     DisposeCapability const& dispose_capability() const { return m_dispose_capability; } | 
					
						
							|  |  |  |     DisposeCapability& dispose_capability() { return m_dispose_capability; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-01 23:22:17 +02:00
										 |  |  | private: | 
					
						
							| 
									
										
										
										
											2024-05-11 17:22:59 +02:00
										 |  |  |     ThrowCompletionOr<Value> get_binding_value_direct(VM&, Binding const&) const; | 
					
						
							| 
									
										
										
										
											2022-09-01 23:22:17 +02:00
										 |  |  |     ThrowCompletionOr<void> set_mutable_binding_direct(VM&, Binding&, Value, bool strict); | 
					
						
							| 
									
										
										
										
											2021-10-07 00:10:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-22 13:30:48 +02:00
										 |  |  | protected: | 
					
						
							| 
									
										
										
										
											2022-08-28 23:51:28 +02:00
										 |  |  |     DeclarativeEnvironment(); | 
					
						
							|  |  |  |     explicit DeclarativeEnvironment(Environment* parent_environment); | 
					
						
							| 
									
										
										
										
											2023-02-05 19:02:54 +00:00
										 |  |  |     DeclarativeEnvironment(Environment* parent_environment, ReadonlySpan<Binding> bindings); | 
					
						
							| 
									
										
										
										
											2022-08-28 23:51:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-22 13:30:48 +02:00
										 |  |  |     virtual void visit_edges(Visitor&) override; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-01 23:22:17 +02:00
										 |  |  |     class BindingAndIndex { | 
					
						
							|  |  |  |     public: | 
					
						
							|  |  |  |         Binding& binding() | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if (m_referenced_binding) | 
					
						
							|  |  |  |                 return *m_referenced_binding; | 
					
						
							|  |  |  |             return m_temporary_binding; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         BindingAndIndex(Binding* binding, Optional<size_t> index) | 
					
						
							|  |  |  |             : m_referenced_binding(binding) | 
					
						
							|  |  |  |             , m_index(move(index)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         explicit BindingAndIndex(Binding temporary_binding) | 
					
						
							|  |  |  |             : m_temporary_binding(move(temporary_binding)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Optional<size_t> const& index() const { return m_index; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private: | 
					
						
							|  |  |  |         Binding* m_referenced_binding { nullptr }; | 
					
						
							|  |  |  |         Binding m_temporary_binding {}; | 
					
						
							|  |  |  |         Optional<size_t> m_index; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     friend class ModuleEnvironment; | 
					
						
							| 
									
										
										
										
											2020-04-15 21:58:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-18 18:08:02 -05:00
										 |  |  |     virtual Optional<BindingAndIndex> find_binding_and_index(FlyString const& name) const | 
					
						
							| 
									
										
										
										
											2022-03-08 11:56:42 -05:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-10-24 10:32:04 +02:00
										 |  |  |         if (auto it = m_bindings_assoc.find(name); it != m_bindings_assoc.end()) { | 
					
						
							|  |  |  |             return BindingAndIndex { const_cast<Binding*>(&m_bindings.at(it->value)), it->value }; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-01 23:22:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-24 10:32:04 +02:00
										 |  |  |         return {}; | 
					
						
							| 
									
										
										
										
											2022-03-08 11:56:42 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-01 23:22:17 +02:00
										 |  |  | private: | 
					
						
							| 
									
										
										
										
											2021-10-06 23:38:46 +02:00
										 |  |  |     Vector<Binding> m_bindings; | 
					
						
							| 
									
										
										
										
											2025-03-18 18:08:02 -05:00
										 |  |  |     HashMap<FlyString, size_t> m_bindings_assoc; | 
					
						
							| 
									
										
										
										
											2025-01-16 16:51:26 -05:00
										 |  |  |     DisposeCapability m_dispose_capability; | 
					
						
							| 
									
										
										
										
											2023-07-12 14:30:51 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     u64 m_environment_serial_number { 0 }; | 
					
						
							| 
									
										
										
										
											2020-04-15 21:58:22 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-11 17:22:59 +02:00
										 |  |  | inline ThrowCompletionOr<Value> DeclarativeEnvironment::get_binding_value_direct(VM& vm, size_t index) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return get_binding_value_direct(vm, m_bindings[index]); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | inline ThrowCompletionOr<Value> DeclarativeEnvironment::get_binding_value_direct(VM&, Binding const& binding) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // 2. If the binding for N in envRec is an uninitialized binding, throw a ReferenceError exception.
 | 
					
						
							|  |  |  |     if (!binding.initialized) | 
					
						
							|  |  |  |         return vm().throw_completion<ReferenceError>(ErrorType::BindingNotInitialized, binding.name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // 3. Return the value currently bound to N in envRec.
 | 
					
						
							|  |  |  |     return binding.value; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-13 11:23:23 +02:00
										 |  |  | template<> | 
					
						
							| 
									
										
										
										
											2021-07-01 12:24:46 +02:00
										 |  |  | inline bool Environment::fast_is<DeclarativeEnvironment>() const { return is_declarative_environment(); } | 
					
						
							| 
									
										
										
										
											2021-06-13 11:23:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-15 21:58:22 +02:00
										 |  |  | } |