wrappable.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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.chromium file.
  4. #ifndef SHELL_COMMON_GIN_HELPER_WRAPPABLE_H_
  5. #define SHELL_COMMON_GIN_HELPER_WRAPPABLE_H_
  6. #include "base/bind.h"
  7. #include "gin/per_isolate_data.h"
  8. #include "shell/common/gin_helper/constructor.h"
  9. namespace gin_helper {
  10. namespace internal {
  11. void* FromV8Impl(v8::Isolate* isolate, v8::Local<v8::Value> val);
  12. } // namespace internal
  13. template <typename T>
  14. class Wrappable : public WrappableBase {
  15. public:
  16. Wrappable() = default;
  17. template <typename Sig>
  18. static void SetConstructor(v8::Isolate* isolate,
  19. const base::Callback<Sig>& constructor) {
  20. v8::Local<v8::FunctionTemplate> templ = gin_helper::CreateFunctionTemplate(
  21. isolate, base::Bind(&internal::InvokeNew<Sig>, constructor));
  22. templ->InstanceTemplate()->SetInternalFieldCount(1);
  23. T::BuildPrototype(isolate, templ);
  24. gin::PerIsolateData::From(isolate)->SetFunctionTemplate(&kWrapperInfo,
  25. templ);
  26. }
  27. static v8::Local<v8::FunctionTemplate> GetConstructor(v8::Isolate* isolate) {
  28. // Fill the object template.
  29. auto* data = gin::PerIsolateData::From(isolate);
  30. auto templ = data->GetFunctionTemplate(&kWrapperInfo);
  31. if (templ.IsEmpty()) {
  32. templ = v8::FunctionTemplate::New(isolate);
  33. templ->InstanceTemplate()->SetInternalFieldCount(1);
  34. T::BuildPrototype(isolate, templ);
  35. data->SetFunctionTemplate(&kWrapperInfo, templ);
  36. }
  37. return templ;
  38. }
  39. protected:
  40. // Init the class with T::BuildPrototype.
  41. void Init(v8::Isolate* isolate) {
  42. v8::Local<v8::FunctionTemplate> templ = GetConstructor(isolate);
  43. // |wrapper| may be empty in some extreme cases, e.g., when
  44. // Object.prototype.constructor is overwritten.
  45. v8::Local<v8::Object> wrapper;
  46. if (!templ->InstanceTemplate()
  47. ->NewInstance(isolate->GetCurrentContext())
  48. .ToLocal(&wrapper)) {
  49. // The current wrappable object will be no longer managed by V8. Delete
  50. // this now.
  51. delete this;
  52. return;
  53. }
  54. InitWith(isolate, wrapper);
  55. }
  56. private:
  57. static gin::WrapperInfo kWrapperInfo;
  58. DISALLOW_COPY_AND_ASSIGN(Wrappable);
  59. };
  60. // static
  61. template <typename T>
  62. gin::WrapperInfo Wrappable<T>::kWrapperInfo = {gin::kEmbedderNativeGin};
  63. } // namespace gin_helper
  64. namespace gin {
  65. template <typename T>
  66. struct Converter<
  67. T*,
  68. typename std::enable_if<
  69. std::is_convertible<T*, gin_helper::WrappableBase*>::value>::type> {
  70. static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, T* val) {
  71. if (val)
  72. return val->GetWrapper();
  73. else
  74. return v8::Null(isolate);
  75. }
  76. static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val, T** out) {
  77. *out = static_cast<T*>(static_cast<gin_helper::WrappableBase*>(
  78. gin_helper::internal::FromV8Impl(isolate, val)));
  79. return *out != nullptr;
  80. }
  81. };
  82. } // namespace gin
  83. #endif // SHELL_COMMON_GIN_HELPER_WRAPPABLE_H_