Handle.h 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Badge.h>
  8. #include <AK/IntrusiveList.h>
  9. #include <AK/Noncopyable.h>
  10. #include <AK/RefCounted.h>
  11. #include <AK/RefPtr.h>
  12. #include <LibJS/Forward.h>
  13. #include <LibJS/Runtime/Environment.h>
  14. #include <LibJS/Runtime/Value.h>
  15. namespace JS {
  16. class HandleImpl : public RefCounted<HandleImpl> {
  17. AK_MAKE_NONCOPYABLE(HandleImpl);
  18. AK_MAKE_NONMOVABLE(HandleImpl);
  19. public:
  20. ~HandleImpl();
  21. Cell* cell() { return m_cell; }
  22. Cell const* cell() const { return m_cell; }
  23. private:
  24. template<class T>
  25. friend class Handle;
  26. explicit HandleImpl(Cell*);
  27. Cell* m_cell { nullptr };
  28. IntrusiveListNode<HandleImpl> m_list_node;
  29. public:
  30. using List = IntrusiveList<&HandleImpl::m_list_node>;
  31. };
  32. template<class T>
  33. class Handle {
  34. public:
  35. Handle() = default;
  36. static Handle create(T* cell)
  37. {
  38. return Handle(adopt_ref(*new HandleImpl(cell)));
  39. }
  40. T* cell() { return static_cast<T*>(m_impl->cell()); }
  41. const T* cell() const { return static_cast<const T*>(m_impl->cell()); }
  42. bool is_null() const { return m_impl.is_null(); }
  43. T* operator->() { return cell(); }
  44. T const* operator->() const { return cell(); }
  45. private:
  46. explicit Handle(NonnullRefPtr<HandleImpl> impl)
  47. : m_impl(move(impl))
  48. {
  49. }
  50. RefPtr<HandleImpl> m_impl;
  51. };
  52. template<class T>
  53. inline Handle<T> make_handle(T* cell)
  54. {
  55. if (!cell)
  56. return Handle<T> {};
  57. return Handle<T>::create(cell);
  58. }
  59. template<class T>
  60. inline Handle<T> make_handle(T& cell)
  61. {
  62. return Handle<T>::create(&cell);
  63. }
  64. template<>
  65. class Handle<Value> {
  66. public:
  67. Handle() = default;
  68. static Handle create(Value value)
  69. {
  70. if (value.is_cell())
  71. return Handle(value, &value.as_cell());
  72. return Handle(value);
  73. }
  74. auto cell() { return m_handle.cell(); }
  75. auto cell() const { return m_handle.cell(); }
  76. auto value() const { return *m_value; }
  77. bool is_null() const { return m_handle.is_null() && !m_value.has_value(); }
  78. private:
  79. explicit Handle(Value value)
  80. : m_value(value)
  81. {
  82. }
  83. explicit Handle(Value value, Cell* cell)
  84. : m_value(value)
  85. , m_handle(Handle<Cell>::create(cell))
  86. {
  87. }
  88. Optional<Value> m_value;
  89. Handle<Cell> m_handle;
  90. };
  91. inline Handle<Value> make_handle(Value value)
  92. {
  93. return Handle<Value>::create(value);
  94. }
  95. }