Skip to content

Commit

Permalink
n-api: improve performance creating strings
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
anthony-tuininga authored and MylesBorins committed Apr 5, 2019
1 parent b0b73fa commit 2643801
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 6 deletions.
25 changes: 19 additions & 6 deletions src/node_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2055,12 +2055,15 @@ napi_status napi_create_string_latin1(napi_env env,
napi_value* result) {
CHECK_ENV(env);
CHECK_ARG(env, result);
RETURN_STATUS_IF_FALSE(env,
(length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
napi_invalid_arg);

auto isolate = env->isolate;
auto str_maybe =
v8::String::NewFromOneByte(isolate,
reinterpret_cast<const uint8_t*>(str),
v8::NewStringType::kInternalized,
v8::NewStringType::kNormal,
length);
CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);

Expand All @@ -2074,11 +2077,18 @@ napi_status napi_create_string_utf8(napi_env env,
napi_value* result) {
CHECK_ENV(env);
CHECK_ARG(env, result);
RETURN_STATUS_IF_FALSE(env,
(length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
napi_invalid_arg);

v8::Local<v8::String> s;
CHECK_NEW_FROM_UTF8_LEN(env, s, str, length);

*result = v8impl::JsValueFromV8LocalValue(s);
auto isolate = env->isolate;
auto str_maybe =
v8::String::NewFromUtf8(isolate,
str,
v8::NewStringType::kNormal,
static_cast<int>(length));
CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);
*result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked());
return napi_clear_last_error(env);
}

Expand All @@ -2088,12 +2098,15 @@ napi_status napi_create_string_utf16(napi_env env,
napi_value* result) {
CHECK_ENV(env);
CHECK_ARG(env, result);
RETURN_STATUS_IF_FALSE(env,
(length == NAPI_AUTO_LENGTH) || length <= INT_MAX,
napi_invalid_arg);

auto isolate = env->isolate;
auto str_maybe =
v8::String::NewFromTwoByte(isolate,
reinterpret_cast<const uint16_t*>(str),
v8::NewStringType::kInternalized,
v8::NewStringType::kNormal,
length);
CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure);

Expand Down
8 changes: 8 additions & 0 deletions test/addons-napi/test_string/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,11 @@ assert.strictEqual(test_string.Utf8Length(str6), 14);
assert.throws(() => {
test_string.TestLargeUtf8();
}, /^Error: Invalid argument$/);

assert.throws(() => {
test_string.TestLargeLatin1();
}, /^Error: Invalid argument$/);

assert.throws(() => {
test_string.TestLargeUtf16();
}, /^Error: Invalid argument$/);
28 changes: 28 additions & 0 deletions test/addons-napi/test_string/test_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,32 @@ static napi_value TestLargeUtf8(napi_env env, napi_callback_info info) {
return output;
}

static napi_value TestLargeLatin1(napi_env env, napi_callback_info info) {
napi_value output;
if (SIZE_MAX > INT_MAX) {
NAPI_CALL(env, napi_create_string_latin1(env, "", ((size_t)INT_MAX) + 1, &output));
} else {
// just throw the expected error as there is nothing to test
// in this case since we can't overflow
NAPI_CALL(env, napi_throw_error(env, NULL, "Invalid argument"));
}

return output;
}

static napi_value TestLargeUtf16(napi_env env, napi_callback_info info) {
napi_value output;
if (SIZE_MAX > INT_MAX) {
NAPI_CALL(env, napi_create_string_utf16(env, "", ((size_t)INT_MAX) + 1, &output));
} else {
// just throw the expected error as there is nothing to test
// in this case since we can't overflow
NAPI_CALL(env, napi_throw_error(env, NULL, "Invalid argument"));
}

return output;
}

static napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor properties[] = {
DECLARE_NAPI_PROPERTY("TestLatin1", TestLatin1),
Expand All @@ -227,6 +253,8 @@ static napi_value Init(napi_env env, napi_value exports) {
DECLARE_NAPI_PROPERTY("Utf16Length", Utf16Length),
DECLARE_NAPI_PROPERTY("Utf8Length", Utf8Length),
DECLARE_NAPI_PROPERTY("TestLargeUtf8", TestLargeUtf8),
DECLARE_NAPI_PROPERTY("TestLargeLatin1", TestLargeLatin1),
DECLARE_NAPI_PROPERTY("TestLargeUtf16", TestLargeUtf16),
};

NAPI_CALL(env, napi_define_properties(
Expand Down

0 comments on commit 2643801

Please sign in to comment.