Thanks for the great help!
I think it makes a lot of sense now.

So I've extended ObjectWrap like so:

class BSONObject : public node::ObjectWrap
> {
> private:
>     bson_t* _bson;
> public:
>     BSONObject(bson_t* bson, Local<ObjectTemplate> tpl) :
>         _bson(bson)
>     {
>         Local<Object> obj = tpl->NewInstance();
>         initialize(v8::Isolate::GetCurrent(), obj, bson);
>         Wrap(obj);
>     }



 ~BSONObject()
>     {
>         std::cout << "~BSONObject()" << std::endl;
>         bson_destroy(_bson);
>     }



    static
>     Local<ObjectTemplate>
>     create_template(Isolate* isolate, const bson_t* document)
>     {
>         Local<ObjectTemplate> tpl = ObjectTemplate::New(isolate);
>         tpl->SetInternalFieldCount(1);


And the "insert" function that I expose in JS and that instanciates the
BSONObject is written like this:

void
> insert(const FunctionCallbackInfo<Value>& args)
> {
>     Isolate* isolate = args.GetIsolate();
>
>     db->insert(
>         json_stringify(isolate, args[0]),
>         [&args, isolate](const bson_t* document)
>         {
>             if (!args[1]->IsUndefined())
>             {
>                 Local<Function> callback = Local<Function>::Cast(args[1]);
>                 Local<Object> obj = Object::New(isolate);
>                 *Local<Value> argv[] = { (new
> BSONObject(bson_copy(document)))->handle(isolate) };*
>                 callback->Call(isolate->GetCurrentContext()->Global(), 1,
> argv);
>             }
>         }
>     );
> }


It runs fine.
But the destructor is never called (I never see "~BSONObject()" on stdout).

Did I miss something?

Thanks !

2017-11-16 22:01 GMT+01:00 J Decker <[email protected]>:

> You don't manage the instance, the v8 engine does.  When it's no longer
> referenced in the engine, it's garbage collected which triggers the
> callback set when the perisstent object is made weak.
>
> You don't need to keep it anywhere, the object returned into the engine
> has Internal Fields ( SetInternalFieldCount(1) ) which is used to point to
> your native class instance.   So when the callback is called, it knows what
> to call to destruct it.
>
> You have to 'keep it' in the javascript scrpit if you want to keep it,
> it's not 'kept' in the native code...
>
>
> --- This is some code I've done that uses setweak directly; but it's
> fairly scattered....
>
> https://github.com/d3x0r/sack.vfs/blob/master/src/jsonParse.cc#L18
>
> You can create an instance of your wrapped object with
>
> Local<Function> cons = Local<Function>::New( isolate, constructor );
>     cons->NewInstance( isolate->GetCurrentContext(), argc, argv
> ).ToLocalChecked() ;
>
> Hmm that's not the best example source...
>
> https://github.com/d3x0r/sack.vfs/blob/master/src/vfs_module.cc#L407
>
> This creates a buffer, and makes it weak...
> https://github.com/d3x0r/sack.vfs/blob/master/src/vfs_module.cc#L438
>
> Local<Object> arrayBuffer = ArrayBuffer::New( isolate, buf, len );
> PARRAY_BUFFER_HOLDER holder = GetHolder();
> holder->o.Reset( isolate, arrayBuffer );
> holder->o.SetWeak<ARRAY_BUFFER_HOLDER>( holder, releaseBuffer,
> WeakCallbackType::kParameter );
> holder->buffer = buf;
>
> PARRAY_BUFFER_HOLDER is just a type that holds the thing to be free (or
> object containing things to be released), and the persistent reference that
> has been made weak...
>
> struct arrayBufferHolder {
> void *buffer;
> Persistent<Object> o;
> };
>
>
>
> On Thu, Nov 16, 2017 at 9:56 AM, Jean-Marc Le Roux <
> [email protected]> wrote:
>
>> Node offers a C++ Clss extention ObjectWrap
>>
>>
>> Thanks !
>> It is related to node. Yet I'm not sure how I'm supposed to use
>> ObjectWrap.
>>
>> I understand I have to create my own class that extends ObjectWrap and
>> implement a proper destructor.
>> Then I'll instanciate that class to wrap my Local<Object>. But how do I
>> manage such instance?
>> If I don't keep it somewhere, it will be destructed.
>> If I keep it around, then I'm keeping references to potentially
>> deallocated memory.
>>
>> It feels like I end up with the same problem...
>>
>> 2017-11-16 18:36 GMT+01:00 J Decker <[email protected]>:
>>
>>>
>>>
>>> On Thu, Nov 16, 2017 at 1:24 AM, Jean-Marc Le Roux <
>>> [email protected]> wrote:
>>>
>>>> I assume you're storing references to the objects as Persistent?
>>>>
>>>>
>>>> Nope. You've got the whole code up there.
>>>> So if I understand correctly:
>>>>
>>>>    - the objects I need to keep track of the lifecycle should be made
>>>>    Persistent ;
>>>>    - all the other values can be set as Local ;
>>>>    - I should set the weak callback using MakeWeak ;
>>>>    - callback will be called when such object is GCed and I can free
>>>>    my C/C++ memory then.
>>>>
>>>> Is that correct ?
>>>>
>>>
>>> Yes.  I sthis perhaps related to Node?
>>> Node offers a C++ Clss extention ObjectWrap
>>>
>>> https://nodejs.org/api/addons.html#addons_wrapping_c_objects
>>> https://github.com/nodejs/node/blob/master/src/node_object_wrap.h
>>>
>>> which simplifies that whole process... when the object is GC'd the class
>>> destructor will get called so you can release values there.
>>>
>>>
>>>
>>>>
>>>> 2017-11-15 19:50 GMT+01:00 J Decker <[email protected]>:
>>>>
>>>>> I assume you're storing references to the objects as Persistent?  All
>>>>> you need to do then is call SetWeak() https://v8docs.nodes
>>>>> ource.com/node-0.10/d2/d78/classv8_1_1_persistent.html
>>>>> void MakeWeak (void *parameters, WeakReferenceCallback callback)
>>>>>
>>>>> the callback is called when the object is GC'd.
>>>>>
>>>>>
>>>>> On Wed, Nov 15, 2017 at 8:37 AM, Jean-Marc Le Roux <
>>>>> [email protected]> wrote:
>>>>>
>>>>>> So I've found a solution to make things lazy: I set an accessor
>>>>>> instead of decoding/setting the actual value.
>>>>>>
>>>>>> void
>>>>>> getter(Local<Name> property, const PropertyCallbackInfo<Value>& info)
>>>>>> {
>>>>>>     Isolate* isolate = info.GetIsolate();
>>>>>>
>>>>>>       const bson_t* document = reinterpret_cast<bson_t*>(
>>>>>>         info.This()
>>>>>>             ->Get(String::NewFromUtf8(isolate,
>>>>>> "__bson_document_ptr"))
>>>>>>             ->ToInt32()->Value()
>>>>>>     );
>>>>>>
>>>>>>     char key[255];
>>>>>>     property->ToString(isolate)->WriteUtf8(key, 255);
>>>>>>
>>>>>>     bson_iter_t iter;
>>>>>>     bson_iter_init(&iter, document);
>>>>>>     // FIXME: index the property so we don't have to find it
>>>>>>     bson_iter_find(&iter, key);
>>>>>>
>>>>>>     // FIXME: replace the accessor with the deserialized value
>>>>>>
>>>>>>     info.GetReturnValue().Set(iterator_to_value(isolate, &iter));
>>>>>> }
>>>>>>
>>>>>> Local<Value>
>>>>>> fill_object(Isolate* isolate, Local<Object>& obj, const bson_t*
>>>>>> document)
>>>>>> {
>>>>>>     obj->Set(
>>>>>>         String::NewFromUtf8(isolate, "__bson_document_ptr"),
>>>>>>         Int32::New(isolate, reinterpret_cast<intptr_t>(document))
>>>>>>     );
>>>>>>
>>>>>>     bson_iter_t iter;
>>>>>>     if (bson_iter_init(&iter, document))
>>>>>>     {
>>>>>>         while (bson_iter_next(&iter))
>>>>>>         {
>>>>>>             const char* key = bson_iter_key(&iter);
>>>>>>
>>>>>>                         if (!obj->Has(String::NewFromUtf8(isolate,
>>>>>> key)))
>>>>>>             {
>>>>>>                 obj->SetAccessor(
>>>>>>                     isolate->GetCurrentContext(),
>>>>>>                     String::NewFromUtf8(isolate, key),
>>>>>>                     &getter
>>>>>>                 );
>>>>>>             }
>>>>>>                 }
>>>>>>     }
>>>>>> }
>>>>>>
>>>>>> The secret sauce is to :
>>>>>>
>>>>>>    - keep the original data (the bson_t) allocated
>>>>>>    - store the corresponding pointer in a v8::Object
>>>>>>
>>>>>> But now I have a memory leak because those pointers will never be
>>>>>> freed.
>>>>>> How can I know when the Object will be disposed by the GC?
>>>>>>
>>>>>> Thanks,
>>>>>>
>>>>>> --
>>>>>> --
>>>>>> v8-users mailing list
>>>>>> [email protected]
>>>>>> http://groups.google.com/group/v8-users
>>>>>> ---
>>>>>> You received this message because you are subscribed to the Google
>>>>>> Groups "v8-users" group.
>>>>>> To unsubscribe from this group and stop receiving emails from it,
>>>>>> send an email to [email protected].
>>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>>
>>>>>
>>>>> --
>>>>> --
>>>>> v8-users mailing list
>>>>> [email protected]
>>>>> http://groups.google.com/group/v8-users
>>>>> ---
>>>>> You received this message because you are subscribed to a topic in the
>>>>> Google Groups "v8-users" group.
>>>>> To unsubscribe from this topic, visit https://groups.google.com/d/to
>>>>> pic/v8-users/aVeevQcHJ2c/unsubscribe.
>>>>> To unsubscribe from this group and all its topics, send an email to
>>>>> [email protected].
>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> *Jean-Marc Le Roux*
>>>>
>>>>
>>>> Founder and CEO of Aerys (http://aerys.in)
>>>>
>>>> Blog: http://blogs.aerys.in/jeanmarc-leroux
>>>> Cell: (+33)6 20 56 45 78 <+33%206%2020%2056%2045%2078>
>>>> Phone: (+33)9 72 40 17 58 <+33%209%2072%2040%2017%2058>
>>>>
>>>> --
>>>> --
>>>> v8-users mailing list
>>>> [email protected]
>>>> http://groups.google.com/group/v8-users
>>>> ---
>>>> You received this message because you are subscribed to the Google
>>>> Groups "v8-users" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>> an email to [email protected].
>>>> For more options, visit https://groups.google.com/d/optout.
>>>>
>>>
>>> --
>>> --
>>> v8-users mailing list
>>> [email protected]
>>> http://groups.google.com/group/v8-users
>>> ---
>>> You received this message because you are subscribed to a topic in the
>>> Google Groups "v8-users" group.
>>> To unsubscribe from this topic, visit https://groups.google.com/d/to
>>> pic/v8-users/aVeevQcHJ2c/unsubscribe.
>>> To unsubscribe from this group and all its topics, send an email to
>>> [email protected].
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>>
>>
>> --
>> *Jean-Marc Le Roux*
>>
>>
>> Founder and CEO of Aerys (http://aerys.in)
>>
>> Blog: http://blogs.aerys.in/jeanmarc-leroux
>> Cell: (+33)6 20 56 45 78 <+33%206%2020%2056%2045%2078>
>> Phone: (+33)9 72 40 17 58 <+33%209%2072%2040%2017%2058>
>>
>> --
>> --
>> v8-users mailing list
>> [email protected]
>> http://groups.google.com/group/v8-users
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "v8-users" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>> For more options, visit https://groups.google.com/d/optout.
>>
>
> --
> --
> v8-users mailing list
> [email protected]
> http://groups.google.com/group/v8-users
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "v8-users" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/
> topic/v8-users/aVeevQcHJ2c/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> [email protected].
> For more options, visit https://groups.google.com/d/optout.
>



-- 
*Jean-Marc Le Roux*


Founder and CEO of Aerys (http://aerys.in)

Blog: http://blogs.aerys.in/jeanmarc-leroux
Cell: (+33)6 20 56 45 78
Phone: (+33)9 72 40 17 58

-- 
-- 
v8-users mailing list
[email protected]
http://groups.google.com/group/v8-users
--- 
You received this message because you are subscribed to the Google Groups 
"v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to