Reference.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  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/PropertyName.h>
  10. #include <LibJS/Runtime/Value.h>
  11. namespace JS {
  12. class Reference {
  13. public:
  14. enum class BaseType : u8 {
  15. Unresolvable,
  16. Value,
  17. Environment,
  18. };
  19. Reference() { }
  20. Reference(BaseType type, PropertyName name, bool strict)
  21. : m_base_type(type)
  22. , m_name(move(name))
  23. , m_strict(strict)
  24. {
  25. }
  26. Reference(Value base, PropertyName name, Value this_value, bool strict = false)
  27. : m_base_type(BaseType::Value)
  28. , m_base_value(base)
  29. , m_name(move(name))
  30. , m_this_value(this_value)
  31. , m_strict(strict)
  32. {
  33. if (base.is_nullish()) {
  34. m_base_type = BaseType::Unresolvable;
  35. m_base_value = {};
  36. m_this_value = {};
  37. m_name = {};
  38. }
  39. }
  40. Reference(Environment& base, FlyString referenced_name, bool strict = false)
  41. : m_base_type(BaseType::Environment)
  42. , m_base_environment(&base)
  43. , m_name(move(referenced_name))
  44. , m_strict(strict)
  45. {
  46. }
  47. Value base() const
  48. {
  49. VERIFY(m_base_type == BaseType::Value);
  50. return m_base_value;
  51. }
  52. Environment& base_environment() const
  53. {
  54. VERIFY(m_base_type == BaseType::Environment);
  55. return *m_base_environment;
  56. }
  57. PropertyName const& name() const { return m_name; }
  58. bool is_strict() const { return m_strict; }
  59. // 6.2.4.2 IsUnresolvableReference ( V ), https://tc39.es/ecma262/#sec-isunresolvablereference
  60. bool is_unresolvable() const { return m_base_type == BaseType::Unresolvable; }
  61. // 6.2.4.1 IsPropertyReference ( V ), https://tc39.es/ecma262/#sec-ispropertyreference
  62. bool is_property_reference() const
  63. {
  64. if (is_unresolvable())
  65. return false;
  66. if (m_base_type == BaseType::Environment)
  67. return false;
  68. 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())
  69. return true;
  70. return false;
  71. }
  72. // 6.2.4.7 GetThisValue ( V ), https://tc39.es/ecma262/#sec-getthisvalue
  73. Value get_this_value() const
  74. {
  75. VERIFY(is_property_reference());
  76. if (is_super_reference())
  77. return m_this_value;
  78. return m_base_value;
  79. }
  80. // 6.2.4.3 IsSuperReference ( V ), https://tc39.es/ecma262/#sec-issuperreference
  81. bool is_super_reference() const
  82. {
  83. return !m_this_value.is_empty();
  84. }
  85. // Note: Non-standard helper.
  86. bool is_environment_reference() const
  87. {
  88. return m_base_type == BaseType::Environment;
  89. }
  90. void put_value(GlobalObject&, Value);
  91. Value get_value(GlobalObject&, bool throw_if_undefined = true) const;
  92. bool delete_(GlobalObject&);
  93. String to_string() const;
  94. private:
  95. void throw_reference_error(GlobalObject&) const;
  96. BaseType m_base_type { BaseType::Unresolvable };
  97. union {
  98. Value m_base_value {};
  99. Environment* m_base_environment;
  100. };
  101. PropertyName m_name;
  102. Value m_this_value;
  103. bool m_strict { false };
  104. };
  105. }