/* * Copyright (c) 2020-2021, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include namespace JS { class DeclarativeEnvironment : public Environment { JS_ENVIRONMENT(DeclarativeEnvironment, Environment); struct Binding { FlyString name; Value value; bool strict { false }; bool mutable_ { false }; bool can_be_deleted { false }; bool initialized { false }; }; public: static DeclarativeEnvironment* create_for_per_iteration_bindings(Badge, DeclarativeEnvironment& other, size_t bindings_size); DeclarativeEnvironment(); explicit DeclarativeEnvironment(Environment* parent_environment); explicit DeclarativeEnvironment(Environment* parent_environment, Span bindings); virtual ~DeclarativeEnvironment() override = default; virtual ThrowCompletionOr has_binding(FlyString const& name, Optional* = nullptr) const override; virtual ThrowCompletionOr create_mutable_binding(GlobalObject&, FlyString const& name, bool can_be_deleted) override; virtual ThrowCompletionOr create_immutable_binding(GlobalObject&, FlyString const& name, bool strict) override; virtual ThrowCompletionOr initialize_binding(GlobalObject&, FlyString const& name, Value) override; virtual ThrowCompletionOr set_mutable_binding(GlobalObject&, FlyString const& name, Value, bool strict) override; virtual ThrowCompletionOr get_binding_value(GlobalObject&, FlyString const& name, bool strict) override; virtual ThrowCompletionOr delete_binding(GlobalObject&, FlyString const& name) override; void initialize_or_set_mutable_binding(Badge, GlobalObject& global_object, FlyString const& name, Value value); ThrowCompletionOr initialize_or_set_mutable_binding(GlobalObject& global_object, FlyString const& name, Value value); // This is not a method defined in the spec! Do not use this in any LibJS (or other spec related) code. [[nodiscard]] Vector bindings() const { Vector names; names.ensure_capacity(m_bindings.size()); for (auto const& binding : m_bindings) names.unchecked_append(binding.name); return names; } ThrowCompletionOr initialize_binding_direct(GlobalObject&, size_t index, Value); ThrowCompletionOr get_binding_value_direct(GlobalObject&, size_t index, bool strict); ThrowCompletionOr set_mutable_binding_direct(GlobalObject&, size_t index, Value, bool strict); protected: virtual void visit_edges(Visitor&) override; private: virtual bool is_declarative_environment() const override { return true; } Optional find_binding_index(FlyString const& name) const { auto it = m_bindings.find_if([&](auto const& binding) { return binding.name == name; }); if (it == m_bindings.end()) return {}; return it.index(); } Vector m_bindings; }; template<> inline bool Environment::fast_is() const { return is_declarative_environment(); } }