Skip to content
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

napi: add support for napi_set_named_property_len function #52984

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

mertcanaltin
Copy link
Member

This pull request addresses issue #52979, where developers encounter issues with the napi_set_named_property function treating '\0' characters as terminators rather than values. To solve this problem, the napi_set_named_property_len function has been introduced as a new variant. This function accepts a string and its length, allowing developers to use '\0' characters as values when setting named properties on JavaScript objects.

in addition notes:

This change includes updates to the documentation to reflect the addition of the new function.
Tests have been added to ensure the correctness of the implementation.
The stability of this feature is marked as experimental and may change in future releases.

Test Plan:

Run existing unit tests to ensure no regressions occur.
Add new unit tests specifically targeting the behavior of the napi_set_named_property_len function.
Manually test the functionality by integrating it into existing code where '\0' characters are used as property values.

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. needs-ci PRs that need a full CI run. node-api Issues and PRs related to the Node-API. labels May 14, 2024
@mertcanaltin mertcanaltin requested a review from anonrig May 14, 2024 18:56
doc/api/n-api.md Outdated
flexible property names, especially when dealing with virtual module
names or other scenarios where '\0' characters are used as part of the name.

Note: This function is experimental and its stability may change in future releases.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there's a stability banner, this would seem to be superfluous. Maybe remove it?

Copy link
Member

@legendecas legendecas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer adding node_api_set_named_property(napi_env env, napi_value object, const char* utf8name, size_t name_length, napi_value value) (which is the new naming pattern) and deprecating napi_set_named_property once the new one promoted to stable.

Copy link
Member

@legendecas legendecas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for working on this. Request for change on implementation as comments above.

test/js-native-api/test_string/test_string.c Outdated Show resolved Hide resolved
@mertcanaltin mertcanaltin changed the title napi: dd support for napi_set_named_property_len function napi: add support for napi_set_named_property_len function May 15, 2024
doc/api/n-api.md Outdated
@@ -3134,6 +3134,35 @@ overhead in creating/storing strings with this method.
The JavaScript `string` type is described in
[Section 6.1.4][] of the ECMAScript Language Specification.

#### `napi_set_named_property_len`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New APIs should have the prefix node_api_*, i.e. this should be renamed to node_api_set_named_property_len.

doc/api/n-api.md Outdated Show resolved Hide resolved
src/js_native_api.h Show resolved Hide resolved
mertcanaltin and others added 2 commits May 17, 2024 17:40
Co-authored-by: Gabriel Schulhof <gabrielschulhof@gmail.com>
Co-authored-by: Gabriel Schulhof <gabrielschulhof@gmail.com>
@gabrielschulhof
Copy link
Contributor

@mertcanaltin we discussed this PR at today's Node-API team meeting. We have come to the conclusion that, although this new API adds convenience for developers, it actually encourages a pattern of runtime inefficiency by making it easy to create properties with keys for which the engine is unaware that they are not just regular strings but property keys, and thus it doesn't optimize them.

We believe it would be better to pivot this PR to creating additional variants of node_api_create_property_key_utf16 for the other two string encodings because it would encourage add-on maintainers to create property keys that are treated efficiently by the engine, thus increasing the performance of code that has to create large numbers of objects.

In addition, it would be advisable for add-on maintainers to create a property key once, and then reuse the resulting napi_value in subsequent calls to napi_set_property and/or napi_define_properties in order to avoid repeatedly creating the same string.

This is certainly less convenient for those writing the code, however, it increases the performance of the resulting add-ons.

@mertcanaltin
Copy link
Member Author

mertcanaltin commented May 17, 2024

@mertcanaltin we discussed this PR at today's Node-API team meeting. We have come to the conclusion that, although this new API adds convenience for developers, it actually encourages a pattern of runtime inefficiency by making it easy to create properties with keys for which the engine is unaware that they are not just regular strings but property keys, and thus it doesn't optimize them.

We believe it would be better to pivot this PR to creating additional variants of node_api_create_property_key_utf16 for the other two string encodings because it would encourage add-on maintainers to create property keys that are treated efficiently by the engine, thus increasing the performance of code that has to create large numbers of objects.

In addition, it would be advisable for add-on maintainers to create a property key once, and then reuse the resulting napi_value in subsequent calls to napi_set_property and/or napi_define_properties in order to avoid repeatedly creating the same string.

This is certainly less convenient for those writing the code, however, it increases the performance of the resulting add-ons.

First of all, thank you very much for your review and support, do you think I can continue to develop this pr I would be very happy if you have any suggestions ❤️🙏 @gabrielschulhof

@mertcanaltin
Copy link
Member Author

mertcanaltin commented May 17, 2024

I created a node_api_create_property_key_utf8 based on what you said

node_api_create_proper-
ty_key_utf8
node_api
_create_proper-
ty_key_ascil

I wonder if we can get a performance as you say by making different string encodings?

@@ -118,6 +118,22 @@ NAPI_EXTERN napi_status NAPI_CDECL node_api_create_property_key_utf16(
napi_env env, const char16_t* str, size_t length, napi_value* result);
#endif // NAPI_EXPERIMENTAL

#ifdef NAPI_EXPERIMENTAL
#define NODE_API_EXPERIMENTAL_HAS_PROPERTY_KEYS
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defining the same macro twice will cause compiler warnings or errors. Please group the new node_api_create_property_key_utf8 API with the previous node_api_create_property_key_utf16.

@@ -1718,6 +1718,46 @@ napi_status NAPI_CDECL node_api_create_property_key_utf16(napi_env env,
});
}

napi_status node_api_create_property_key_utf8(napi_env env,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please implement the node_api_create_property_key_utf8 the same way as the node_api_create_property_key_utf16 implemented using the v8impl::NewString helper function.
The current implementation is missing a few checks and uses v8::NewStringType::kNormal instead of v8::NewStringType::kInternalized which differentiates V8 normal string creation from a V8 string used as a property key.

@@ -310,6 +310,93 @@ static napi_value TestPropertyKeyUtf16AutoLength(napi_env env,
auto_length);
}

static napi_value TestPropertyKeyUtf8(napi_env env, napi_callback_info info) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great to follow the same pattern for test implementation as TestPropertyKeyUtf16 and TestPropertyKeyUtf16AutoLength

@@ -310,6 +310,93 @@ static napi_value TestPropertyKeyUtf16AutoLength(napi_env env,
auto_length);
}

static napi_value TestPropertyKeyUtf8(napi_env env, napi_callback_info info) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new test methods must be exposed to JS in the end of this code file and then used from JS test code.

@vmoroz
Copy link
Member

vmoroz commented May 24, 2024

I wonder if we can get a performance as you say by making different string encodings?

@mertcanaltin , there are a few Node-API benchmarks here: https://github.com/nodejs/node/tree/main/benchmark/napi. A new one can be created to benchmark different ways to set and get property values.
Note that the true advantage from using node_api_create_property_key_utf8 and node_api_create_property_key_utf16 must be seen only when the same property key is reused for setting/getting a property multiple times.

@KevinEady
Copy link
Contributor

I am hesitant of adding these APIs, as the functionality to do what you want already exists using both node_api_create_property_key_utf16() and napi_set_property(). I do not follow the argument of "an extra napi call" as outlined in #52979 (comment), as the team discussed it in a Node-API meeting and decided the additional call would be minimal overhead.

Adding new APIs has more overreaching effects than just Node.js itself, as other JavaScript engines must implement the new APIs as well.

Since this functionality already exists and can be performed in a trivial manner, I 👎 this addition.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. needs-ci PRs that need a full CI run. node-api Issues and PRs related to the Node-API.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants