node-api: enable napi_ref for all value types
The issue
In the Node-API the napi_value
exists only on the call stack. When the value needs to be persisted after the call stack is unwinded, we can use the napi_ref
. Currently the napi_ref
keeps napi_value
only for napi_object
, napi_function
, napi_external
, and napi_symbol
types because napi_ref
must support weak pointer semantic. Thus, there was a decision to not keep persistent values for other types such as napi_string
or napi_number
. Though, the napi_symbol
cannot have the weak semantic, but we still can have a napi_ref
for it.
Solution
In this PR we enable use of napi_ref
for strong references to all napi_value
types. Though, only references for napi_object
, napi_external
, and napi_function
types could have the true weak reference semantic. These three types could be collected by GC when the ref count is 0, while other types cannot be collected because they are always string references. To keep the backward compatibility, this PR enables the new behavior under a special node_api_features
bit flag node_api_feature_reference_all_types
. The node_api_features
are being introduced in this PR.
The new node_api_features
allow changing internal behavior of existing Node-API functions.
We pass a node_api_features
pointer to the napi_module
struct in the NAPI_MODULE_X
macro. This macro is used for the module registration. If the module is initialized without using this macro, then there will be no features selected and the module will use the node_api_feature_none
.
Each Node-API version is going to define its own default set of features. For the current version it can be accessed using node_api_default_features
. A module can override the set of its enabled features by adding NODE_API_CUSTOM_FEATURES
definition to the .gyp
file and then setting the value of the global node_api_module_features
variable. To check enabled features, use the node_api_is_feature_enabled
function.
For example, to disable node_api_feature_reference_all_types
we can exclude its bit from the node_api_default_features
:
node_api_features node_api_module_features =
node_api_default_features & ~node_api_feature_reference_all_types;
Documentation
The n-api.md
documentation is updated with the info about node_api_features
enum and the node_api_is_feature_enabled
function.
Testing
Added three new tests:
-
js-native-api/test_reference_all_types
. The test storesnapi_value
of different types and then retrieves them for the strong and weaknapi_ref
references. -
node-api/test_init_reference_all_types
. The same as the previous test, but it usesNAPI_MODULE_INIT
macro to initialize module instead ofNAPI_MODULE
. This is to verify that bothNAPI_MODULE
andNAPI_MODULE_INIT
macro support feature specification. -
node-api/test_init_reference_obj_only
. To test old references behavior and module initialization withNAPI_MODULE_INIT
macro.
The test_reference
and test_init_reference_obj_only
disable the node_api_feature_reference_all_types
feature and make sure that the old napi_ref
behavior continues to work.
The NAPI_EXPERIMENTAL
is added to common.h
and entry_point.c
in test/js-native-api
folder to make sure that the js-native-api
tests always use the latest Node-API version features.