-
Notifications
You must be signed in to change notification settings - Fork 30k
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
n-api: refactor napi_addon_register_func #15088
n-api: refactor napi_addon_register_func #15088
Conversation
napi_value Init(napi_env env) { | ||
napi_value exports; | ||
NAPI_CALL(env, | ||
napi_create_function(env, "exports", CreateFunction, NULL, &exports)); |
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.
Nit: Four spaces for continuations, IIRC.
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.
Thanks for pointing all these out. Visual Studio strikes again, I guess. I will push an update with these nits fixed. 👍
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
napi_value Init(napi_env env) { | ||
napi_value exports; | ||
NAPI_CALL(env, | ||
napi_create_function(env, "exports", CreateObject, NULL, &exports)); |
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.
Four spaces for continuation, IIRC.
NAPI_CALL_RETURN_VOID(env, napi_define_properties(env, module, 1, &desc)); | ||
napi_value exports; | ||
NAPI_CALL(env, | ||
napi_create_function(env, "exports", CreateObject, NULL, &exports)); |
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.
Four spaces.
napi_value exports; | ||
NAPI_CALL(env, napi_create_object(env, &exports)); | ||
|
||
NAPI_CALL(env, | ||
napi_define_properties(env, exports, sizeof(desc) / sizeof(*desc), desc)); |
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.
Here too.
napi_value exports; | ||
NAPI_CALL(env, napi_create_object(env, &exports)); | ||
|
||
NAPI_CALL(env, napi_define_properties( | ||
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); |
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.
Here too.
napi_value exports; | ||
NAPI_CALL(env, napi_create_object(env, &exports)); | ||
|
||
NAPI_CALL(env, napi_define_properties( |
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.
Here too.
@@ -137,8 +138,10 @@ void Init(napi_env env, napi_value exports, napi_value module, void* priv) { | |||
DECLARE_NAPI_PROPERTY("staticBuffer", staticBuffer), | |||
}; | |||
|
|||
NAPI_CALL_RETURN_VOID(env, napi_define_properties( | |||
NAPI_CALL(env, napi_define_properties( |
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.
Here too.
@@ -77,14 +77,12 @@ void Init(napi_env env, napi_value exports, napi_value module, void* priv) { | |||
}; | |||
|
|||
napi_value cons; | |||
NAPI_CALL_RETURN_VOID(env, napi_define_class(env, "MyObject", New, | |||
NAPI_CALL(env, napi_define_class(env, "MyObject", New, |
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.
Here too.
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.
Boy, I sure painted myself into a corner finding all the two-space continuations that should've been four spaces :) Anyway, this change is awesome, and brings N-API closer to the JerryScript module initializer.
napi_value exports; | ||
NAPI_CALL(env, napi_create_object(env, &exports)); | ||
|
||
NAPI_CALL(env, napi_define_properties( |
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.
Here too.
napi_value exports; | ||
NAPI_CALL(env, napi_create_object(env, &exports)); | ||
|
||
NAPI_CALL(env, napi_define_properties( |
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.
Here too.
napi_value exports; | ||
NAPI_CALL(env, napi_create_object(env, &exports)); | ||
|
||
NAPI_CALL(env, napi_define_properties( |
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.
Here too.
napi_value exports; | ||
NAPI_CALL(env, napi_create_object(env, &exports)); | ||
|
||
NAPI_CALL(env, napi_define_properties( |
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.
Here too.
napi_value exports; | ||
NAPI_CALL(env, napi_create_object(env, &exports)); | ||
|
||
NAPI_CALL(env, napi_define_properties( | ||
env, exports, sizeof(properties) / sizeof(*properties), properties)); |
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.
Here too.
napi_value exports; | ||
NAPI_CALL(env, napi_create_object(env, &exports)); | ||
|
||
NAPI_CALL(env, napi_define_properties( |
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.
Here too.
napi_value exports; | ||
NAPI_CALL(env, napi_create_object(env, &exports)); | ||
|
||
NAPI_CALL(env, napi_define_properties( | ||
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); |
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.
Here too.
napi_value exports; | ||
NAPI_CALL(env, napi_create_object(env, &exports)); | ||
|
||
NAPI_CALL(env, napi_define_properties( | ||
env, exports, sizeof(properties) / sizeof(*properties), properties)); |
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.
Here too.
napi_value exports; | ||
NAPI_CALL(env, napi_create_object(env, &exports)); | ||
|
||
NAPI_CALL(env, napi_define_properties( | ||
env, exports, sizeof(properties) / sizeof(*properties), properties)); |
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.
Here too.
napi_value exports; | ||
NAPI_CALL(env, napi_create_object(env, &exports)); | ||
|
||
NAPI_CALL(env, napi_define_properties( | ||
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); |
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.
Here too.
Would it make sense to update docs together with actual impl changes or you want to do that in a separate PR? |
env, | ||
v8impl::JsValueFromV8LocalValue(exports), | ||
v8impl::JsValueFromV8LocalValue(module), | ||
mod->nm_priv); |
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.
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.
No idea why. As far as I know, it is just the way it always has been (at least from Node v0.6 onwards).
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 think it was just for compatibility with JS-based CommonJS modules where you have both pre-created exports
and module
itself available.
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.
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.
Seems like it was done so native modules could also do module.exports = function() {};
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.
Ok from comments/backgroup it does not sound like we think the limitations will be a problem. I guess worst case is we have to add a second register with additional parameters later on and best case we don't need them and stick with it as proposed here. So once updates are added I'll take another look.
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.
One alternative that was discussed was to pre-emptively reserve a parameter in the register func signature in case the lack of module object availability during registration became a problem- that would allow us to deal with that situation in the future if it becomes a problem without causing a breaking change
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.
@digitalinfinity Even if it's needed in the future, it should be easy to add it as a separate function similar to napi_get_global
. Although I don't see any good reason to expose such CommonJS implementation details to native modules for now.
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.
@RReverser That makes sense- for some reason I was imagining the fix would involve changing the signature of napi_addon_register_func
but your approach makes sense- so I'm fine with this signature as is.
I think we should update the docs in the same PR. |
Thanks for reviewing, folks. I will update the docs along with the code changes. |
ea5c16d
to
4fd3578
Compare
@mhdawson, @gabrielschulhof Updated to add docs and address the spacing nitpicks (also fixed all the other line continuation indentation mistakes I could find in the addons-napi tests). |
doc/api/n-api.md
Outdated
napi_status status; | ||
napi_property_descriptor desc = | ||
{"hello", Method, 0, 0, 0, napi_default, 0}; | ||
napi_value exports; | ||
status = napi_create_object(env, &exports); | ||
status = napi_define_properties(env, exports, 1, &desc); |
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.
Nit: might want to update the sample to check the status of napi_create_object before calling napi_define_properties- it reads a little better, and helps folks reusing this sample from making a mistake
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.
That's fair. I noticed this sample and the one below both save the status code and then do nothing with it while I was updating the doc. Makes sense to have both of them do something when the status is not ok, especially now that the Init function return value has meaning.
env, | ||
v8impl::JsValueFromV8LocalValue(exports), | ||
v8impl::JsValueFromV8LocalValue(module), | ||
mod->nm_priv); |
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.
One alternative that was discussed was to pre-emptively reserve a parameter in the register func signature in case the lack of module object availability during registration became a problem- that would allow us to deal with that situation in the future if it becomes a problem without causing a breaking change
After thinking about it for a while, I realized that, since most often modules consist of an object that has several functions, perhaps we should pass through exports as the second parameter (after the Thus, modules which populate Modules that overwrite exports can simply return the value with which they wish to overwrite. On the implementation side, if the init callback returns NULL, we assume it has populated exports and we do nothing. If it returns non-NULL, we set the exports property on the module. If Node ever went into a mode where it no longer supplies exports we can just create it from scratch and pass it in. Then, if the module returns NULL, the object we passed in is the result of having loaded the module, otherwise the return value is the result. That way it would be a convenience we provide which modules need not make use of. I think the essence of the improvement in this PR is not the removal of the arguments, but rather the use of a return value. Setting module.exports is a really round-about way of saying the same thing that a return value says - i.e. that this is the result of having loaded the module. |
In the last N-API meeting we agreed that we should add a reserved parameter as suggested by @boingoing above. @gabrielschulhof I like the idea of avoiding forcing modules to create their own object. Once we figure out ES6 support we might even be able to recognize what type of module is being loaded and then provide the right object regardless of the type of module. I wonder if it should be that we provide an object to which exports "can" be added (at least for existing CS modules for now) but that its up to the code to either return that object after they have made additions or return a different object. ie. the module must always return an object, but that it can be a modified version of the exports object that was passed in. |
👍 |
@nodejs/n-api lets make sure to discuss this in our meeting this week so we can agree/close on the way forward. |
We have agreed:
|
As per discussion in abi-stable-node: nodejs/abi-stable-node#256, take a refactor to napi_addon_register_func such that the result from the register function is assigned to the module exports property. By making this change, native module can be agnostic about which type of module the environment supports.
fb68fc7
to
746af62
Compare
Implemented pending feedback and rebased to resolve conflicts. |
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
Landed as 92e5f5c |
As per discussion in abi-stable-node: nodejs/abi-stable-node#256, take a refactor to napi_addon_register_func such that the result from the register function is assigned to the module exports property. By making this change, native module can be agnostic about which type of module the environment supports. PR-URL: #15088 Reviewed-By: Gabriel Schulhof <[email protected]> Reviewed-By: Michael Dawson <[email protected]> Reviewed-By: Hitesh Kanwathirtha <[email protected]>
As per discussion in abi-stable-node: nodejs/abi-stable-node#256, take a refactor to napi_addon_register_func such that the result from the register function is assigned to the module exports property. By making this change, native module can be agnostic about which type of module the environment supports. PR-URL: nodejs/node#15088 Reviewed-By: Gabriel Schulhof <[email protected]> Reviewed-By: Michael Dawson <[email protected]> Reviewed-By: Hitesh Kanwathirtha <[email protected]>
As per discussion in abi-stable-node: nodejs/abi-stable-node#256, take a refactor to napi_addon_register_func such that the result from the register function is assigned to the module exports property. By making this change, native module can be agnostic about which type of module the environment supports. PR-URL: #15088 Reviewed-By: Gabriel Schulhof <[email protected]> Reviewed-By: Michael Dawson <[email protected]> Reviewed-By: Hitesh Kanwathirtha <[email protected]>
As per discussion in abi-stable-node: nodejs/abi-stable-node#256, take a refactor to napi_addon_register_func such that the result from the register function is assigned to the module exports property. By making this change, native module can be agnostic about which type of module the environment supports. PR-URL: nodejs/node#15088 Reviewed-By: Gabriel Schulhof <[email protected]> Reviewed-By: Michael Dawson <[email protected]> Reviewed-By: Hitesh Kanwathirtha <[email protected]>
As per discussion in abi-stable-node: nodejs/abi-stable-node#256, take a refactor to napi_addon_register_func such that the result from the register function is assigned to the module exports property. By making this change, native module can be agnostic about which type of module the environment supports. PR-URL: nodejs#15088 Reviewed-By: Gabriel Schulhof <[email protected]> Reviewed-By: Michael Dawson <[email protected]> Reviewed-By: Hitesh Kanwathirtha <[email protected]>
As per discussion in abi-stable-node: nodejs/abi-stable-node#256, take a refactor to napi_addon_register_func such that the result from the register function is assigned to the module exports property. By making this change, native module can be agnostic about which type of module the environment supports. Backport-PR-URL: #19447 PR-URL: #15088 Reviewed-By: Gabriel Schulhof <[email protected]> Reviewed-By: Michael Dawson <[email protected]> Reviewed-By: Hitesh Kanwathirtha <[email protected]>
As per discussion in abi-stable-node:
nodejs/abi-stable-node#256,
take a refactor to napi_addon_register_func such that
the result from the register function is assigned to
the module exports property. By making this change,
native module can be agnostic about which type of
module the environment supports.
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
n-api