Skip to content

Commit 50cb48b

Browse files
boingoingMylesBorins
authored andcommittedApr 16, 2018
n-api: refactor napi_addon_register_func
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 <gabriel.schulhof@intel.com> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: Hitesh Kanwathirtha <digitalinfinity@gmail.com>
1 parent 156a8b6 commit 50cb48b

File tree

37 files changed

+322
-272
lines changed

37 files changed

+322
-272
lines changed
 

‎doc/api/n-api.md

+32-23
Original file line numberDiff line numberDiff line change
@@ -873,7 +873,7 @@ JavaScript Object associated with the `napi_ref`. Otherise, result
873873
will be NULL.
874874

875875
## Module registration
876-
N-API modules are registered in the same manner as other modules
876+
N-API modules are registered in a manner similar to other modules
877877
except that instead of using the `NODE_MODULE` macro the following
878878
is used:
879879

@@ -885,32 +885,39 @@ The next difference is the signature for the `Init` method. For a N-API
885885
module it is as follows:
886886

887887
```C
888-
void Init(napi_env env, napi_value exports, napi_value module, void* priv);
888+
napi_value Init(napi_env env, napi_value exports);
889889
```
890890

891-
As with any other module, functions are exported by either adding them to
892-
the `exports` or `module` objects passed to the `Init` method.
891+
The return value from `Init` is treated as the `exports` object for the module.
892+
The `Init` method is passed an empty object via the `exports` parameter as a
893+
convenience. If `Init` returns NULL, the parameter passed as `exports` is
894+
exported by the module. N-API modules cannot modify the `module` object but can
895+
specify anything as the `exports` property of the module.
893896

894897
For example, to add the method `hello` as a function so that it can be called
895898
as a method provided by the addon:
896899

897900
```C
898-
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
901+
napi_value Init(napi_env env, napi_value exports) {
899902
napi_status status;
900903
napi_property_descriptor desc =
901904
{"hello", Method, 0, 0, 0, napi_default, 0};
905+
if (status != napi_ok) return nullptr;
902906
status = napi_define_properties(env, exports, 1, &desc);
907+
if (status != napi_ok) return nullptr;
908+
return exports;
903909
}
904910
```
905911

906912
For example, to set a function to be returned by the `require()` for the addon:
907913

908914
```C
909-
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
915+
napi_value Init(napi_env env, napi_value exports) {
916+
napi_value method;
910917
napi_status status;
911-
napi_property_descriptor desc =
912-
{"exports", Method, 0, 0, 0, napi_default, 0};
913-
status = napi_define_properties(env, module, 1, &desc);
918+
status = napi_create_function(env, "exports", Method, NULL, &method));
919+
if (status != napi_ok) return nullptr;
920+
return method;
914921
}
915922
```
916923

@@ -919,28 +926,30 @@ For example, to define a class so that new instances can be created
919926

920927
```C
921928
// NOTE: partial example, not all referenced code is included
922-
923-
napi_status status;
924-
napi_property_descriptor properties[] = {
929+
napi_value Init(napi_env env, napi_value exports) {
930+
napi_status status;
931+
napi_property_descriptor properties[] = {
925932
{ "value", nullptr, GetValue, SetValue, 0, napi_default, 0 },
926933
DECLARE_NAPI_METHOD("plusOne", PlusOne),
927934
DECLARE_NAPI_METHOD("multiply", Multiply),
928-
};
935+
};
929936

930-
napi_value cons;
931-
status =
932-
napi_define_class(env, "MyObject", New, nullptr, 3, properties, &cons);
933-
if (status != napi_ok) return;
937+
napi_value cons;
938+
status =
939+
napi_define_class(env, "MyObject", New, nullptr, 3, properties, &cons);
940+
if (status != napi_ok) return nullptr;
934941

935-
status = napi_create_reference(env, cons, 1, &constructor);
936-
if (status != napi_ok) return;
942+
status = napi_create_reference(env, cons, 1, &constructor);
943+
if (status != napi_ok) return nullptr;
937944

938-
status = napi_set_named_property(env, exports, "MyObject", cons);
939-
if (status != napi_ok) return;
945+
status = napi_set_named_property(env, exports, "MyObject", cons);
946+
if (status != napi_ok) return nullptr;
947+
948+
return exports;
949+
}
940950
```
941951

