Reference.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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 <AK/String.h>
  8. #include <LibJS/Runtime/Environment.h>
  9. #include <LibJS/Runtime/EnvironmentCoordinate.h>
  10. #include <LibJS/Runtime/ExecutionContext.h>
  11. #include <LibJS/Runtime/PropertyName.h>
  12. #include <LibJS/Runtime/Value.h>
  13. namespace JS {
  14. class Reference {
  15. public:
  16. enum class BaseType : u8 {
  17. Unresolvable,
  18. Value,
  19. Environment,
  20. };
  21. Reference() { }
  22. Reference(BaseType type, PropertyName name, bool strict)
  23. : m_base_type(type)
  24. , m_name(move(name))
  25. , m_strict(strict)
  26. {
  27. }
  28. Reference(Value base, PropertyName name, Value this_value, bool strict = false)
  29. : m_base_type(BaseType::Value)
  30. , m_base_value(base)
  31. , m_name(move(name))
  32. , m_this_value(this_value)
  33. , m_strict(strict)
  34. {
  35. if (base.is_nullish()) {
  36. m_base_type = BaseType::Unresolvable;
  37. m_base_value = {};
  38. m_this_value = {};
  39. m_name = {};
  40. }
  41. }
  42. Reference(Environment& base, FlyString referenced_name, bool strict = false, Optional<EnvironmentCoordinate> environment_coordinate = {})
  43. : m_base_type(BaseType::Environment)
  44. , m_base_environment(&base)
  45. , m_name(move(referenced_name))
  46. , m_strict(strict)
  47. , m_environment_coordinate(move(environment_coordinate))
  48. {
  49. }
  50. Value base() const
  51. {
  52. VERIFY(m_base_type == BaseType::Value);
  53. return m_base_value;
  54. }
  55. Environment& base_environment() const
  56. {
  57. VERIFY(m_base_type == BaseType::Environment);
  58. return *m_base_environment;
  59. }
  60. PropertyName const& name() const { return m_name; }
  61. bool is_strict() const { return m_strict; }
  62. // 6.2.4.2 IsUnresolvableReference ( V ), https://tc39.es/ecma262/#sec-isunresolvablereference
  63. bool is_unresolvable() const { return m_base_type == BaseType::Unresolvable; }
  64. // 6.2.4.1 IsPropertyReference ( V ), https://tc39.es/ecma262/#sec-ispropertyreference
  65. bool is_property_reference() const
  66. {
  67. if (is_unresolvable())
  68. return false;
  69. if (m_base_type == BaseType::Environment)
  70. return false;
  71. if (m_base_value.is_boolean() || m_base_value.is_string() || m_base_value.is_symbol() || m_base_value.is_bigint() || m_base_value.is_number() || m_base_value.is_object())
  72. return true;
  73. return false;
  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. // Note: Non-standard helper.
  89. bool is_environment_reference() const
  90. {
  91. return m_base_type == BaseType::Environment;
  92. }
  93. void initialize_referenced_binding(GlobalObject& global_object, Value value) const
  94. {
  95. VERIFY(!is_unresolvable());
  96. VERIFY(m_base_type == BaseType::Environment);
  97. m_base_environment->initialize_binding(global_object, m_name.as_string(), value);
  98. }
  99. void put_value(GlobalObject&, Value);
  100. Value get_value(GlobalObject&) const;
  101. bool delete_(GlobalObject&);
  102. String to_string() const;
  103. bool is_valid_reference() const { return m_name.is_valid(); }
  104. Optional<EnvironmentCoordinate> environment_coordinate() const { return m_environment_coordinate; }
  105. private:
  106. void throw_reference_error(GlobalObject&) const;
  107. BaseType m_base_type { BaseType::Unresolvable };
  108. union {
  109. Value m_base_value {};
  110. mutable Environment* m_base_environment;
  111. };
  112. PropertyName m_name;
  113. Value m_this_value;
  114. bool m_strict { false };
  115. Optional<EnvironmentCoordinate> m_environment_coordinate;
  116. };
  117. }