Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed externally referenced objects getting their destructor invoked #110

Closed
wants to merge 7 commits into from
24 changes: 15 additions & 9 deletions v8pp/class.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <memory>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <list>

Expand Down Expand Up @@ -82,8 +83,7 @@ class object_registry final : public class_info
// each JavaScript instance has 3 internal fields:
// 0 - pointer to a wrapped C++ object
// 1 - pointer to this object_registry
// 2 - pointer to the object destructor
func->InstanceTemplate()->SetInternalFieldCount(3);
func->InstanceTemplate()->SetInternalFieldCount(2);
func->Inherit(js_func);
}

Expand All @@ -93,6 +93,7 @@ class object_registry final : public class_info
, bases_(std::move(src.bases_))
, derivatives_(std::move(src.derivatives_))
, objects_(std::move(src.objects_))
, unowned_objects_(std::move(src.unowned_objects_))
, isolate_(std::move(src.isolate_))
, func_(std::move(src.func_))
, js_func_(std::move(src.js_func_))
Expand Down Expand Up @@ -238,7 +239,9 @@ class object_registry final : public class_info

obj->SetAlignedPointerInInternalField(0, Traits::pointer_id(object));
obj->SetAlignedPointerInInternalField(1, this);
obj->SetAlignedPointerInInternalField(2, call_dtor? /*dtor_*/this : nullptr);
if (!call_dtor) {
unowned_objects_.emplace(object);
}

v8::Global<v8::Object> pobj(isolate_, obj);
pobj.SetWeak(this, [](v8::WeakCallbackInfo<object_registry> const& data)
Expand Down Expand Up @@ -269,7 +272,7 @@ class object_registry final : public class_info
while (value->IsObject())
{
v8::Local<v8::Object> obj = value.As<v8::Object>();
if (obj->InternalFieldCount() == 3)
if (obj->InternalFieldCount() == 2)
{
object_id id = obj->GetAlignedPointerFromInternalField(0);
if (id)
Expand All @@ -294,22 +297,24 @@ class object_registry final : public class_info
private:
void reset_object(std::pair<pointer_type const, v8::Global<v8::Object>>& object)
{
bool call_dtor = true;
if (!object.second.IsNearDeath())
{
v8::Local<v8::Object> obj = to_local(isolate_, object.second);
assert(obj->InternalFieldCount() == 3);
assert(obj->InternalFieldCount() == 2);
assert(obj->GetAlignedPointerFromInternalField(0) == Traits::pointer_id(object.first));
assert(obj->GetAlignedPointerFromInternalField(1) == this);
call_dtor = (obj->GetAlignedPointerFromInternalField(2) != nullptr);
// remove internal fields to disable unwrapping for this V8 Object
obj->SetAlignedPointerInInternalField(0, nullptr);
obj->SetAlignedPointerInInternalField(1, nullptr);
obj->SetAlignedPointerInInternalField(2, nullptr);
}
if (call_dtor)
auto it = unowned_objects_.find(object.first);
if (it == unowned_objects_.end())
{
dtor_(isolate_, object.first);
}
else
{
unowned_objects_.erase(it);
}
object.second.Reset();
}
Expand All @@ -330,6 +335,7 @@ class object_registry final : public class_info
std::vector<object_registry*> derivatives_;

std::unordered_map<pointer_type, v8::Global<v8::Object>> objects_;
std::unordered_set<pointer_type> unowned_objects_;

v8::Isolate* isolate_;
v8::Global<v8::FunctionTemplate> func_;
Expand Down