942-
For more details on setting properties on either the `exports` or `module`
943-
objects, see the section on
952+
For more details on setting properties on objects, see the section on
944953
[Working with JavaScript Properties][].
945954

946955
For more details on building addon modules in general, refer to the existing API

‎src/node_api.cc

+11-5
Original file line numberDiff line numberDiff line change
@@ -829,11 +829,17 @@ void napi_module_register_cb(v8::Local<v8::Object> exports,
829829
// one is found.
830830
napi_env env = v8impl::GetEnv(context);
831831

832-
mod->nm_register_func(
833-
env,
834-
v8impl::JsValueFromV8LocalValue(exports),
835-
v8impl::JsValueFromV8LocalValue(module),
836-
mod->nm_priv);
832+
napi_value _exports =
833+
mod->nm_register_func(env, v8impl::JsValueFromV8LocalValue(exports));
834+
835+
// If register function returned a non-null exports object different from
836+
// the exports object we passed it, set that as the "exports" property of
837+
// the module.
838+
if (_exports != nullptr &&
839+
_exports != v8impl::JsValueFromV8LocalValue(exports)) {
840+
napi_value _module = v8impl::JsValueFromV8LocalValue(module);
841+
napi_set_named_property(env, _module, "exports", _exports);
842+
}
837843
}
838844

839845
#ifndef EXTERNAL_NAPI

‎src/node_api.h

+2-4
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,8 @@
4444
#endif
4545

4646

47-
typedef void (*napi_addon_register_func)(napi_env env,
48-
napi_value exports,
49-
napi_value module,
50-
void* priv);
47+
typedef napi_value (*napi_addon_register_func)(napi_env env,
48+
napi_value exports);
5149

5250
typedef struct {
5351
int nm_version;

‎test/addons-napi/1_hello_world/binding.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ napi_value Method(napi_env env, napi_callback_info info) {
1010
return world;
1111
}
1212

13-
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
13+
napi_value Init(napi_env env, napi_value exports) {
1414
napi_property_descriptor desc = DECLARE_NAPI_PROPERTY("hello", Method);
15-
NAPI_CALL_RETURN_VOID(env, napi_define_properties(env, exports, 1, &desc));
15+
NAPI_CALL(env, napi_define_properties(env, exports, 1, &desc));
16+
return exports;
1617
}
1718

1819
NAPI_MODULE(addon, Init)

‎test/addons-napi/2_function_arguments/binding.c

+4-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ napi_value Add(napi_env env, napi_callback_info info) {
1515
NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));
1616

1717
NAPI_ASSERT(env, valuetype0 == napi_number && valuetype1 == napi_number,
18-
"Wrong argument type. Numbers expected.");
18+
"Wrong argument type. Numbers expected.");
1919

2020
double value0;
2121
NAPI_CALL(env, napi_get_value_double(env, args[0], &value0));
@@ -29,9 +29,10 @@ napi_value Add(napi_env env, napi_callback_info info) {
2929
return sum;
3030
}
3131

32-
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
32+
napi_value Init(napi_env env, napi_value exports) {
3333
napi_property_descriptor desc = DECLARE_NAPI_PROPERTY("add", Add);
34-
NAPI_CALL_RETURN_VOID(env, napi_define_properties(env, exports, 1, &desc));
34+
NAPI_CALL(env, napi_define_properties(env, exports, 1, &desc));
35+
return exports;
3536
}
3637

3738
NAPI_MODULE(addon, Init)

‎test/addons-napi/3_callbacks/binding.c

+6-5
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@ napi_value RunCallback(napi_env env, napi_callback_info info) {
88
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
99

1010
NAPI_ASSERT(env, argc == 1,
11-
"Wrong number of arguments. Expects a single argument.");
11+
"Wrong number of arguments. Expects a single argument.");
1212

1313
napi_valuetype valuetype0;
1414
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
1515
NAPI_ASSERT(env, valuetype0 == napi_function,
16-
"Wrong type of arguments. Expects a function as first argument.");
16+
"Wrong type of arguments. Expects a function as first argument.");
1717

1818
napi_valuetype valuetype1;
1919
NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));
2020
NAPI_ASSERT(env, valuetype1 == napi_undefined,
21-
"Additional arguments should be undefined.");
21+
"Additional arguments should be undefined.");
2222

