diff --git a/atom.gyp b/atom.gyp index 15484fea2ae5..11621c57c663 100644 --- a/atom.gyp +++ b/atom.gyp @@ -48,6 +48,8 @@ 'common/api/atom_bindings.h', 'common/api/atom_extensions.cc', 'common/api/atom_extensions.h', + 'common/api/object_life_monitor.cc', + 'common/api/object_life_monitor.h', 'common/node_bindings.cc', 'common/node_bindings.h', 'common/node_bindings_mac.h', diff --git a/common/api/atom_api_v8_util.cc b/common/api/atom_api_v8_util.cc index ac7ac2c3421c..81f42e6c6dce 100644 --- a/common/api/atom_api_v8_util.cc +++ b/common/api/atom_api_v8_util.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "common/api/object_life_monitor.h" #include "vendor/node/src/node.h" namespace atom { @@ -38,6 +39,11 @@ v8::Handle GetObjectHash(const v8::Arguments& args) { args[0]->ToObject()->GetIdentityHash())); } +v8::Handle SetDestructor(const v8::Arguments& args) { + ObjectLifeMonitor::BindTo(args[0]->ToObject(), args[1]); + return v8::Undefined(); +} + } // namespace void InitializeV8Util(v8::Handle target) { @@ -45,6 +51,7 @@ void InitializeV8Util(v8::Handle target) { NODE_SET_METHOD(target, "getHiddenValue", GetHiddenValue); NODE_SET_METHOD(target, "setHiddenValue", SetHiddenValue); NODE_SET_METHOD(target, "getObjectHash", GetObjectHash); + NODE_SET_METHOD(target, "setDestructor", SetDestructor); } } // namespace api diff --git a/common/api/object_life_monitor.cc b/common/api/object_life_monitor.cc new file mode 100644 index 000000000000..27e4a1616c0a --- /dev/null +++ b/common/api/object_life_monitor.cc @@ -0,0 +1,51 @@ +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// Copyright (c) 2012 Intel Corp. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "common/api/object_life_monitor.h" + +namespace atom { + +// static +void ObjectLifeMonitor::BindTo(v8::Handle target, + v8::Handle destructor) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + target->SetHiddenValue(v8::String::New("destructor"), destructor); + + ObjectLifeMonitor* olm = new ObjectLifeMonitor(); + olm->handle_ = v8::Persistent::New(isolate, target); + olm->handle_.MakeWeak(isolate, olm, WeakCallback); +} + +ObjectLifeMonitor::ObjectLifeMonitor() { +} + +ObjectLifeMonitor::~ObjectLifeMonitor() { + if (!handle_.IsEmpty()) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + handle_.ClearWeak(isolate); + handle_.Dispose(isolate); + handle_.Clear(); + } +} + +// static +void ObjectLifeMonitor::WeakCallback(v8::Isolate* isolate, + v8::Persistent value, + void *data) { + // destructor.call(object, object); + { + v8::HandleScope scope; + + v8::Local obj = value->ToObject(); + v8::Local args[] = { obj }; + v8::Local::Cast(obj->GetHiddenValue( + v8::String::New("destructor")))->Call(obj, 1, args); + } + + ObjectLifeMonitor* obj = static_cast(data); + delete obj; +} + +} // namespace atom diff --git a/common/api/object_life_monitor.h b/common/api/object_life_monitor.h new file mode 100644 index 000000000000..ba68f17ec65f --- /dev/null +++ b/common/api/object_life_monitor.h @@ -0,0 +1,34 @@ +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// Copyright (c) 2012 Intel Corp. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ATOM_COMMON_API_OBJECT_LIFE_MONITOR_H_ +#define ATOM_COMMON_API_OBJECT_LIFE_MONITOR_H_ + +#include "base/basictypes.h" +#include "v8/include/v8.h" + +namespace atom { + +class ObjectLifeMonitor { + public: + static void BindTo(v8::Handle target, + v8::Handle destructor); + + private: + ObjectLifeMonitor(); + virtual ~ObjectLifeMonitor(); + + static void WeakCallback(v8::Isolate* isolate, + v8::Persistent value, + void *data); + + v8::Persistent handle_; + + DISALLOW_COPY_AND_ASSIGN(ObjectLifeMonitor); +}; + +} // namespace atom + +#endif // ATOM_COMMON_API_OBJECT_LIFE_MONITOR_H_