wrappable.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // Copyright 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef GIN_WRAPPABLE_H_
  5. #define GIN_WRAPPABLE_H_
  6. #include <type_traits>
  7. #include "gin/converter.h"
  8. #include "gin/gin_export.h"
  9. #include "gin/public/wrapper_info.h"
  10. namespace gin {
  11. // Wrappable is a base class for C++ objects that have corresponding v8 wrapper
  12. // objects. To retain a Wrappable object on the stack, use a gin::Handle.
  13. //
  14. // USAGE:
  15. // // my_class.h
  16. // class MyClass : Wrappable<MyClass> {
  17. // public:
  18. // static WrapperInfo kWrapperInfo;
  19. //
  20. // // Optional, only required if non-empty template should be used.
  21. // virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
  22. // v8::Isolate* isolate);
  23. // ...
  24. // };
  25. //
  26. // // my_class.cc
  27. // WrapperInfo MyClass::kWrapperInfo = {kEmbedderNativeGin};
  28. //
  29. // gin::ObjectTemplateBuilder MyClass::GetObjectTemplateBuilder(
  30. // v8::Isolate* isolate) {
  31. // return Wrappable<MyClass>::GetObjectTemplateBuilder(isolate)
  32. // .SetValue("foobar", 42);
  33. // }
  34. //
  35. // Subclasses should also typically have private constructors and expose a
  36. // static Create function that returns a gin::Handle. Forcing creators through
  37. // this static Create function will enforce that clients actually create a
  38. // wrapper for the object. If clients fail to create a wrapper for a wrappable
  39. // object, the object will leak because we use the weak callback from the
  40. // wrapper as the signal to delete the wrapped object.
  41. //
  42. // Wrappable<T> explicitly does not support further subclassing of T.
  43. // Subclasses of Wrappable<T> should be declared final. Because Wrappable<T>
  44. // caches the object template using &T::kWrapperInfo as the key, all subclasses
  45. // would share a single object template. This will lead to hard to debug crashes
  46. // that look like use-after-free errors.
  47. namespace internal {
  48. GIN_EXPORT void* FromV8Impl(v8::Isolate* isolate,
  49. v8::Local<v8::Value> val,
  50. WrapperInfo* info);
  51. } // namespace internal
  52. class ObjectTemplateBuilder;
  53. // Non-template base class to share code between templates instances.
  54. class GIN_EXPORT WrappableBase {
  55. public:
  56. WrappableBase(const WrappableBase&) = delete;
  57. WrappableBase& operator=(const WrappableBase&) = delete;
  58. protected:
  59. WrappableBase();
  60. virtual ~WrappableBase();
  61. // Overrides of this method should be declared final and not overridden again.
  62. virtual ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate);
  63. // Returns a readable type name that will be used in surfacing errors. The
  64. // default implementation returns nullptr, which results in a generic error.
  65. virtual const char* GetTypeName();
  66. v8::MaybeLocal<v8::Object> GetWrapperImpl(v8::Isolate* isolate,
  67. WrapperInfo* wrapper_info);
  68. private:
  69. static void FirstWeakCallback(
  70. const v8::WeakCallbackInfo<WrappableBase>& data);
  71. static void SecondWeakCallback(
  72. const v8::WeakCallbackInfo<WrappableBase>& data);
  73. bool dead_ = false;
  74. v8::Global<v8::Object> wrapper_; // Weak
  75. };
  76. template<typename T>
  77. class Wrappable : public WrappableBase {
  78. public:
  79. Wrappable(const Wrappable&) = delete;
  80. Wrappable& operator=(const Wrappable&) = delete;
  81. // Retrieve (or create) the v8 wrapper object corresponding to this object.
  82. v8::MaybeLocal<v8::Object> GetWrapper(v8::Isolate* isolate) {
  83. return GetWrapperImpl(isolate, &T::kWrapperInfo);
  84. }
  85. protected:
  86. Wrappable() = default;
  87. ~Wrappable() override = default;
  88. };
  89. template <typename T>
  90. struct ToV8ReturnsMaybe<
  91. T*,
  92. typename std::enable_if<
  93. std::is_convertible<T*, WrappableBase*>::value>::type> {
  94. static const bool value = true;
  95. };
  96. // This converter handles any subclass of Wrappable.
  97. template <typename T>
  98. struct Converter<T*,
  99. typename std::enable_if<
  100. std::is_convertible<T*, WrappableBase*>::value>::type> {
  101. static v8::MaybeLocal<v8::Value> ToV8(v8::Isolate* isolate, T* val) {
  102. if (val == nullptr)
  103. return v8::Null(isolate);
  104. v8::Local<v8::Object> wrapper;
  105. if (!val->GetWrapper(isolate).ToLocal(&wrapper))
  106. return v8::MaybeLocal<v8::Value>();
  107. return v8::MaybeLocal<v8::Value>(wrapper);
  108. }
  109. static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val, T** out) {
  110. *out = static_cast<T*>(static_cast<WrappableBase*>(
  111. internal::FromV8Impl(isolate, val, &T::kWrapperInfo)));
  112. return *out != NULL;
  113. }
  114. };
  115. } // namespace gin
  116. #endif // GIN_WRAPPABLE_H_