You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Unused prototype objects from V8 FunctionTemplate initialization #17668
We don't need these prototypes, and we can get rid of them either through v8::FunctionTemplate::RemovePrototype() or indirectly, by specifying v8::ConstructorBehavior::kThrow when creating the v8::FunctionTemplate.
@brandonrninefive I think Environment::SetMethod, Environment::SetProtoMethod and Environment::SetTemplateMethod in env-inl.h are the relevant places where this would apply.
@addaleax Great! Thank you. I think I've figured out how this works. The udp_wrap binding and its associated prototypes/functions are defined within udp_wrap.cc. From there, I can use RemovePrototype() on FunctionTemplate objects to remove their prototype objects. Furthermore, I can use the Environment methods that you listed above to define methods outside or within prototype objects.
For clarification regarding this exact issue, am I just getting rid of the last prototype object listed in > typeof process.binding('udp_wrap').UDP.prototype.bind6.prototype ?
Or am getting rid of that prototype and also the prototype object after UDP, and replacing its prototype methods with regular methods defined either by Environment::SetMethod or Environment::SetTemplateMethod?
I appreciate the help, and please let me know if any of my above conclusions are incorrect.
@brandonrninefive My recommendation is that you do not use RemovePrototype(), instead using v8::ConstructorBehavior::kThrow when creating such methods in Environment::SetProtoMethod. (You will need to tweak Environment::NewFunctionTemplate() (decl, impl) to accept a third optional parameter of type v8::ConstructorBehavior, to allow passing this information to V8.) There are several reasons for this:
This way, not only udp_wrap's classes are fixed but also other bindings. In the original issue, I only used udp_wrap as an example. The same issue applies to all other bindings.
As a bonus, this would make new (process.binding('udp_wrap').UDP.prototype.bind6)() throw. One should never do something like that in the first place, and since process.binding is considered internal API this makes the code more robust.
With regards to your last question, you are only getting rid of the last prototype. If you look at built-in methods like Number.prototype.toString, you will notice that they don't have a prototype property. That's what we are trying to accomplish here as well.
Activity
brandontruggles commentedon Apr 12, 2018
Hello, I'd like to work on this! Any tips on where I should look?
addaleax commentedon Apr 14, 2018
@brandonrninefive I think
Environment::SetMethod,Environment::SetProtoMethodandEnvironment::SetTemplateMethodinenv-inl.hare the relevant places where this would apply.brandontruggles commentedon Apr 19, 2018
@addaleax Great! Thank you. I think I've figured out how this works. The
udp_wrapbinding and its associated prototypes/functions are defined withinudp_wrap.cc. From there, I can useRemovePrototype()onFunctionTemplateobjects to remove their prototype objects. Furthermore, I can use theEnvironmentmethods that you listed above to define methods outside or within prototype objects.For clarification regarding this exact issue, am I just getting rid of the last
prototypeobject listed in> typeof process.binding('udp_wrap').UDP.prototype.bind6.prototype?Or am getting rid of that prototype and also the
prototypeobject afterUDP, and replacing its prototype methods with regular methods defined either byEnvironment::SetMethodorEnvironment::SetTemplateMethod?I appreciate the help, and please let me know if any of my above conclusions are incorrect.
TimothyGu commentedon Apr 20, 2018
@brandonrninefive My recommendation is that you do not use
RemovePrototype(), instead usingv8::ConstructorBehavior::kThrowwhen creating such methods inEnvironment::SetProtoMethod. (You will need to tweakEnvironment::NewFunctionTemplate()(decl, impl) to accept a third optional parameter of typev8::ConstructorBehavior, to allow passing this information to V8.) There are several reasons for this:udp_wrap's classes are fixed but also other bindings. In the original issue, I only usedudp_wrapas an example. The same issue applies to all other bindings.new (process.binding('udp_wrap').UDP.prototype.bind6)()throw. One should never do something like that in the first place, and sinceprocess.bindingis considered internal API this makes the code more robust.With regards to your last question, you are only getting rid of the last prototype. If you look at built-in methods like
Number.prototype.toString, you will notice that they don't have aprototypeproperty. That's what we are trying to accomplish here as well.brandontruggles commentedon Apr 25, 2018
@TimothyGu Thank you for all the tips! I'm working on implementing this now, and I should have a PR ready over the next few days.
src: removed unnecessary prototypes from Environment::SetProtoMethod
src: removed unnecessary prototypes from Environment::SetProtoMethod
src: removed unnecessary prototypes from Environment::SetProtoMethod
src: removed unnecessary prototypes from Environment::SetProtoMethod