Skip to content

Commit 2643801

Browse files
anthony-tuiningaMylesBorins
authored andcommitted
n-api: improve performance creating strings
Improve performance creating strings using N-API by ensuring that the strings are not internalized. Added test cases for latin-1 and utf-16 strings. PR-URL: #26439 Fixes: #26437 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent b0b73fa commit 2643801

File tree

3 files changed

+55
-6
lines changed

3 files changed

+55
-6
lines changed

src/node_api.cc

+19-6
Original file line numberDiff line numberDiff line change
@@ -2055,12 +2055,15 @@ napi_status napi_create_string_latin1(napi_env env,
20552055
napi_value* result) {
20562056
CHECK_ENV(env);
20572057
CHECK_ARG(env, result);
2058+
RETURN_STATUS_IF_FALSE(env,
2059+
(length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
2060+
napi_invalid_arg);
20582061

20592062
auto isolate = env->isolate;
20602063
auto str_maybe =
20612064
v8::String::NewFromOneByte(isolate,
20622065
reinterpret_cast<const uint8_t*>(str),
2063-
v8::NewStringType::kInternalized,
2066+
v8::NewStringType::kNormal,
20642067
length);
20652068
CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
20662069

@@ -2074,11 +2077,18 @@ napi_status napi_create_string_utf8(napi_env env,
20742077
napi_value* result) {
20752078
CHECK_ENV(env);
20762079
CHECK_ARG(env, result);
2080+
RETURN_STATUS_IF_FALSE(env,
2081+
(length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
2082+
napi_invalid_arg);
20772083

2078-
v8::Local<v8::String> s;
2079-
CHECK_NEW_FROM_UTF8_LEN(env, s, str, length);
2080-
2081-
*result = v8impl::JsValueFromV8LocalValue(s);
2084+
auto isolate = env->isolate;
2085+
auto str_maybe =
2086+
v8::String::NewFromUtf8(isolate,
2087+
str,
2088+
v8::NewStringType::kNormal,
2089+
static_cast<int>(length));
2090+
CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
2091+
*result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
20822092
return napi_clear_last_error(env);
20832093
}
20842094

@@ -2088,12 +2098,15 @@ napi_status napi_create_string_utf16(napi_env env,
20882098
napi_value* result) {
20892099
CHECK_ENV(env);
20902100
CHECK_ARG(env, result);
2101+
RETURN_STATUS_IF_FALSE(env,
2102+
(length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
2103+
napi_invalid_arg);
20912104

20922105
auto isolate = env->isolate;
20932106
auto str_maybe =
20942107
v8::String::NewFromTwoByte(isolate,
20952108
reinterpret_cast<const uint16_t*>(str),
2096-
v8::NewStringType::kInternalized,
2109+
v8::NewStringType::kNormal,
20972110
length);
20982111
CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
20992112

test/addons-napi/test_string/test.js

+8
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,11 @@ assert.strictEqual(test_string.Utf8Length(str6), 14);
7373
assert.throws(() => {
7474
test_string.TestLargeUtf8();
7575
}, /^Error: Invalid argument$/);
76+
77+
assert.throws(() => {
78+
test_string.TestLargeLatin1();
79+
}, /^Error: Invalid argument$/);
80+
81+
assert.throws(() => {
82+
test_string.TestLargeUtf16();
83+
}, /^Error: Invalid argument$/);

test/addons-napi/test_string/test_string.c

+28
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,32 @@ static napi_value TestLargeUtf8(napi_env env, napi_callback_info info) {
216216
return output;
217217
}
218218

219+
static napi_value TestLargeLatin1(napi_env env, napi_callback_info info) {
220+
napi_value output;
221+
if (SIZE_MAX > INT_MAX) {
222+
NAPI_CALL(env, napi_create_string_latin1(env, "", ((size_t)INT_MAX) + 1, &output));
223+
} else {
224+
// just throw the expected error as there is nothing to test
225+
// in this case since we can't overflow
226+
NAPI_CALL(env, napi_throw_error(env, NULL, "Invalid argument"));
227+
}
228+
229+
return output;
230+
}
231+
232+
static napi_value TestLargeUtf16(napi_env env, napi_callback_info info) {
233+
napi_value output;
234+
if (SIZE_MAX > INT_MAX) {
235+
NAPI_CALL(env, napi_create_string_utf16(env, "", ((size_t)INT_MAX) + 1, &output));
236+
} else {
237+
// just throw the expected error as there is nothing to test
238+
// in this case since we can't overflow
239+
NAPI_CALL(env, napi_throw_error(env, NULL, "Invalid argument"));
240+
}
241+
242+
return output;
243+
}
244+
219245
static napi_value Init(napi_env env, napi_value exports) {
220246
napi_property_descriptor properties[] = {
221247
DECLARE_NAPI_PROPERTY("TestLatin1", TestLatin1),
@@ -227,6 +253,8 @@ static napi_value Init(napi_env env, napi_value exports) {
227253
DECLARE_NAPI_PROPERTY("Utf16Length", Utf16Length),
228254
DECLARE_NAPI_PROPERTY("Utf8Length", Utf8Length),
229255
DECLARE_NAPI_PROPERTY("TestLargeUtf8", TestLargeUtf8),
256+
DECLARE_NAPI_PROPERTY("TestLargeLatin1", TestLargeLatin1),
257+
DECLARE_NAPI_PROPERTY("TestLargeUtf16", TestLargeUtf16),
230258
};
231259

232260
NAPI_CALL(env, napi_define_properties(

0 commit comments

Comments
 (0)