Skip to content

Support for ArrayBuffer::isMutableBuffer() and ArrayBuffer::getMutableBuffer() #1578

Open
@mrousavy

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:

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.

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions