Skip to content

Commit 8e7204e

Browse files
anthony-tuiningaBridgeAR
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 <[email protected]> Reviewed-By: Michael Dawson <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent bf7a52b commit 8e7204e

File tree

3 files changed

+55
-6
lines changed

3 files changed

+55
-6
lines changed

Diff for: src/js_native_api_v8.cc

+19-6
Original file line numberDiff line numberDiff line change
@@ -1315,12 +1315,15 @@ napi_status napi_create_string_latin1(napi_env env,
13151315
napi_value* result) {
13161316
CHECK_ENV(env);
13171317
CHECK_ARG(env, result);
1318+
RETURN_STATUS_IF_FALSE(env,
1319+
(length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1320+
napi_invalid_arg);
13181321

13191322
auto isolate = env->isolate;
13201323
auto str_maybe =
13211324
v8::String::NewFromOneByte(isolate,
13221325
reinterpret_cast<const uint8_t*>(str),
1323-
v8::NewStringType::kInternalized,
1326+
v8::NewStringType::kNormal,
13241327
length);
13251328
CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
13261329

@@ -1334,11 +1337,18 @@ napi_status napi_create_string_utf8(napi_env env,
13341337
napi_value* result) {
13351338
CHECK_ENV(env);
13361339
CHECK_ARG(env, result);
1340+
RETURN_STATUS_IF_FALSE(env,
1341+
(length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1342+
napi_invalid_arg);
13371343

1338-
v8::Local<v8::String> s;
1339-
CHECK_NEW_FROM_UTF8_LEN(env, s, str, length);
1340-
1341-
*result = v8impl::JsValueFromV8LocalValue(s);
1344+
auto isolate = env->isolate;
1345+
auto str_maybe =
1346+
v8::String::NewFromUtf8(isolate,
1347+
str,
1348+
v8::NewStringType::kNormal,
1349+
static_cast<int>(length));
1350+
CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
1351+
*result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
13421352
return napi_clear_last_error(env);
13431353
}
13441354

@@ -1348,12 +1358,15 @@ napi_status napi_create_string_utf16(napi_env env,
13481358
napi_value* result) {
13491359
CHECK_ENV(env);
13501360
CHECK_ARG(env, result);
1361+
RETURN_STATUS_IF_FALSE(env,
1362+
(length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
1363+
napi_invalid_arg);
13511364

13521365
auto isolate = env->isolate;
13531366
auto str_maybe =
13541367
v8::String::NewFromTwoByte(isolate,
13551368
reinterpret_cast<const uint16_t*>(str),
1356-
v8::NewStringType::kInternalized,
1369+
v8::NewStringType::kNormal,
13571370
length);
13581371
CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
13591372

Diff for: test/js-native-api/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$/);

Diff for: test/js-native-api/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
EXTERN_C_START
220246
napi_value Init(napi_env env, napi_value exports) {
221247
napi_property_descriptor properties[] = {
@@ -228,6 +254,8 @@ napi_value Init(napi_env env, napi_value exports) {
228254
DECLARE_NAPI_PROPERTY("Utf16Length", Utf16Length),
229255
DECLARE_NAPI_PROPERTY("Utf8Length", Utf8Length),
230256
DECLARE_NAPI_PROPERTY("TestLargeUtf8", TestLargeUtf8),
257+
DECLARE_NAPI_PROPERTY("TestLargeLatin1", TestLargeLatin1),
258+
DECLARE_NAPI_PROPERTY("TestLargeUtf16", TestLargeUtf16),
231259
};
232260

233261
NAPI_CALL(env, napi_define_properties(

0 commit comments

Comments
 (0)