-
Notifications
You must be signed in to change notification settings - Fork 465
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
src: add Addon<T> class #749
src: add Addon<T> class #749
Conversation
8a779a3
to
beb1fa3
Compare
beb1fa3
to
a8cccd8
Compare
b1c99cf
to
ce880ff
Compare
ce880ff
to
871dc65
Compare
0beeb83
to
6b0469b
Compare
6b0469b
to
4283b2c
Compare
@mhdawson @NickNaso @addaleax @legendecas @KevinEady @jschlight as discussed in today's meeting, I re-worked the PR as follows:
I also made the commit message more verbose:
Bindings created like this perform slightly worse than static ones in |
a6d68c7
to
855372f
Compare
@gabrielschulhof thanks for refactoring. Trying hard to carve out a block of time to review. Failed today but will try again tomorrow. |
@mhdawson thank you! |
napi-inl.h
Outdated
#define NODE_API_MODULE(modname, regfunc) \ | ||
napi_value __napi_ ## regfunc(napi_env env, \ | ||
static napi_value __napi_ ## regfunc(napi_env env, \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tests seems to compile/pass without this change. Wondering as to my its in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added it because I was working on an add-on definition macro right next to it, and we shouldn't be exposing the entry point symbol. You're right though, I'll make it a separate PR.
benchmark/function_args.cc
Outdated
|
||
return exports; | ||
} | ||
NAPI_THROW_IF_FAILED_VOID(env, status); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes mean we won't be able to run the benchmarks if the target is less than NAPI_VERSION 6.
I wonder if the changes to the benchmark code should be additive so that we get new numbers if the target is NAPI_VERSION 6 or greater as opposed to replacing the existing ones.
That would also let us keep an eye on the delta between using the additional wrapper or not.
Overall I really like this. I think it really helps with ease of use. Just had a few comments. Once you've updated let me know and I'll LGTM. Totally separate but something I think this helps enable and that I think it would be really cool is that instead of having to create the code to call DefineAddon(), you could just annotate the methods and we'd generate the required call to DefineAddon(), maybe something like: // @function increment
Napi::Value Increment(const Napi::CallbackInfo& info) {
return Napi::Number::New(info.Env(), ++value);
} It also relates a bit to the question we had about generating documentation as well as we could then also add information /**
* @function increment
* @param {number} increment_amount - amount to increment when the method is called
* @returns {number} the incremented value
*/
Napi::Value Increment(const Napi::CallbackInfo& info) {
value = value + ${PARAM_increment_amount}.Uint32Value();
return Napi::Number::New(info.Env(), value);
} Where ${PARAM_increment_amount} would be converted to info[0].AsNapi::Number() based on being the first parameter defined, and being defined as type number. I think it would require a pre-processing step but that might be reasonable. Thinking about it, the same could be useful for object wrap as well I think we could probably come up with annotations for the |
855372f
to
30ce2b9
Compare
@mhdawson I have made the changes you requested. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
* separate out instance-related APIs from `ObjectWrap<T>` into a new class `InstanceWrap<T>` which then becomes a base class for `ObjectWrap<T>`. * Add `Addon<T>` class as a subclass of `InstanceWrap<T>`, reimplementing `Unwrap()` to retrieve the instance data using `GetInstanceData<T>()` of `Napi::Env` instead of `napi_unwrap()`. * Add macros `NODE_API_ADDON()` and `NODE_API_NAMED_ADDON()` to load an add-on from its `Addon<T>` subclass definition. Bindings created like this perform slightly worse than static ones in exchange for the benefit of having the context of a class instance as their C++ `this` object. This way, they avoid having to call `info.GetInstanceData<ClassName>()` in the bindings, which brings with it the risk that the wrong `ClassName` will end up in the template parameter thus resulting in a hard-to-track-down segfault. Static bindings can still be created and associated with the `exports` object and they can use `Napi::Env::GetInstanceData()` to retrieve the add-on instance.
30ce2b9
to
ecafa3e
Compare
Rebased and squashed. |
* separate out instance-related APIs from `ObjectWrap<T>` into a new class `InstanceWrap<T>` which then becomes a base class for `ObjectWrap<T>`. * Add `Addon<T>` class as a subclass of `InstanceWrap<T>`, reimplementing `Unwrap()` to retrieve the instance data using `GetInstanceData<T>()` of `Napi::Env` instead of `napi_unwrap()`. * Add macros `NODE_API_ADDON()` and `NODE_API_NAMED_ADDON()` to load an add-on from its `Addon<T>` subclass definition. Bindings created like this perform slightly worse than static ones in exchange for the benefit of having the context of a class instance as their C++ `this` object. This way, they avoid having to call `info.GetInstanceData<ClassName>()` in the bindings, which brings with it the risk that the wrong `ClassName` will end up in the template parameter thus resulting in a hard-to-track-down segfault. Static bindings can still be created and associated with the `exports` object and they can use `Napi::Env::GetInstanceData()` to retrieve the add-on instance. PR-URL: #749 Reviewed-By: Michael Dawson <[email protected]>
Landed in 5af645f. |
* separate out instance-related APIs from `ObjectWrap<T>` into a new class `InstanceWrap<T>` which then becomes a base class for `ObjectWrap<T>`. * Add `Addon<T>` class as a subclass of `InstanceWrap<T>`, reimplementing `Unwrap()` to retrieve the instance data using `GetInstanceData<T>()` of `Napi::Env` instead of `napi_unwrap()`. * Add macros `NODE_API_ADDON()` and `NODE_API_NAMED_ADDON()` to load an add-on from its `Addon<T>` subclass definition. Bindings created like this perform slightly worse than static ones in exchange for the benefit of having the context of a class instance as their C++ `this` object. This way, they avoid having to call `info.GetInstanceData<ClassName>()` in the bindings, which brings with it the risk that the wrong `ClassName` will end up in the template parameter thus resulting in a hard-to-track-down segfault. Static bindings can still be created and associated with the `exports` object and they can use `Napi::Env::GetInstanceData()` to retrieve the add-on instance. PR-URL: nodejs/node-addon-api#749 Reviewed-By: Michael Dawson <[email protected]>
* separate out instance-related APIs from `ObjectWrap<T>` into a new class `InstanceWrap<T>` which then becomes a base class for `ObjectWrap<T>`. * Add `Addon<T>` class as a subclass of `InstanceWrap<T>`, reimplementing `Unwrap()` to retrieve the instance data using `GetInstanceData<T>()` of `Napi::Env` instead of `napi_unwrap()`. * Add macros `NODE_API_ADDON()` and `NODE_API_NAMED_ADDON()` to load an add-on from its `Addon<T>` subclass definition. Bindings created like this perform slightly worse than static ones in exchange for the benefit of having the context of a class instance as their C++ `this` object. This way, they avoid having to call `info.GetInstanceData<ClassName>()` in the bindings, which brings with it the risk that the wrong `ClassName` will end up in the template parameter thus resulting in a hard-to-track-down segfault. Static bindings can still be created and associated with the `exports` object and they can use `Napi::Env::GetInstanceData()` to retrieve the add-on instance. PR-URL: nodejs/node-addon-api#749 Reviewed-By: Michael Dawson <[email protected]>
* separate out instance-related APIs from `ObjectWrap<T>` into a new class `InstanceWrap<T>` which then becomes a base class for `ObjectWrap<T>`. * Add `Addon<T>` class as a subclass of `InstanceWrap<T>`, reimplementing `Unwrap()` to retrieve the instance data using `GetInstanceData<T>()` of `Napi::Env` instead of `napi_unwrap()`. * Add macros `NODE_API_ADDON()` and `NODE_API_NAMED_ADDON()` to load an add-on from its `Addon<T>` subclass definition. Bindings created like this perform slightly worse than static ones in exchange for the benefit of having the context of a class instance as their C++ `this` object. This way, they avoid having to call `info.GetInstanceData<ClassName>()` in the bindings, which brings with it the risk that the wrong `ClassName` will end up in the template parameter thus resulting in a hard-to-track-down segfault. Static bindings can still be created and associated with the `exports` object and they can use `Napi::Env::GetInstanceData()` to retrieve the add-on instance. PR-URL: nodejs/node-addon-api#749 Reviewed-By: Michael Dawson <[email protected]>
* separate out instance-related APIs from `ObjectWrap<T>` into a new class `InstanceWrap<T>` which then becomes a base class for `ObjectWrap<T>`. * Add `Addon<T>` class as a subclass of `InstanceWrap<T>`, reimplementing `Unwrap()` to retrieve the instance data using `GetInstanceData<T>()` of `Napi::Env` instead of `napi_unwrap()`. * Add macros `NODE_API_ADDON()` and `NODE_API_NAMED_ADDON()` to load an add-on from its `Addon<T>` subclass definition. Bindings created like this perform slightly worse than static ones in exchange for the benefit of having the context of a class instance as their C++ `this` object. This way, they avoid having to call `info.GetInstanceData<ClassName>()` in the bindings, which brings with it the risk that the wrong `ClassName` will end up in the template parameter thus resulting in a hard-to-track-down segfault. Static bindings can still be created and associated with the `exports` object and they can use `Napi::Env::GetInstanceData()` to retrieve the add-on instance. PR-URL: nodejs/node-addon-api#749 Reviewed-By: Michael Dawson <[email protected]>
ObjectWrap<T>
into a newclass
InstanceWrap<T>
which then becomes a base class forObjectWrap<T>
.Expose newDefineProperties
overload onObject
which accepts alist of
napi_property_descriptor
and implement the other overloadsas a call to it.
Addon<T>
class as a subclass ofInstanceWrap<T>
.NODE_API_ADDON()
andNODE_API_NAMED_ADDON()
to load anadd-on from its
Addon<T>
subclass definition.Bindings created like this perform slightly worse than static ones in
exchange for the benefit of having the context of a class instance as
their C++
this
object. Static bindings can still be created andassociated with the
exports
object and they can useNapi::Env::GetInstanceData()
to retrieve the add-on instance.Edit: I removed the
DefineProperties
overload, opting instead to haveAddon<T>
provide aDefineProperties
method to its subclasses.