/* * Copyright (c) 2020-2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include namespace JS { struct Variable { Value value; DeclarationKind declaration_kind; }; #define JS_ENVIRONMENT(class_, base_class) JS_CELL(class_, base_class) class Environment : public Cell { JS_CELL(Environment, Cell); public: virtual bool has_this_binding() const { return false; } virtual ThrowCompletionOr get_this_binding(VM&) const { return Value {}; } virtual Object* with_base_object() const { return nullptr; } virtual ThrowCompletionOr has_binding([[maybe_unused]] FlyString const& name, [[maybe_unused]] Optional* out_index = nullptr) const { return false; } virtual ThrowCompletionOr create_mutable_binding(VM&, [[maybe_unused]] FlyString const& name, [[maybe_unused]] bool can_be_deleted) { return {}; } virtual ThrowCompletionOr create_immutable_binding(VM&, [[maybe_unused]] FlyString const& name, [[maybe_unused]] bool strict) { return {}; } virtual ThrowCompletionOr initialize_binding(VM&, [[maybe_unused]] FlyString const& name, Value) { return {}; } virtual ThrowCompletionOr set_mutable_binding(VM&, [[maybe_unused]] FlyString const& name, Value, [[maybe_unused]] bool strict) { return {}; } virtual ThrowCompletionOr get_binding_value(VM&, [[maybe_unused]] FlyString const& name, [[maybe_unused]] bool strict) { return Value {}; } virtual ThrowCompletionOr delete_binding(VM&, [[maybe_unused]] FlyString const& name) { return false; } // [[OuterEnv]] Environment* outer_environment() { return m_outer_environment; } Environment const* outer_environment() const { return m_outer_environment; } virtual bool is_global_environment() const { return false; } virtual bool is_declarative_environment() const { return false; } virtual bool is_function_environment() const { return false; } template bool fast_is() const = delete; // This flag is set on the entire variable environment chain when direct eval() is performed. // It is used to disable non-local variable access caching. bool is_permanently_screwed_by_eval() const { return m_permanently_screwed_by_eval; } void set_permanently_screwed_by_eval(); protected: explicit Environment(Environment* parent); virtual void visit_edges(Visitor&) override; private: virtual bool is_environment() const final { return true; } bool m_permanently_screwed_by_eval { false }; Environment* m_outer_environment { nullptr }; }; }