Skip to content

Commit d3de1ed

Browse files
anthony-tuiningaMylesBorins
authored andcommittedApr 16, 2019
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 705935d commit d3de1ed

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
@@ -1993,12 +1993,15 @@ napi_status napi_create_string_latin1(napi_env env,
19931993
napi_value* result) {
19941994
CHECK_ENV(env);
19951995
CHECK_ARG(env, result);
1996+
RETURN_STATUS_IF_FALSE(env,
1997+
(length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1998+
napi_invalid_arg);
19961999

19972000
auto isolate = env->isolate;
19982001
auto str_maybe =
19992002
v8::String::NewFromOneByte(isolate,
20002003
reinterpret_cast<const uint8_t*>(str),
2001-
v8::NewStringType::kInternalized,
2004+
v8::NewStringType::kNormal,
20022005
length);
20032006
CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
20042007

@@ -2012,11 +2015,18 @@ napi_status napi_create_string_utf8(napi_env env,
20122015
napi_value* result) {
20132016
CHECK_ENV(env);
20142017
CHECK_ARG(env, result);
2018+
RETURN_STATUS_IF_FALSE(env,
2019+
(length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
2020+
napi_invalid_arg);
20152021

2016-
v8::Local<v8::String> s;
2017-
CHECK_NEW_FROM_UTF8_LEN(env, s, str, length);
2018-
2019-
*result = v8impl::JsValueFromV8LocalValue(s);
2022+
auto isolate = env->isolate;
2023+
auto str_maybe =
2024+
v8::String::NewFromUtf8(isolate,
2025+
str,
2026+
v8::NewStringType::kNormal,
2027+
static_cast<int>(length));
2028+
CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
2029+
*result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
20202030
return napi_clear_last_error(env);
20212031
}
20222032

@@ -2026,12 +2036,15 @@ napi_status napi_create_string_utf16(napi_env env,
20262036
napi_value* result) {
20272037
CHECK_ENV(env);
20282038
CHECK_ARG(env, result);
2039+
RETURN_STATUS_IF_FALSE(env,
2040+
(length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
2041+
napi_invalid_arg);
20292042

20302043
auto isolate = env->isolate;
20312044
auto str_maybe =
20322045
v8::String::NewFromTwoByte(isolate,
20332046
reinterpret_cast<const uint16_t*>(str),
2034-
v8::NewStringType::kInternalized,
2047+
v8::NewStringType::kNormal,
20352048
length);
20362049
CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
20372050

‎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
@@ -215,6 +215,32 @@ napi_value TestLargeUtf8(napi_env env, napi_callback_info info) {
215215
return output;
216216
}
217217

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

231259
NAPI_CALL(env, napi_define_properties(

0 commit comments

Comments
 (0)
Please sign in to comment.