Re: [v8-users] Recovering a FunctionTemplate (or how to ->Inherit from one you've lost the handle to?)

2020-10-23 Thread Rodrigo Hernandez
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 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 context = aIsolate->GetCurrentContext();
>> //---
>> // Store constructor on a callback data object
>>
>> v8::Local constructor_data_template = 
>> v8::ObjectTemplate::New ( aIsolate );
>> constructor_data_template->SetInternalFieldCount ( 1 );
>> v8::Local constructor_data =
>>
>> constructor_data_template->NewInstance ( context 
>> ).ToLocalChecked();
>>
>> // Prepare EventTarget constructor template
>> v8::Local constructor_template = 
>> v8::FunctionTemplate::New ( aIsolate, JsObjectWrap::New, 
>> 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 event = event_template->GetFunction ( 
>> context ).ToLocalChecked();
>> context->Global()->Set ( context, v8::String::NewFromUtf8 (
>>  aIsolate, "Event" ).ToLocalChecked(),
>>  event ).FromJust();
>>
>>
>> v8::Local 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 context = aIsolate->GetCurrentContext();
>>
>> // Prepare Node constructor template
>>
>> v8::Local 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 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 

Re: [v8-users] Recovering a FunctionTemplate (or how to ->Inherit from one you've lost the handle to?)

2020-10-23 Thread Ben Ernst
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 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 context = aIsolate->GetCurrentContext();
> //---
> // Store constructor on a callback data object
>
> v8::Local constructor_data_template = 
> v8::ObjectTemplate::New ( aIsolate );
> constructor_data_template->SetInternalFieldCount ( 1 );
> v8::Local constructor_data =
>
> constructor_data_template->NewInstance ( context 
> ).ToLocalChecked();
>
> // Prepare EventTarget constructor template
> v8::Local constructor_template = 
> v8::FunctionTemplate::New ( aIsolate, JsObjectWrap::New, 
> 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 event = event_template->GetFunction ( context 
> ).ToLocalChecked();
> context->Global()->Set ( context, v8::String::NewFromUtf8 (
>  aIsolate, "Event" ).ToLocalChecked(),
>  event ).FromJust();
>
>
> v8::Local 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 context = aIsolate->GetCurrentContext();
>
> // Prepare Node constructor template
>
> v8::Local 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 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, 
> v8::Persistent v8::CopyablePersistentTraits>> FunctionTemplates{};
>
> So I need to free them all, unlike a