From c6e65d5dd2845f4094043a7b6eb9e13d7453faa8 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Thu, 9 Nov 2023 14:45:55 -0800 Subject: [PATCH] Update For V8 Memory Cage (#476) --- source/http_stream.c | 2 +- source/module.c | 42 ++++++++++++++++++++++++++++++--- source/module.h | 19 +++++++++++++++ source/mqtt_client_connection.c | 8 +++++-- 4 files changed, 65 insertions(+), 6 deletions(-) diff --git a/source/http_stream.c b/source/http_stream.c index 23923a196..5921b90ce 100644 --- a/source/http_stream.c +++ b/source/http_stream.c @@ -140,7 +140,7 @@ static void s_on_body_call(napi_env env, napi_value on_body, void *context, void AWS_NAPI_ENSURE( env, - napi_create_external_arraybuffer( + aws_napi_create_external_arraybuffer( env, args->chunk.buffer, args->chunk.len, s_external_arraybuffer_finalizer, args, ¶ms[0])); AWS_NAPI_ENSURE( diff --git a/source/module.c b/source/module.c index 40309cd01..c4bb91337 100644 --- a/source/module.c +++ b/source/module.c @@ -268,9 +268,10 @@ int aws_napi_attach_object_property_binary_as_finalizable_external( } napi_value napi_binary = NULL; + AWS_NAPI_ENSURE( env, - napi_create_external_arraybuffer( + aws_napi_create_external_arraybuffer( env, data_buffer->buffer, data_buffer->len, @@ -831,7 +832,6 @@ const char *aws_napi_status_to_str(napi_status status) { case napi_callback_scope_mismatch: reason = "napi_callback_scope_mismatch"; break; -#if NAPI_VERSION >= 3 case napi_queue_full: reason = "napi_queue_full"; break; @@ -841,7 +841,9 @@ const char *aws_napi_status_to_str(napi_status status) { case napi_bigint_expected: reason = "napi_bigint_expected"; break; -#endif + case napi_no_external_buffers_allowed: + reason = "napi_no_external_buffers_allowed"; + break; } return reason; } @@ -931,6 +933,40 @@ static void s_handle_failed_callback(napi_env env, napi_value function, napi_sta } } +napi_status aws_napi_create_external_arraybuffer( + napi_env env, + void *external_data, + size_t byte_length, + napi_finalize finalize_cb, + void *finalize_hint, + napi_value *result) { + + napi_status external_buffer_status = + napi_create_external_arraybuffer(env, external_data, byte_length, finalize_cb, finalize_hint, result); + + if (external_buffer_status == napi_no_external_buffers_allowed) { + + // The external buffer is disabled, manually copy the external_data into Node + void *napi_buf_data = NULL; + napi_status create_arraybuffer_status = napi_create_arraybuffer(env, byte_length, &napi_buf_data, result); + + if (create_arraybuffer_status != napi_ok) { + AWS_NAPI_LOGF_ERROR( + "napi_create_arraybuffer (in aws_napi_create_external_arraybuffer) failed with : %s", + aws_napi_status_to_str(create_arraybuffer_status)); + return create_arraybuffer_status; + } + + memcpy(napi_buf_data, external_data, byte_length); + + // As the data has been copied into the Node, invoke the finalize callback to make sure the + // data is released. + finalize_cb(env, finalize_hint, finalize_hint); + } + + return napi_ok; +} + napi_status aws_napi_dispatch_threadsafe_function( napi_env env, napi_threadsafe_function tsfn, diff --git a/source/module.h b/source/module.h index b9fd2349f..f4d8faa40 100644 --- a/source/module.h +++ b/source/module.h @@ -225,6 +225,25 @@ struct aws_client_bootstrap *aws_napi_get_default_client_bootstrap(void); const char *aws_napi_status_to_str(napi_status status); +/* + * Wrapper around napi_create_external_arraybuffer, + * The function returns `napi_ok` if array buffer is created successfully in nodejs. Otherwise returns the error code. + * The user is responsible to release/proceed the `external_data` if the creation failed. + * + * `aws_napi_create_external_arraybuffer` handles the creation of the arraybuffer from the `external_data`. As + * some runtimes other than Node.js have dropped support for external buffers, the napi function call will fail in such + * case. If the call failed, the function will directly create an arraybuffer in Node and copy the data of external + * buffer into it. Once data copied, the `finalize_cb` will be immediately invoked to release the external data. + * + */ +napi_status aws_napi_create_external_arraybuffer( + napi_env env, + void *external_data, + size_t byte_length, + napi_finalize finalize_cb, + void *finalize_hint, + napi_value *result); + /** * Gets the allocator used to allocate native resources in the node environment, should be used * by all binding code in this extension diff --git a/source/mqtt_client_connection.c b/source/mqtt_client_connection.c index 341c4cfdd..ce5775312 100644 --- a/source/mqtt_client_connection.c +++ b/source/mqtt_client_connection.c @@ -1424,15 +1424,17 @@ static void s_on_publish_call(napi_env env, napi_value on_publish, void *context AWS_NAPI_ENSURE( env, napi_create_string_utf8(env, (const char *)args->topic.buffer, args->topic.len, ¶ms[0])); + AWS_NAPI_ENSURE( env, - napi_create_external_arraybuffer( + aws_napi_create_external_arraybuffer( env, args->payload->buffer, args->payload->len, s_publish_external_arraybuffer_finalizer, args->payload, ¶ms[1])); + AWS_NAPI_ENSURE(env, napi_get_boolean(env, args->dup, ¶ms[2])); AWS_NAPI_ENSURE(env, napi_create_int32(env, args->qos, ¶ms[3])); AWS_NAPI_ENSURE(env, napi_get_boolean(env, args->retain, ¶ms[4])); @@ -1672,15 +1674,17 @@ static void s_on_any_publish_call(napi_env env, napi_value on_publish, void *con AWS_NAPI_ENSURE( env, napi_create_string_utf8(env, aws_string_c_str(args->topic), args->topic->len, ¶ms[0])); + AWS_NAPI_ENSURE( env, - napi_create_external_arraybuffer( + aws_napi_create_external_arraybuffer( env, args->payload->buffer, args->payload->len, s_any_publish_external_arraybuffer_finalizer, args->payload, ¶ms[1])); + AWS_NAPI_ENSURE(env, napi_get_boolean(env, args->dup, ¶ms[2])); AWS_NAPI_ENSURE(env, napi_create_int32(env, args->qos, ¶ms[3])); AWS_NAPI_ENSURE(env, napi_get_boolean(env, args->retain, ¶ms[4]));