Description
Problem
In Nitro, array buffers are supported types for native modules.
Imagine the following native nitro module:
const seedArrayBuffer = myNitroModule.createRandomSeed()
const keyString = myNitroModule.getEncryptionKey(seedArrayBuffer)
On the native side of getEncryptionKey
, we can safely access the ArrayBuffer
's data without any problems just fine because it is synchronous and we are running on the JS thread:
auto arrayBuffer = args[0].getObject(runtime).getArrayBuffer(runtime);
void* data = arrayBuffer.data(runtime);
..but as soon as we make this function asynchronous:
const seedArrayBuffer = myNitroModule.createRandomSeed()
const keyString = await myNitroModule.getEncryptionKey(seedArrayBuffer)
We can no longer safely access the ArrayBuffer
's data because we are running on a separate Thread.
Nitro will convert the
jsi::ArrayBuffer
to a custom Nitro type that basically tells you to not access it on a different Thread and will throw if you try to do so. So the user is always forced to make a copy of the data before switching to a different Thread.
I think it'd be a cool API to get access to the underlying std::shared_ptr<jsi::MutableBuffer>
if it has one (not every ArrayBuffer
is created with one):
auto arrayBuffer = args[0].getObject(runtime).getArrayBuffer(runtime);
auto mutableBuffer = arrayBuffer.getMutableBuffer(runtime);
std::thread([=]() {
void* data = mutableBuffer.data();
});
Note: This could cause data race issues if not used correctly. I think it's up to the user to guard against that (either via Mutexes, or just praying at night that their APIs will not be misused)
Solution
jsi::ArrayBuffer::isMutableBuffer(..)
jsi::ArrayBuffer::getMutableBuffer(..)
jsi::ArrayBuffer::asMutableBuffer(..)
(?)
Additional Context
In Nitro, I currently solved it like this:
- The
nitro::ArrayBuffer
base class - The
nitro::NativeArrayBuffer
class, which allows you to access data from any Thread and is owning - The
nitro::JSArrayBuffer
class, which only allows you to access data on the JS Thread
If I receive an ArrayBuffer
from JS, it is currently always a nitro::JSArrayBuffer
. I would love to look into it and unwrap the jsi::MutableBuffer
from it so I can optionally also pass the user a nitro::NativeArrayBuffer
instead though.