123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- /*
- * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #pragma once
- #include <AK/String.h>
- #include <LibJS/Runtime/Environment.h>
- #include <LibJS/Runtime/EnvironmentCoordinate.h>
- #include <LibJS/Runtime/ExecutionContext.h>
- #include <LibJS/Runtime/PropertyName.h>
- #include <LibJS/Runtime/Value.h>
- namespace JS {
- Reference make_private_reference(VM&, Value base_value, FlyString const& private_identifier);
- class Reference {
- public:
- enum class BaseType : u8 {
- Unresolvable,
- Value,
- Environment,
- };
- Reference() { }
- Reference(BaseType type, PropertyName name, bool strict)
- : m_base_type(type)
- , m_name(move(name))
- , m_strict(strict)
- {
- }
- Reference(Value base, PropertyName name, Value this_value, bool strict = false)
- : m_base_type(BaseType::Value)
- , m_base_value(base)
- , m_name(move(name))
- , m_this_value(this_value)
- , m_strict(strict)
- {
- if (base.is_nullish()) {
- m_base_type = BaseType::Unresolvable;
- m_base_value = {};
- m_this_value = {};
- m_name = {};
- }
- }
- Reference(Environment& base, FlyString referenced_name, bool strict = false, Optional<EnvironmentCoordinate> environment_coordinate = {})
- : m_base_type(BaseType::Environment)
- , m_base_environment(&base)
- , m_name(move(referenced_name))
- , m_strict(strict)
- , m_environment_coordinate(move(environment_coordinate))
- {
- }
- Reference(Value base, PrivateName name)
- : m_base_type(BaseType::Value)
- , m_base_value(base)
- , m_this_value(Value {})
- , m_strict(true)
- , m_is_private(true)
- , m_private_name(move(name))
- {
- }
- Value base() const
- {
- VERIFY(m_base_type == BaseType::Value);
- return m_base_value;
- }
- Environment& base_environment() const
- {
- VERIFY(m_base_type == BaseType::Environment);
- return *m_base_environment;
- }
- PropertyName const& name() const { return m_name; }
- bool is_strict() const { return m_strict; }
- // 6.2.4.2 IsUnresolvableReference ( V ), https://tc39.es/ecma262/#sec-isunresolvablereference
- bool is_unresolvable() const { return m_base_type == BaseType::Unresolvable; }
- // 6.2.4.1 IsPropertyReference ( V ), https://tc39.es/ecma262/#sec-ispropertyreference
- bool is_property_reference() const
- {
- if (is_unresolvable())
- return false;
- if (m_base_type == BaseType::Environment)
- return false;
- return true;
- }
- // 6.2.4.7 GetThisValue ( V ), https://tc39.es/ecma262/#sec-getthisvalue
- Value get_this_value() const
- {
- VERIFY(is_property_reference());
- if (is_super_reference())
- return m_this_value;
- return m_base_value;
- }
- // 6.2.4.3 IsSuperReference ( V ), https://tc39.es/ecma262/#sec-issuperreference
- bool is_super_reference() const
- {
- return !m_this_value.is_empty();
- }
- // 6.2.4.4 IsPrivateReference ( V ), https://tc39.es/ecma262/#sec-isprivatereference
- bool is_private_reference() const
- {
- return m_is_private;
- }
- // Note: Non-standard helper.
- bool is_environment_reference() const
- {
- return m_base_type == BaseType::Environment;
- }
- void initialize_referenced_binding(GlobalObject& global_object, Value value) const
- {
- VERIFY(!is_unresolvable());
- VERIFY(m_base_type == BaseType::Environment);
- (void)m_base_environment->initialize_binding(global_object, m_name.as_string(), value);
- }
- void put_value(GlobalObject&, Value);
- Value get_value(GlobalObject&) const;
- bool delete_(GlobalObject&);
- String to_string() const;
- bool is_valid_reference() const { return m_name.is_valid() || m_is_private; }
- Optional<EnvironmentCoordinate> environment_coordinate() const { return m_environment_coordinate; }
- private:
- void throw_reference_error(GlobalObject&) const;
- BaseType m_base_type { BaseType::Unresolvable };
- union {
- Value m_base_value {};
- mutable Environment* m_base_environment;
- };
- PropertyName m_name;
- Value m_this_value;
- bool m_strict { false };
- bool m_is_private { false };
- // FIXME: This can (probably) be an union with m_name.
- PrivateName m_private_name { 0, "" };
- Optional<EnvironmentCoordinate> m_environment_coordinate;
- };
- }
|