destroyable.cc 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. // Copyright (c) 2019 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "shell/common/gin_helper/destroyable.h"
  5. #include "base/no_destructor.h"
  6. #include "gin/converter.h"
  7. #include "shell/common/gin_helper/wrappable_base.h"
  8. namespace gin_helper {
  9. namespace {
  10. v8::Global<v8::FunctionTemplate>* GetDestroyFunc() {
  11. static base::NoDestructor<v8::Global<v8::FunctionTemplate>> destroy_func;
  12. return destroy_func.get();
  13. }
  14. v8::Global<v8::FunctionTemplate>* GetIsDestroyedFunc() {
  15. static base::NoDestructor<v8::Global<v8::FunctionTemplate>> is_destroyed_func;
  16. return is_destroyed_func.get();
  17. }
  18. void DestroyFunc(const v8::FunctionCallbackInfo<v8::Value>& info) {
  19. v8::Local<v8::Object> holder = info.Holder();
  20. if (Destroyable::IsDestroyed(holder))
  21. return;
  22. // TODO(zcbenz): gin_helper::Wrappable will be removed.
  23. delete static_cast<gin_helper::WrappableBase*>(
  24. holder->GetAlignedPointerFromInternalField(0));
  25. holder->SetAlignedPointerInInternalField(0, nullptr);
  26. }
  27. void IsDestroyedFunc(const v8::FunctionCallbackInfo<v8::Value>& info) {
  28. info.GetReturnValue().Set(gin::ConvertToV8(
  29. info.GetIsolate(), Destroyable::IsDestroyed(info.Holder())));
  30. }
  31. } // namespace
  32. // static
  33. bool Destroyable::IsDestroyed(v8::Local<v8::Object> object) {
  34. // An object is considered destroyed if it has no internal pointer or its
  35. // internal has been destroyed.
  36. return object->InternalFieldCount() == 0 ||
  37. object->GetAlignedPointerFromInternalField(0) == nullptr;
  38. }
  39. // static
  40. void Destroyable::MakeDestroyable(v8::Isolate* isolate,
  41. v8::Local<v8::FunctionTemplate> prototype) {
  42. // Cache the FunctionTemplate of "destroy" and "isDestroyed".
  43. if (GetDestroyFunc()->IsEmpty()) {
  44. auto templ = v8::FunctionTemplate::New(isolate, DestroyFunc);
  45. templ->RemovePrototype();
  46. GetDestroyFunc()->Reset(isolate, templ);
  47. templ = v8::FunctionTemplate::New(isolate, IsDestroyedFunc);
  48. templ->RemovePrototype();
  49. GetIsDestroyedFunc()->Reset(isolate, templ);
  50. }
  51. auto proto_templ = prototype->PrototypeTemplate();
  52. proto_templ->Set(
  53. gin::StringToSymbol(isolate, "destroy"),
  54. v8::Local<v8::FunctionTemplate>::New(isolate, *GetDestroyFunc()));
  55. proto_templ->Set(
  56. gin::StringToSymbol(isolate, "isDestroyed"),
  57. v8::Local<v8::FunctionTemplate>::New(isolate, *GetIsDestroyedFunc()));
  58. }
  59. } // namespace gin_helper