From bd64f5ced2b5d2680d9bf2cea28ec038dfe62b49 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 27 Aug 2015 16:41:51 +0800 Subject: [PATCH] Use V8's new SetWeak method --- atom/common/api/object_life_monitor.cc | 50 ++++++++++++++++++-------- atom/common/api/object_life_monitor.h | 21 +++++++---- atom/common/id_weak_map.cc | 31 +++++++++------- atom/common/id_weak_map.h | 3 -- vendor/native_mate | 2 +- 5 files changed, 70 insertions(+), 37 deletions(-) diff --git a/atom/common/api/object_life_monitor.cc b/atom/common/api/object_life_monitor.cc index 18d2a3a4d53f..9b7c7fe6d05f 100644 --- a/atom/common/api/object_life_monitor.cc +++ b/atom/common/api/object_life_monitor.cc @@ -5,32 +5,52 @@ #include "atom/common/api/object_life_monitor.h" -#include "native_mate/compat.h" +#include "base/bind.h" +#include "base/message_loop/message_loop.h" namespace atom { // static void ObjectLifeMonitor::BindTo(v8::Isolate* isolate, v8::Local target, - v8::Local destructor) { - target->SetHiddenValue(MATE_STRING_NEW(isolate, "destructor"), destructor); - - ObjectLifeMonitor* olm = new ObjectLifeMonitor(); - olm->handle_.reset(isolate, target); - olm->handle_.SetWeak(olm, WeakCallback); + v8::Local destructor) { + new ObjectLifeMonitor(isolate, target, destructor); } -ObjectLifeMonitor::ObjectLifeMonitor() { +ObjectLifeMonitor::ObjectLifeMonitor(v8::Isolate* isolate, + v8::Local target, + v8::Local destructor) + : isolate_(isolate), + context_(isolate, isolate->GetCurrentContext()), + target_(isolate, target), + destructor_(isolate, destructor), + weak_ptr_factory_(this) { + target_.SetWeak(this, OnObjectGC, v8::WeakCallbackType::kParameter); } // static -void ObjectLifeMonitor::WeakCallback( - const v8::WeakCallbackData& data) { - // destructor.call(object, object); - v8::Local obj = data.GetValue(); - v8::Local::Cast(obj->GetHiddenValue( - MATE_STRING_NEW(data.GetIsolate(), "destructor")))->Call(obj, 0, NULL); - delete data.GetParameter(); +void ObjectLifeMonitor::OnObjectGC( + const v8::WeakCallbackInfo& data) { + // Usually FirstWeakCallback should do nothing other than reset |object_| + // and then set a second weak callback to run later. We can sidestep that, + // because posting a task to the current message loop is all but free - but + // DO NOT add any more work to this method. The only acceptable place to add + // code is RunCallback. + ObjectLifeMonitor* self = data.GetParameter(); + self->target_.Reset(); + base::MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(&ObjectLifeMonitor::RunCallback, + self->weak_ptr_factory_.GetWeakPtr())); +} + +void ObjectLifeMonitor::RunCallback() { + v8::HandleScope handle_scope(isolate_); + v8::Local context = v8::Local::New( + isolate_, context_); + v8::Context::Scope context_scope(context); + v8::Local::New(isolate_, destructor_)->Call( + context->Global(), 0, nullptr); + delete this; } } // namespace atom diff --git a/atom/common/api/object_life_monitor.h b/atom/common/api/object_life_monitor.h index e8dbbcf65f15..90216d8227a5 100644 --- a/atom/common/api/object_life_monitor.h +++ b/atom/common/api/object_life_monitor.h @@ -6,7 +6,8 @@ #define ATOM_COMMON_API_OBJECT_LIFE_MONITOR_H_ #include "base/basictypes.h" -#include "native_mate/scoped_persistent.h" +#include "base/memory/weak_ptr.h" +#include "v8/include/v8.h" namespace atom { @@ -14,15 +15,23 @@ class ObjectLifeMonitor { public: static void BindTo(v8::Isolate* isolate, v8::Local target, - v8::Local destructor); + v8::Local destructor); private: - ObjectLifeMonitor(); + ObjectLifeMonitor(v8::Isolate* isolate, + v8::Local target, + v8::Local destructor); - static void WeakCallback( - const v8::WeakCallbackData& data); + static void OnObjectGC(const v8::WeakCallbackInfo& data); - mate::ScopedPersistent handle_; + void RunCallback(); + + v8::Isolate* isolate_; + v8::Global context_; + v8::Global target_; + v8::Global destructor_; + + base::WeakPtrFactory weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(ObjectLifeMonitor); }; diff --git a/atom/common/id_weak_map.cc b/atom/common/id_weak_map.cc index 4e86d7309a82..0be16765ac4c 100644 --- a/atom/common/id_weak_map.cc +++ b/atom/common/id_weak_map.cc @@ -10,6 +10,23 @@ namespace atom { +namespace { + +struct ObjectKey { + ObjectKey(int id, IDWeakMap* map) : id(id), map(map) {} + int id; + IDWeakMap* map; +}; + +void OnObjectGC(const v8::WeakCallbackInfo& data) { + ObjectKey* key = data.GetParameter(); + LOG(ERROR) << "OnObjectGC: " << key->id; + key->map->Remove(key->id); + delete key; +} + +} // namespace + IDWeakMap::IDWeakMap() : next_id_(0) { } @@ -18,11 +35,9 @@ IDWeakMap::~IDWeakMap() { int32_t IDWeakMap::Add(v8::Isolate* isolate, v8::Local object) { int32_t id = GetNextID(); - object->SetHiddenValue(mate::StringToSymbol(isolate, "IDWeakMapKey"), - mate::Converter::ToV8(isolate, id)); - auto global = make_linked_ptr(new v8::Global(isolate, object)); - global->SetWeak(this, &WeakCallback); + ObjectKey* key = new ObjectKey(id, this); + global->SetWeak(key, OnObjectGC, v8::WeakCallbackType::kParameter); map_[id] = global; return id; } @@ -71,12 +86,4 @@ int32_t IDWeakMap::GetNextID() { return ++next_id_; } -// static -void IDWeakMap::WeakCallback( - const v8::WeakCallbackData& data) { - int32_t id = data.GetValue()->GetHiddenValue( - mate::StringToV8(data.GetIsolate(), "IDWeakMapKey"))->Int32Value(); - data.GetParameter()->Remove(id); -} - } // namespace atom diff --git a/atom/common/id_weak_map.h b/atom/common/id_weak_map.h index b16334d6cea1..9fe71ebb616f 100644 --- a/atom/common/id_weak_map.h +++ b/atom/common/id_weak_map.h @@ -44,9 +44,6 @@ class IDWeakMap { // Returns next available ID. int32_t GetNextID(); - static void WeakCallback( - const v8::WeakCallbackData& data); - // ID of next stored object. int32_t next_id_; diff --git a/vendor/native_mate b/vendor/native_mate index f5e34deb1a52..8ca005eb4159 160000 --- a/vendor/native_mate +++ b/vendor/native_mate @@ -1 +1 @@ -Subproject commit f5e34deb1a5226b4e7e620cb65fce0225471d4d9 +Subproject commit 8ca005eb41591f583ebab804945311903f866ad6