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.