Skip to content

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 stores napi_value of different types and then retrieves them for the strong and weak napi_ref references.
  • node-api/test_init_reference_all_types. The same as the previous test, but it uses NAPI_MODULE_INIT macro to initialize module instead of NAPI_MODULE. This is to verify that both NAPI_MODULE and NAPI_MODULE_INIT macro support feature specification.
  • node-api/test_init_reference_obj_only. To test old references behavior and module initialization with NAPI_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.

Merge request reports

Loading