V8's ObjectTemplate
provides us two ways to attach a so-called accessor property to the object under instantiation.
The first one is ObjectTemplate::SetAccessor
:
/**
* Sets an accessor on the object template.
*
* Whenever the property with the given name is accessed on objects
* created from this ObjectTemplate the getter and setter callbacks
* are called instead of getting and setting the property directly
* on the JavaScript object.
*
* \param name The name of the property for which an accessor is added.
* \param getter The callback to invoke when getting the property.
* \param setter The callback to invoke when setting the property.
* \param data A piece of data that will be passed to the getter and setter
* callbacks whenever they are invoked.
* \param settings Access control settings for the accessor. This is a bit
* field consisting of one of more of
* DEFAULT = 0, ALL_CAN_READ = 1, or ALL_CAN_WRITE = 2.
* The default is to not allow cross-context access.
* ALL_CAN_READ means that all cross-context reads are allowed.
* ALL_CAN_WRITE means that all cross-context writes are allowed.
* The combination ALL_CAN_READ | ALL_CAN_WRITE can be used to allow all
* cross-context access.
* \param attribute The attributes of the property for which an accessor
* is added.
* \param signature The signature describes valid receivers for the accessor
* and is used to perform implicit instance checks against them. If the
* receiver is incompatible (i.e. is not an instance of the constructor as
* defined by FunctionTemplate::HasInstance()), an implicit TypeError is
* thrown and no callback is invoked.
*/
void SetAccessor(
Local<String> name, AccessorGetterCallback getter,
AccessorSetterCallback setter = nullptr,
Local<Value> data = Local<Value>(), AccessControl settings = DEFAULT, // note the data is on the template level.
PropertyAttribute attribute = None, // not on the instance level.
Local<AccessorSignature> signature = Local<AccessorSignature>(),
SideEffectType getter_side_effect_type = SideEffectType::kHasSideEffect,
SideEffectType setter_side_effect_type = SideEffectType::kHasSideEffect);
and the second one is Template::SetAccessorProperty
:
void SetAccessorProperty(
Local<Name> name, // The latter one is called data property.
Local<FunctionTemplate> getter = Local<FunctionTemplate>(),
Local<FunctionTemplate> setter = Local<FunctionTemplate>(),
PropertyAttribute attribute = None,
AccessControl settings = DEFAULT);
Having two very similar APIs confuses me a lot.
Unfortunately there is no docs describing their differences, so I have to do experiment on my own. I found that the combination of Holder()
and SetAccessor()
will break, while other combinations of Holder() or This()
and SetAccessor() or SetAccessorProperty()
work fine. On a previous post I ran into this failing combination and was fooled to believe what's went wrong is Holder() or This()
. But after the experiment I now believe that it is SetAccessor
went wrong.
My question is, whether SetAccessor
is a deprecated API? If so, all we have to do is stop using it. If not so, please explain a little bit their differences, esspecially in causing this failure. Many thanks to the warm-hearted and experienced V8 developers!