wrappable.cc 3.2 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 file.
  4. #include "gin/wrappable.h"
  5. #include "base/check_op.h"
  6. #include "gin/object_template_builder.h"
  7. #include "gin/per_isolate_data.h"
  8. namespace gin {
  9. WrappableBase::WrappableBase() = default;
  10. WrappableBase::~WrappableBase() {
  11. wrapper_.Reset();
  12. }
  13. ObjectTemplateBuilder WrappableBase::GetObjectTemplateBuilder(
  14. v8::Isolate* isolate) {
  15. return ObjectTemplateBuilder(isolate, GetTypeName());
  16. }
  17. const char* WrappableBase::GetTypeName() {
  18. return nullptr;
  19. }
  20. void WrappableBase::FirstWeakCallback(
  21. const v8::WeakCallbackInfo<WrappableBase>& data) {
  22. WrappableBase* wrappable = data.GetParameter();
  23. wrappable->dead_ = true;
  24. wrappable->wrapper_.Reset();
  25. data.SetSecondPassCallback(SecondWeakCallback);
  26. }
  27. void WrappableBase::SecondWeakCallback(
  28. const v8::WeakCallbackInfo<WrappableBase>& data) {
  29. WrappableBase* wrappable = data.GetParameter();
  30. delete wrappable;
  31. }
  32. v8::MaybeLocal<v8::Object> WrappableBase::GetWrapperImpl(v8::Isolate* isolate,
  33. WrapperInfo* info) {
  34. if (!wrapper_.IsEmpty()) {
  35. return v8::MaybeLocal<v8::Object>(
  36. v8::Local<v8::Object>::New(isolate, wrapper_));
  37. }
  38. if (dead_)
  39. return v8::MaybeLocal<v8::Object>();
  40. PerIsolateData* data = PerIsolateData::From(isolate);
  41. v8::Local<v8::ObjectTemplate> templ = data->GetObjectTemplate(info);
  42. if (templ.IsEmpty()) {
  43. templ = GetObjectTemplateBuilder(isolate).Build();
  44. CHECK(!templ.IsEmpty());
  45. data->SetObjectTemplate(info, templ);
  46. }
  47. CHECK_EQ(kNumberOfInternalFields, templ->InternalFieldCount());
  48. v8::Local<v8::Object> wrapper;
  49. // |wrapper| may be empty in some extreme cases, e.g., when
  50. // Object.prototype.constructor is overwritten.
  51. if (!templ->NewInstance(isolate->GetCurrentContext()).ToLocal(&wrapper)) {
  52. // The current wrappable object will be no longer managed by V8. Delete this
  53. // now.
  54. delete this;
  55. return v8::MaybeLocal<v8::Object>(wrapper);
  56. }
  57. int indices[] = {kWrapperInfoIndex, kEncodedValueIndex};
  58. void* values[] = {info, this};
  59. wrapper->SetAlignedPointerInInternalFields(2, indices, values);
  60. wrapper_.Reset(isolate, wrapper);
  61. wrapper_.SetWeak(this, FirstWeakCallback, v8::WeakCallbackType::kParameter);
  62. return v8::MaybeLocal<v8::Object>(wrapper);
  63. }
  64. namespace internal {
  65. void* FromV8Impl(v8::Isolate* isolate, v8::Local<v8::Value> val,
  66. WrapperInfo* wrapper_info) {
  67. if (!val->IsObject())
  68. return NULL;
  69. v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(val);
  70. WrapperInfo* info = WrapperInfo::From(obj);
  71. // If this fails, the object is not managed by Gin. It is either a normal JS
  72. // object that's not wrapping any external C++ object, or it is wrapping some
  73. // C++ object, but that object isn't managed by Gin (maybe Blink).
  74. if (!info)
  75. return NULL;
  76. // If this fails, the object is managed by Gin, but it's not wrapping an
  77. // instance of the C++ class associated with wrapper_info.
  78. if (info != wrapper_info)
  79. return NULL;
  80. return obj->GetAlignedPointerFromInternalField(kEncodedValueIndex);
  81. }
  82. } // namespace internal
  83. } // namespace gin