Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

node-api: add napi_create_buffer_from_arraybuffer method #54505

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

mertcanaltin
Copy link
Member

introduces a new N-API method napi_create_buffer_from_arraybuffer that allows the creation of a Buffer from an ArrayBuffer. This new method provides functionality similar to napi_create_typedarray, enabling developers to specify a byte offset and length to create a Buffer from a portion of the ArrayBuffer. This feature addresses the limitation where it was previously not possible to create a Buffer directly from an ArrayBuffer using N-API.

Closes: #54440

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/node-api

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. needs-ci PRs that need a full CI run. node-api Issues and PRs related to the Node-API. labels Aug 22, 2024
@mertcanaltin mertcanaltin changed the title node-api: add napi_create_buffer_from_arraybuffer method to create Bu… node-api: add napi_create_buffer_from_arraybuffer method Aug 22, 2024
@mertcanaltin mertcanaltin added the buffer Issues and PRs related to the buffer subsystem. label Aug 22, 2024
src/js_native_api_v8.cc Outdated Show resolved Hide resolved
@mertcanaltin
Copy link
Member Author

mertcanaltin commented Aug 22, 2024

I made make in my local environment and ran the make only-tesy command and saw that it passed the build and tests, I will check the places that give errors again.

Copy link
Member

@ronag ronag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is actually creating a node buffer.

doc/api/n-api.md Outdated Show resolved Hide resolved
Copy link
Member

@ronag ronag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but would like another review from someone more familiar with this part of the code.

@ronag ronag self-requested a review August 23, 2024 05:00
Copy link

codecov bot commented Aug 23, 2024

Codecov Report

Attention: Patch coverage is 50.00000% with 8 lines in your changes missing coverage. Please review.

Project coverage is 88.41%. Comparing base (aac8ba7) to head (6c4e386).
Report is 97 commits behind head on main.

Files with missing lines Patch % Lines
src/node_api.cc 50.00% 3 Missing and 5 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #54505      +/-   ##
==========================================
+ Coverage   88.24%   88.41%   +0.16%     
==========================================
  Files         651      652       +1     
  Lines      183856   186628    +2772     
  Branches    35853    36065     +212     
==========================================
+ Hits       162251   165001    +2750     
+ Misses      14896    14885      -11     
- Partials     6709     6742      +33     
Files with missing lines Coverage Δ
src/node_api.cc 76.26% <50.00%> (-0.53%) ⬇️

... and 135 files with indirect coverage changes

@legendecas
Copy link
Member

legendecas commented Aug 23, 2024

@ronag would you mind sharing a use case for this method? Does https://nodejs.org/api/n-api.html#napi_create_typedarray work for the use case?

We talked about this in Node-API meeting, a new node-api can not be easily changed or deprecated, a concrete use case would really help us understand the necessity to add the new API and if the API interface sufficient.

src/js_native_api.h Outdated Show resolved Hide resolved
@ronag
Copy link
Member

ronag commented Aug 23, 2024

@ronag would you mind sharing a use case for this method? Does https://nodejs.org/api/n-api.html#napi_create_typedarray work for the use case?

We talked about this in Node-API meeting, a new node-api can not be easily changed or deprecated, a concrete use case would really help us understand the necessity to add the new API and if the API interface sufficient.

It doesn't work if I need to return node buffers in the js api. I guess I could change the prototype in js but that seems a bit ugly.

@ronag
Copy link
Member

ronag commented Aug 26, 2024

@nodejs/node-api

ronag added a commit to nxtedition/rocks-level that referenced this pull request Aug 26, 2024
@mertcanaltin
Copy link
Member Author

I wonder if you have a suggestion for incompatible signatures here, I tried const but I got an error again

gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
  CC(target) Release/obj.target/test_buffer/test_buffer.o
../test_buffer.c:47:42: warning: incompatible function pointer types passing 'void (napi_env, void *, void *)' (aka 'void (struct napi_env__ *, void *, void *)') to parameter of type 'node_api_basic_finalize' (aka 'void (*)(const struct napi_env__ *, void *, void *)') [-Wincompatible-function-pointer-types]
          env, sizeof(theText), theCopy, deleteTheText,
                                         ^~~~~~~~~~~~~
../../../js-native-api/common.h:90:27: note: expanded from macro 'NODE_API_CALL'
  NODE_API_CALL_BASE(env, the_call, NULL)
                          ^~~~~~~~