2323
napi_value argv[1];
2424
const char* str = "hello world";
@@ -45,12 +45,13 @@ napi_value RunCallbackWithRecv(napi_env env, napi_callback_info info) {
4545
return NULL;
4646
}
4747

48-
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
48+
napi_value Init(napi_env env, napi_value exports) {
4949
napi_property_descriptor desc[2] = {
5050
DECLARE_NAPI_PROPERTY("RunCallback", RunCallback),
5151
DECLARE_NAPI_PROPERTY("RunCallbackWithRecv", RunCallbackWithRecv),
5252
};
53-
NAPI_CALL_RETURN_VOID(env, napi_define_properties(env, exports, 2, desc));
53+
NAPI_CALL(env, napi_define_properties(env, exports, 2, desc));
54+
return exports;
5455
}
5556

5657
NAPI_MODULE(addon, Init)

‎test/addons-napi/4_object_factory/binding.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ napi_value CreateObject(napi_env env, napi_callback_info info) {
1414
return obj;
1515
}
1616

17-
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
18-
napi_property_descriptor desc =
19-
DECLARE_NAPI_PROPERTY("exports", CreateObject);
20-
NAPI_CALL_RETURN_VOID(env, napi_define_properties(env, module, 1, &desc));
17+
napi_value Init(napi_env env, napi_value exports) {
18+
NAPI_CALL(env,
19+
napi_create_function(env, "exports", CreateObject, NULL, &exports));
20+
return exports;
2121
}
2222

2323
NAPI_MODULE(addon, Init)

‎test/addons-napi/5_function_factory/binding.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ napi_value MyFunction(napi_env env, napi_callback_info info) {
1111
napi_value CreateFunction(napi_env env, napi_callback_info info) {
1212
napi_value fn;
1313
NAPI_CALL(env,
14-
napi_create_function(env, "theFunction", MyFunction, NULL, &fn));
14+
napi_create_function(env, "theFunction", MyFunction, NULL, &fn));
1515

1616
return fn;
1717
}
1818

19-
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
20-
napi_property_descriptor desc =
21-
DECLARE_NAPI_PROPERTY("exports", CreateFunction);
22-
NAPI_CALL_RETURN_VOID(env, napi_define_properties(env, module, 1, &desc));
19+
napi_value Init(napi_env env, napi_value exports) {
20+
NAPI_CALL(env,
21+
napi_create_function(env, "exports", CreateFunction, NULL, &exports));
22+
return exports;
2323
}
2424

2525
NAPI_MODULE(addon, Init)
+3-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#include "myobject.h"
2+
#include "../common.h"
23

3-
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
4+
napi_value Init(napi_env env, napi_value exports) {
45
MyObject::Init(env, exports);
6+
return exports;
57
}
68

79
NAPI_MODULE(addon, Init)

‎test/addons-napi/6_object_wrap/myobject.cc

+9-9
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ void MyObject::Init(napi_env env, napi_value exports) {
2323

2424
napi_value cons;
2525
NAPI_CALL_RETURN_VOID(env,
26-
napi_define_class(env, "MyObject", New, nullptr, 3, properties, &cons));
26+
napi_define_class(env, "MyObject", New, nullptr, 3, properties, &cons));
2727

2828
NAPI_CALL_RETURN_VOID(env, napi_create_reference(env, cons, 1, &constructor));
2929

3030
NAPI_CALL_RETURN_VOID(env,
31-
napi_set_named_property(env, exports, "MyObject", cons));
31+
napi_set_named_property(env, exports, "MyObject", cons));
3232
}
3333

3434
napi_value MyObject::New(napi_env env, napi_callback_info info) {
@@ -55,11 +55,11 @@ napi_value MyObject::New(napi_env env, napi_callback_info info) {
5555

5656
obj->env_ = env;
5757
NAPI_CALL(env, napi_wrap(env,
58-
_this,
59-
obj,
60-
MyObject::Destructor,
61-
nullptr, // finalize_hint
62-
&obj->wrapper_));
58+
_this,
59+
obj,
60+
MyObject::Destructor,
61+
nullptr, // finalize_hint
62+
&obj->wrapper_));
6363

