Yeah, that sounds like needlessly complicating things even more. I'll just 
stash this problem for now since its already working.

Thanks again!

On Friday, October 23, 2020 at 12:16:09 AM UTC-6 boi...@gmail.com wrote:

> I work with embedded V8, not with node, so some of that is french to me :)
> I tried storing FunctionTemplate in a Value and encountered the same error.
> If you're keeping the persistent handles in a global collection in any 
> case, you might consider taking a raw pointer to the Persistent, and 
> storing that in a v8::External. Then you can static_cast it back to 
> FunctionTemplate where you call "Inherit". It still means you're doing some 
> deliberate garbage handling however.
>
> On Friday, 23 October 2020 at 06:35:07 UTC+10:30 Rodrigo Hernandez wrote:
>
>> Hi Ben,
>>
>> Yes, however what I need to store is the v8::FunctionTemplate, 
>> v8::Local<v8::FunctionTemplate> to be more specific, which does not inherit 
>> from Value and there is a static_assert that checks for that.
>>
>> So perhaps, maybe if go to the real problem a different solution may 
>> arise.
>>
>> I have a Js wrapper C++ base class from which all C++-to-Js must inherit, 
>> this is based on the code for Node.js, so when I write a new class that 
>> inherits from this wrapper, I need to allocate a FunctionTemplate on the 
>> isolate/context pair, like so:
>>
>> I removed some lines, but otherwise you can look at this code here: 
>> https://github.com/AeonGames/AeonGUI/blob/master/core/dom/EventTarget.cpp#L23
>>
>>     void EventTarget::Initialize ( v8::Isolate* aIsolate )
>>     {
>>         v8::Local<v8::Context> context = aIsolate->GetCurrentContext();
>>         //---------------------------------------
>>         // Store constructor on a callback data object
>>
>>         v8::Local<v8::ObjectTemplate> constructor_data_template = 
>> v8::ObjectTemplate::New ( aIsolate );
>>         constructor_data_template->SetInternalFieldCount ( 1 );
>>         v8::Local<v8::Object> constructor_data =
>>
>>             constructor_data_template->NewInstance ( context 
>> ).ToLocalChecked();
>>
>>         // Prepare EventTarget constructor template
>>         v8::Local<v8::FunctionTemplate> constructor_template = 
>> v8::FunctionTemplate::New ( aIsolate, JsObjectWrap::New<EventTarget>, 
>> constructor_data ); 
>> // <----- THIS IS THE FunctionTemplate I NEED TO STORE
>>
>>         constructor_template->SetClassName ( v8::String::NewFromUtf8 ( 
>> aIsolate, "EventTarget" ).ToLocalChecked() );
>>
>>         constructor_template->InstanceTemplate()->SetInternalFieldCount ( 1 
>> );
>>
>>         
>> AddFunctionTemplate ( aIsolate, typeid ( EventTarget ), constructor_template 
>> ); 
>> // <---- THIS IS MY CURRENT SOLUTION
>>
>>         //----------------------------------------------------------------
>>
>>
>>         v8::Local<v8::Function> event = event_template->GetFunction ( 
>> context ).ToLocalChecked();
>>         context->Global()->Set ( context, v8::String::NewFromUtf8 (
>>                                      aIsolate, "Event" ).ToLocalChecked(),
>>                                  event ).FromJust();
>>
>>
>>         v8::Local<v8::Function> constructor = 
>> constructor_template->GetFunction ( context ).ToLocalChecked();
>>         constructor_data->SetInternalField ( 0, constructor );
>>         context->Global()->Set ( context, v8::String::NewFromUtf8 (
>>
>>                                      aIsolate, "EventTarget" 
>> ).ToLocalChecked(),
>>                                  constructor ).FromJust();
>>     }
>>
>> Then, when I want to have Node inherit from EventTarget I write a similar 
>> static function (the previous one is also static)
>> https://github.com/AeonGames/AeonGUI/blob/master/core/dom/Node.cpp#L221
>>
>>     void Node::Initialize ( v8::Isolate* aIsolate )
>>     {
>>         if ( HasFunctionTemplate ( aIsolate, typeid ( Node ) ) )
>>         {
>>             throw std::runtime_error ( "Isolate already initialized." );
>>         }
>>
>>         v8::Local<v8::Context> context = aIsolate->GetCurrentContext();
>>
>>         // Prepare Node constructor template
>>
>>         v8::Local<v8::FunctionTemplate> constructor_template = 
>> v8::FunctionTemplate::New ( aIsolate );
>>
>>         constructor_template->SetClassName ( v8::String::NewFromUtf8 ( 
>> aIsolate, "Node" ).ToLocalChecked() );
>>         constructor_template->Inherit ( EventTarget::GetFunctionTemplate ( 
>> aIsolate, typeid ( EventTarget ) ) ); 
>> // <-- THIS IS WHAT I REALLY NEED
>>
>>
>>         AddFunctionTemplate ( aIsolate, typeid ( Node ), 
>> constructor_template );
>>
>>
>>         v8::Local<v8::Function> constructor = 
>> constructor_template->GetFunction ( context ).ToLocalChecked();
>>         context->Global()->Set ( context, v8::String::NewFromUtf8 (
>>                                      aIsolate, "Node" ).ToLocalChecked(),
>>                                  constructor ).FromJust();
>>     }
>>
>> As I said before, this works but I feel that makes the code too verbose 
>> and prone to error, for example now I am now forced to have a trivial 
>> Finalize function on all classes:
>>
>>     void Node::Finalize ( v8::Isolate* aIsolate )
>>     {
>>         RemoveFunctionTemplate ( aIsolate, typeid ( Node ) );
>>     }
>>
>> because the FunctionTemplate objects are stored as Persistent Handles in 
>> this map:
>>
>>
>> static std::unordered_map<std::pair<v8::Isolate*, size_t>, 
>> v8::Persistent<v8::FunctionTemplate, 
>> v8::CopyablePersistentTraits<v8::FunctionTemplate>>> FunctionTemplates{};
>>
>> So I need to free them all, unlike a Local.
>>
>> So, perhaps there is a way where I can either store the template in the 
>> constructor, or maybe there is a way to have Node inherit from EventTarget 
>> without requiring the FunctionTemplate, but instead require just the 
>> function?
>>
>> Thanks for taking a look!
>> On Wednesday, October 21, 2020 at 5:39:59 PM UTC-6 boi...@gmail.com 
>> wrote:
>>
>>> Rodrigo, you should be able to trivially cast a v8::Function or 
>>> v8::Object to v8::Value is that what you're trying to do? In that case you 
>>> don't need to put them in a v8::External. You can pass those objects to 
>>> data->SetInternalField safely I would think.
>>> Ben
>>>
>>>
>>> On Tuesday, 20 October 2020 at 15:10:00 UTC+10:30 Rodrigo Hernandez 
>>> wrote:
>>>
>>>> So, coming back to this, is there a way to cast/convert/wrap a local 
>>>> template (function or object) into a v8::Value?
>>>> I am thinking about hiding them inside an internal field so I could do:
>>>>
>>>> context->global()->GetFunction("constructor")->GetInternalField(X).
>>>>
>>>> how safe would it be to cast them to a void* and wrapping them inside a 
>>>> v8::External?
>>>>
>>>> On Sunday, October 11, 2020 at 11:40:27 AM UTC-6 Rodrigo Hernandez 
>>>> wrote:
>>>>
>>>>> Thanks Ben, I see how those are less optimal, I was hoping for 
>>>>> something along the lines of 
>>>>> context->global()->GetFunctionTemplate("constructor"), or something along 
>>>>> those lines.
>>>>> The only problem I have with my approach is that I need a Finalize 
>>>>> function on each wrapped class that pretty much just resets the permanent 
>>>>> handles.
>>>>>
>>>>> Thanks Again!
>>>>> On Sunday, October 11, 2020 at 1:49:10 AM UTC-6 Ben Noordhuis wrote:
>>>>>
>>>>>> On Sat, Oct 10, 2020 at 10:44 PM Rodrigo Hernandez 
>>>>>> <kwizatz.ae...@gmail.com> wrote: 
>>>>>> > 
>>>>>> > Hello, 
>>>>>> > 
>>>>>> > So, suppose I am wrapping a C++ class around a JS constructor, I've 
>>>>>> already created and initialized the isolate, created and initialized a 
>>>>>> context, I have the FunctionTemplate for the constructor and I have 
>>>>>> instantiated the function and I can call it from Js as x() or new X(), 
>>>>>> > all this is fine, the function template context is finished and the 
>>>>>> handle lost. 
>>>>>> > 
>>>>>> > But then I want to create another wrapped object for a class that 
>>>>>> inherits from the first one. 
>>>>>> > Is there a way to retrieve the base class FunctionTemplate so in 
>>>>>> the child class I can call child->Inherit(base)? 
>>>>>> > 
>>>>>> > Is there another way of doing this? 
>>>>>> > 
>>>>>> > Right now I am keeping a C++ unordered_map of isolate to persistent 
>>>>>> handle to function templates, and that works, but is that the only 
>>>>>> option? 
>>>>>> > 
>>>>>> > Thanks! 
>>>>>>
>>>>>> It's not the only option but it's a pretty good solution. Less 
>>>>>> optimal 
>>>>>> solutions: 
>>>>>>
>>>>>> - store them in the snapshot with SnapshotCreator::AddData() (but you 
>>>>>> can only retrieve it once) 
>>>>>> - scan the heap for them with Isolate::VisitHandlesWithClassIds(). 
>>>>>>
>>>>>> No doubt there are more ways to stow them away somewhere. 
>>>>>>
>>>>>

-- 
-- 
v8-users mailing list
v8-users@googlegroups.com
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 v8-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/v8-users/ab0c1374-e8e7-41d4-9574-67a903bb64ean%40googlegroups.com.

Reply via email to