Reference.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <LibJS/Runtime/Environment.h>
  8. #include <LibJS/Runtime/EnvironmentCoordinate.h>
  9. #include <LibJS/Runtime/PropertyKey.h>
  10. #include <LibJS/Runtime/Value.h>
  11. namespace JS {
  12. Reference make_private_reference(VM&, Value base_value, DeprecatedFlyString const& private_identifier);
  13. class Reference {
  14. public:
  15. enum class BaseType : u8 {
  16. Unresolvable,
  17. Value,
  18. Environment,
  19. };
  20. Reference() = default;
  21. Reference(BaseType type, PropertyKey name, bool strict)
  22. : m_base_type(type)
  23. , m_name(move(name))
  24. , m_strict(strict)
  25. {
  26. }
  27. Reference(Value base, PropertyKey name, Value this_value, bool strict = false)
  28. : m_base_type(BaseType::Value)
  29. , m_base_value(base)
  30. , m_name(move(name))
  31. , m_this_value(this_value)
  32. , m_strict(strict)
  33. {
  34. }
  35. Reference(Environment& base, DeprecatedFlyString referenced_name, bool strict = false, Optional<EnvironmentCoordinate> environment_coordinate = {})
  36. : m_base_type(BaseType::Environment)
  37. , m_base_environment(&base)
  38. , m_name(move(referenced_name))
  39. , m_strict(strict)
  40. , m_environment_coordinate(move(environment_coordinate))
  41. {
  42. }
  43. Reference(Value base, PrivateName name)
  44. : m_base_type(BaseType::Value)
  45. , m_base_value(base)
  46. , m_this_value(Value {})
  47. , m_strict(true)
  48. , m_is_private(true)
  49. , m_private_name(move(name))
  50. {
  51. }
  52. Value base() const
  53. {
  54. VERIFY(m_base_type == BaseType::Value);
  55. return m_base_value;
  56. }
  57. Environment& base_environment() const
  58. {
  59. VERIFY(m_base_type == BaseType::Environment);
  60. return *m_base_environment;
  61. }
  62. PropertyKey const& name() const { return m_name; }
  63. bool is_strict() const { return m_strict; }
  64. // 6.2.4.2 IsUnresolvableReference ( V ), https://tc39.es/ecma262/#sec-isunresolvablereference
  65. bool is_unresolvable() const { return m_base_type == BaseType::Unresolvable; }
  66. // 6.2.4.1 IsPropertyReference ( V ), https://tc39.es/ecma262/#sec-ispropertyreference
  67. bool is_property_reference() const
  68. {
  69. if (is_unresolvable())
  70. return false;
  71. if (m_base_type == BaseType::Environment)
  72. return false;
  73. return true;
  74. }
  75. // 6.2.4.7 GetThisValue ( V ), https://tc39.es/ecma262/#sec-getthisvalue
  76. Value get_this_value() const
  77. {
  78. VERIFY(is_property_reference());
  79. if (is_super_reference())
  80. return m_this_value;
  81. return m_base_value;
  82. }
  83. // 6.2.4.3 IsSuperReference ( V ), https://tc39.es/ecma262/#sec-issuperreference
  84. bool is_super_reference() const
  85. {
  86. return !m_this_value.is_empty();
  87. }
  88. // 6.2.4.4 IsPrivateReference ( V ), https://tc39.es/ecma262/#sec-isprivatereference
  89. bool is_private_reference() const
  90. {
  91. return m_is_private;
  92. }
  93. // Note: Non-standard helper.
  94. bool is_environment_reference() const
  95. {
  96. return m_base_type == BaseType::Environment;
  97. }
  98. ThrowCompletionOr<void> initialize_referenced_binding(VM&, Value value, Environment::InitializeBindingHint hint = Environment::InitializeBindingHint::Normal) const;
  99. ThrowCompletionOr<void> put_value(VM&, Value);
  100. ThrowCompletionOr<Value> get_value(VM&) const;
  101. ThrowCompletionOr<bool> delete_(VM&);
  102. bool is_valid_reference() const { return m_name.is_valid() || m_is_private; }
  103. Optional<EnvironmentCoordinate> environment_coordinate() const { return m_environment_coordinate; }
  104. private:
  105. Completion throw_reference_error(VM&) const;
  106. BaseType m_base_type { BaseType::Unresolvable };
  107. union {
  108. Value m_base_value {};
  109. mutable Environment* m_base_environment;
  110. };
  111. PropertyKey m_name;
  112. Value m_this_value;
  113. bool m_strict { false };
  114. bool m_is_private { false };
  115. // FIXME: This can (probably) be an union with m_name.
  116. PrivateName m_private_name;
  117. Optional<EnvironmentCoordinate> m_environment_coordinate;
  118. };
  119. }