6464
return _this;
6565
}
@@ -80,7 +80,7 @@ napi_value MyObject::New(napi_env env, napi_callback_info info) {
8080
napi_value MyObject::GetValue(napi_env env, napi_callback_info info) {
8181
napi_value _this;
8282
NAPI_CALL(env,
83-
napi_get_cb_info(env, info, nullptr, nullptr, &_this, nullptr));
83+
napi_get_cb_info(env, info, nullptr, nullptr, &_this, nullptr));
8484

8585
MyObject* obj;
8686
NAPI_CALL(env, napi_unwrap(env, _this, reinterpret_cast<void**>(&obj)));
@@ -108,7 +108,7 @@ napi_value MyObject::SetValue(napi_env env, napi_callback_info info) {
108108
napi_value MyObject::PlusOne(napi_env env, napi_callback_info info) {
109109
napi_value _this;
110110
NAPI_CALL(env,
111-
napi_get_cb_info(env, info, nullptr, nullptr, &_this, nullptr));
111+
napi_get_cb_info(env, info, nullptr, nullptr, &_this, nullptr));
112112

113113
MyObject* obj;
114114
NAPI_CALL(env, napi_unwrap(env, _this, reinterpret_cast<void**>(&obj)));

‎test/addons-napi/7_factory_wrap/binding.cc

+5-5
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ napi_value CreateObject(napi_env env, napi_callback_info info) {
1212
return instance;
1313
}
1414

15-
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
16-
NAPI_CALL_RETURN_VOID(env, MyObject::Init(env));
15+
napi_value Init(napi_env env, napi_value exports) {
16+
NAPI_CALL(env, MyObject::Init(env));
1717

18-
napi_property_descriptor desc =
19-
DECLARE_NAPI_PROPERTY("exports", CreateObject);
20-
NAPI_CALL_RETURN_VOID(env, napi_define_properties(env, module, 1, &desc));
18+
NAPI_CALL(env,
19+
napi_create_function(env, "exports", CreateObject, NULL, &exports));
20+
return exports;
2121
}
2222

2323
NAPI_MODULE(addon, Init)

‎test/addons-napi/7_factory_wrap/myobject.cc

+6-6
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ napi_value MyObject::New(napi_env env, napi_callback_info info) {
5050

5151
obj->env_ = env;
5252
NAPI_CALL(env, napi_wrap(env,
53-
_this,
54-
obj,
55-
MyObject::Destructor,
56-
nullptr, /* finalize_hint */
57-
&obj->wrapper_));
53+
_this,
54+
obj,
55+
MyObject::Destructor,
56+
nullptr, /* finalize_hint */
57+
&obj->wrapper_));
5858

5959
return _this;
6060
}
@@ -80,7 +80,7 @@ napi_status MyObject::NewInstance(napi_env env,
8080
napi_value MyObject::PlusOne(napi_env env, napi_callback_info info) {
8181
napi_value _this;
8282
NAPI_CALL(env,
83-
napi_get_cb_info(env, info, nullptr, nullptr, &_this, nullptr));
83+
napi_get_cb_info(env, info, nullptr, nullptr, &_this, nullptr));
8484

8585
MyObject* obj;
8686
NAPI_CALL(env, napi_unwrap(env, _this, reinterpret_cast<void**>(&obj)));

‎test/addons-napi/8_passing_wrapped/binding.cc

+5-3
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,18 @@ napi_value Add(napi_env env, napi_callback_info info) {
2929
return sum;
3030
}
3131

32-
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
32+
napi_value Init(napi_env env, napi_value exports) {
3333
MyObject::Init(env);
3434

3535
napi_property_descriptor desc[] = {
3636
DECLARE_NAPI_PROPERTY("createObject", CreateObject),
3737
DECLARE_NAPI_PROPERTY("add", Add),
3838
};
3939

40-
NAPI_CALL_RETURN_VOID(env,
41-
napi_define_properties(env, exports, sizeof(desc) / sizeof(*desc), desc));
40+
NAPI_CALL(env,
41+
napi_define_properties(env, exports, sizeof(desc) / sizeof(*desc), desc));
42+
43+
return exports;
4244
}
4345

4446
NAPI_MODULE(addon, Init)

0 commit comments

Comments
 (0)
Please sign in to comment.