From e29b2c0ed130fcee48671400877f0175230e1636 Mon Sep 17 00:00:00 2001 From: Michael Dawson Date: Tue, 25 Oct 2022 17:39:41 -0400 Subject: [PATCH] node-api: handle no support for external buffers Refs: https://github.com/electron/electron/issues/35801 Refs: https://github.com/nodejs/abi-stable-node/issues/441 Electron recently dropped support for external buffers. Provide a way for addon authors to: - hide the methods to create external buffers so they can avoid using them if they want the broadest compatibility. - call the methods that create external buffers at runtime to check if external buffers are supported and either use them or not based on the return code. Signed-off-by: Michael Dawson --- doc/api/n-api.md | 13 +++++++++++++ src/js_native_api.h | 2 ++ src/js_native_api_types.h | 3 ++- src/node_api.cc | 4 ++++ src/node_api.h | 2 ++ 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 3a2b9bceb2ab64..b450717f4d5232 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -2362,6 +2362,19 @@ This API allocates a JavaScript value with external data attached to it. This is used to pass external data through JavaScript code, so it can be retrieved later by native code using [`napi_get_value_external`][]. +**Some runtimes other than Node.ja hasve dropped support for external buffers**. +On runtimes other than Node.js this method may return +`napi_no_external_buffers_allowed` to indicate that external +buffers are not supported. One such runtime is electron as +described in this issue +[electron/issues/35801](https://github.com/electron/electron/issues/35801). + +In order to maintain broadest compatibility with all runtimes +you may define `NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED` in your addon before +includes for the node-api headers. Doing so will hide the 2 methods +that create external buffers. This will ensure a compilation error +occurs if you accidentally use one of these methods. + The API adds a `napi_finalize` callback which will be called when the JavaScript object just created is ready for garbage collection. It is similar to `napi_wrap()` except that: diff --git a/src/js_native_api.h b/src/js_native_api.h index 220d140d4bfe9a..9c99813f4fc88e 100644 --- a/src/js_native_api.h +++ b/src/js_native_api.h @@ -402,12 +402,14 @@ NAPI_EXTERN napi_status NAPI_CDECL napi_create_arraybuffer(napi_env env, void** data, napi_value* result); NAPI_EXTERN napi_status NAPI_CDECL +#ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED napi_create_external_arraybuffer(napi_env env, void* external_data, size_t byte_length, napi_finalize finalize_cb, void* finalize_hint, napi_value* result); +#endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED NAPI_EXTERN napi_status NAPI_CDECL napi_get_arraybuffer_info( napi_env env, napi_value arraybuffer, void** data, size_t* byte_length); NAPI_EXTERN napi_status NAPI_CDECL napi_is_typedarray(napi_env env, diff --git a/src/js_native_api_types.h b/src/js_native_api_types.h index 376930ba4a3220..517614950a90f7 100644 --- a/src/js_native_api_types.h +++ b/src/js_native_api_types.h @@ -98,7 +98,8 @@ typedef enum { napi_date_expected, napi_arraybuffer_expected, napi_detachable_arraybuffer_expected, - napi_would_deadlock // unused + napi_would_deadlock, // unused + napi_no_external_buffers_allowed } napi_status; // Note: when adding a new enum value to `napi_status`, please also update // * `const int last_status` in the definition of `napi_get_last_error_info()' diff --git a/src/node_api.cc b/src/node_api.cc index 48b94a7c12873c..792322634d2c2b 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -950,6 +950,10 @@ napi_status NAPI_CDECL napi_create_external_buffer(napi_env env, NAPI_PREAMBLE(env); CHECK_ARG(env, result); +#if defined(V8_COMPRESS_POINTERS_IN_SHARED_CAGE) + return napi_set_last_error(env, napi_no_external_buffers_allowed); +#endif + v8::Isolate* isolate = env->isolate; // The finalizer object will delete itself after invoking the callback. diff --git a/src/node_api.h b/src/node_api.h index 3dc17f31f68778..8e6af2cf284e85 100644 --- a/src/node_api.h +++ b/src/node_api.h @@ -153,6 +153,7 @@ NAPI_EXTERN napi_status NAPI_CDECL napi_create_buffer(napi_env env, size_t length, void** data, napi_value* result); +#ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED NAPI_EXTERN napi_status NAPI_CDECL napi_create_external_buffer(napi_env env, size_t length, @@ -160,6 +161,7 @@ napi_create_external_buffer(napi_env env, napi_finalize finalize_cb, void* finalize_hint, napi_value* result); +#endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED NAPI_EXTERN napi_status NAPI_CDECL napi_create_buffer_copy(napi_env env, size_t length, const void* data,