../../../js-native-api/common.h:74:10: note: expanded from macro 'NODE_API_CALL_BASE'
    if ((the_call) != napi_ok) {                                         \
         ^~~~~~~~
/Users/mert/Library/Caches/node-gyp/20.17.0/include/node/node_api.h:134:53: note: passing argument to parameter 'finalize_cb' here
                            node_api_basic_finalize finalize_cb,
                                                    ^
../test_buffer.c:106:49: warning: incompatible function pointer types passing 'void (napi_env, void *, void *)' (aka 'void (struct napi_env__ *, void *, void *)') to parameter of type 'node_api_basic_finalize' (aka 'void (*)(const struct napi_env__ *, void *, void *)') [-Wincompatible-function-pointer-types]
          env, sizeof(theText), (void*)theText, noopDeleter,
                                                ^~~~~~~~~~~
../../../js-native-api/common.h:90:27: note: expanded from macro 'NODE_API_CALL'
  NODE_API_CALL_BASE(env, the_call, NULL)
                          ^~~~~~~~
../../../js-native-api/common.h:74:10: note: expanded from macro 'NODE_API_CALL_BASE'
    if ((the_call) != napi_ok) {                                         \
         ^~~~~~~~
/Users/mert/Library/Caches/node-gyp/20.17.0/include/node/node_api.h:134:53: note: passing argument to parameter 'finalize_cb' here
                            node_api_basic_finalize finalize_cb,
                                                    ^
2 warnings generated.
  SOLINK_MODULE(target) Release/test_buffer.node
  CC(target) Release/obj.target/test_finalizer/test_finalizer.o
  SOLINK_MODULE(target) Release/test_finalizer.node
gyp info ok 

@legendecas
Copy link
Member

legendecas commented Sep 26, 2024

The type of the first argument of a finalizer with NAPI_EXPERIMENTAL should be node_api_basic_env: https://nodejs.org/api/n-api.html#node_api_basic_finalize, and per suggestion #54505 (comment) for `node_api_post_finalizer.

@vmoroz
Copy link
Member

vmoroz commented Sep 26, 2024

Just to be on the same page: my suggestion regarding the use of node_api_post_finalizer was in the context of the failing tests caused by the new NAPI_EXPERIMENTAL in the gyp file. The malignDeleter function in the test_finalizer.c file calls functions like napi_get_global that cause the crash in the new immediate finalizers while running tests. To address this issue the code in the malignDeleter function must be changed to a call to a single function node_api_post_finalizer which would call a new function with the body of the former malignDeleter function.

I made an update @vmoroz

@mertcanaltin , @legendecas , looking back at this code I think I was completely wrong about the test_finalizer.c.
I did not realize that it is a different DLL.
I previously saw the issue in the unit test related to the finalizers, and then lately found the finalizer to be only in the test_finalizer.c, and wrongly assumed that the issue is in this file instead of it being in the original file where it was then removed.
Sorry about that.
It must be OK to keep the change as long as the finalizers signature match to the declaration in the js_native_api.h.
Otherwise, you could rollback changes in the test_finalizer.c and remove the NAPI_EXPERIMENTAL for the finalizer test.

@vmoroz
Copy link
Member

vmoroz commented Sep 26, 2024

The type of the first argument of a finalizer with NAPI_EXPERIMENTAL should be node_api_basic_env: https://nodejs.org/api/n-api.html#node_api_basic_finalize, and per suggestion #54505 (comment) for `node_api_post_finalizer.

It is interesting that MSVC compiler does not have any issues compiling the code.
The issue shows up only for the Linux and Mac compilers.
MSVC does not implement the true "C" compilation and it seems that the new basic env type trick does not work for it.

@mertcanaltin
Copy link
Member Author

I made the signature definitions 🚀

@mertcanaltin
Copy link
Member Author

I set napi signature but get call to undeclared function error, I wonder if anyone has a comment on this

gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
  CC(target) Release/obj.target/test_buffer/test_buffer.o
../test_buffer.c:148:12: error: call to undeclared function 'node_api_create_buffer_from_arraybuffer'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
  status = node_api_create_buffer_from_arraybuffer(
           ^
../test_buffer.c:148:12: note: did you mean 'napi_create_external_arraybuffer'?
/Users/mert/Library/Caches/node-gyp/20.17.0/include/node/js_native_api.h:433:1: note: 'napi_create_external_arraybuffer' declared here
napi_create_external_arraybuffer(napi_env env,
^
1 error generated.
make: *** [Release/obj.target/test_buffer/test_buffer.o] Error 1

@mertcanaltin
Copy link
Member Author

I set napi signature but get call to undeclared function error, I wonder if anyone has a comment on this

gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]

  CC(target) Release/obj.target/test_buffer/test_buffer.o

../test_buffer.c:148:12: error: call to undeclared function 'node_api_create_buffer_from_arraybuffer'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]

  status = node_api_create_buffer_from_arraybuffer(

           ^

../test_buffer.c:148:12: note: did you mean 'napi_create_external_arraybuffer'?

/Users/mert/Library/Caches/node-gyp/20.17.0/include/node/js_native_api.h:433:1: note: 'napi_create_external_arraybuffer' declared here

napi_create_external_arraybuffer(napi_env env,

^

1 error generated.

make: *** [Release/obj.target/test_buffer/test_buffer.o] Error 1

hmm I'm getting errors on my local, but here the tests seem to have passed 🤔

test/js-native-api/common.h Outdated Show resolved Hide resolved
@vmoroz
Copy link
Member

vmoroz commented Oct 1, 2024

hmm I'm getting errors on my local, but here the tests seem to have passed 🤔

I suspect you are running gyp for the installed Node.js instance instead of the one built on your machine. This is why it cannot find the new function that is added in your PR.

I typically build the tests on Windows with vcbuild.bat and then iterate on them inside of Visual Studio. To run them using the built Node.js instance I usually do out\Debug\node.exe test\node-api\test_buffer\test.js. I.e. the key here is to use the Node.js instance from the out folder. I guess on Mac it can be done in a similar way.

@mertcanaltin
Copy link
Member Author

I suspect you are running gyp for the installed Node.js instance instead of the one built on your machine. This is why it cannot find the new function that is added in your PR.

I typically build the tests on Windows with vcbuild.bat and then iterate on them inside of Visual Studio. To run them using the built Node.js instance I usually do out\Debug\node.exe test\node-api\test_buffer\test.js. I.e. the key here is to use the Node.js instance from the out folder. I guess on Mac it can be done in a similar way.

this worked very well thank you very much

src/js_native_api.h Outdated Show resolved Hide resolved
src/node_api.cc Show resolved Hide resolved
test/js-native-api/common.h Outdated Show resolved Hide resolved
Copy link
Member

@vmoroz vmoroz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
buffer Issues and PRs related to the buffer subsystem. c++ Issues and PRs that require attention from people who are familiar with C++. needs-ci PRs that need a full CI run. node-api Issues and PRs related to the Node-API.
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

napi is missing method to create buffer from ArrayBuffer
10 participants