emnapi icon indicating copy to clipboard operation
emnapi copied to clipboard

napi_create_arraybuffer problem

Open kmatzen opened this issue 1 year ago • 5 comments

I'm attempting to call napi_create_arraybuffer from https://github.com/nodejs/node-addon-api/blob/294a43f8c6a4c79b3295a8f1b83d4782d44cfe74/napi-inl.h#L1998.

However, writing to the memory pointed to by the output data void pointer does not correctly update the state of the arraybuffer in javascript. I was able to successfully use napi_create_external_arraybuffer from emnapi by passing in the desired buffer during ArrayBuffer construction rather than mutating the allocated buffer after construction.

Any ideas what might be going wrong? I didn't really understand the logic in emnapiExternalMemory.getArrayBufferPointer. It appears to be correct if you want to read the buffer, but since it makes a copy, I don't see how it could properly provide write access to the caller.

According to the napi docs https://nodejs.org/api/n-api.html#napi_create_arraybuffer:

The underlying buffer is optionally returned back to the caller in case the caller wants to directly
manipulate the buffer. This buffer can only be written to directly from native code. 

Thanks!

kmatzen avatar Sep 18 '24 02:09 kmatzen

Actually this is a limitation (https://emnapi-docs.vercel.app/reference/list.html#arraybuffer-related), unlike in native, wasm code can not directly access V8 API so there is no way to "link" the memory of ArrayBuffer (managed by V8) to a char* buffer (wasm memory). you need to use emnapi_sync_memory from C/C++ side or EmscriptenModule.emnapiSyncMemory from JavaScript side to sync ArrayBuffer memory manually

toyobayashi avatar Sep 18 '24 03:09 toyobayashi

Is there any way possible to malloc from the wasm heap the necessary memory and take a view as the ArrayBuffer?

kmatzen avatar Sep 18 '24 22:09 kmatzen

https://github.com/toyobayashi/emnapi/blob/416fa06e992ed1f17ae0bbd760914ddcae3f9397/packages/emnapi/include/node/emnapi.h#L61-L67

toyobayashi avatar Sep 19 '24 01:09 toyobayashi

Fair enough. I was hoping there was a way to simulate the ArrayBuffer since it would be easier to integrate emnapi into another external project without modifying their code to do the memory synchronization. I'll work around emnapi's limitation instead. Thanks!

kmatzen avatar Sep 19 '24 02:09 kmatzen

I have also been wondering if there is a way to simulate an external ArrayBuffer, but the key problem is that the JS engine's memory and wasm memory are isolated from each other. What I can think of is to use WeakMap to associate the simulated ArrayBuffer and wasm memory, but when this simulated ArrayBuffer is passed to other JavaScript APIs, it will not work as expected, for example, new Uint8Array(simulatedArrayBuffer) will return the wrong Uint8Array.

toyobayashi avatar Sep 19 '24 02:09 toyobayashi