Skip to content

Commit

Permalink
node-api: add napi_create_buffer_from_arraybuffer method to create Bu…
Browse files Browse the repository at this point in the history
…ffer from ArrayBuffer
  • Loading branch information
Mert Can Altin committed Aug 22, 2024
1 parent cef2047 commit aaed441
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 6 deletions.
29 changes: 29 additions & 0 deletions doc/api/n-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2696,6 +2696,35 @@ is raised.
JavaScript `TypedArray` objects are described in
[Section 22.2][] of the ECMAScript Language Specification.

#### `napi_create_buffer_from_arraybuffer`

<!-- YAML
added: v22.7.0
napiVersion: 1
-->

```c
napi_status NAPI_CDECL napi_create_buffer_from_arraybuffer(napi_env env,
size_t length,
napi_value arraybuffer,
size_t byte_offset,
napi_value* result)
```

* `[in] env`: The environment that the API is invoked under.
* `[in] length`: The length of the buffer to be created from the `ArrayBuffer`.
* `[in] arraybuffer`: The `ArrayBuffer` from which the buffer will be created.
* `[in] byte_offset`: The byte offset within the `ArrayBuffer` from which to start creating the buffer.
* `[out] result`: A `napi_value` representing a JavaScript `Buffer` object.

Returns `napi_ok` if the API succeeded.

This API creates a JavaScript `Buffer` object from an existing `ArrayBuffer`.
The `Buffer` object is a node-specific class that provides a way to work with binary data directly in JavaScript.

The byte range `[byte_offset, byte_offset + length)` must be within the bounds of the `ArrayBuffer`.
If `byte_offset + length` exceeds the size of the `ArrayBuffer`, a `RangeError` exception is raised.

#### `napi_create_dataview`

<!-- YAML
Expand Down
6 changes: 6 additions & 0 deletions src/js_native_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,12 @@ napi_create_typedarray(napi_env env,
size_t byte_offset,
napi_value* result);
NAPI_EXTERN napi_status NAPI_CDECL
napi_create_buffer_from_arraybuffer(napi_env env,
napi_value arraybuffer,
size_t byte_offset,
size_t byte_length,
napi_value* result);
NAPI_EXTERN napi_status NAPI_CDECL
napi_get_typedarray_info(napi_env env,
napi_value typedarray,
napi_typedarray_type* type,
Expand Down
30 changes: 30 additions & 0 deletions src/js_native_api_v8.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3535,3 +3535,33 @@ napi_status NAPI_CDECL napi_is_detached_arraybuffer(napi_env env,

return napi_clear_last_error(env);
}

napi_status NAPI_CDECL
napi_create_buffer_from_arraybuffer(napi_env env,
size_t length,
napi_value arraybuffer,
size_t byte_offset,
napi_value* result) {
NAPI_PREAMBLE(env);
CHECK_ARG(env, arraybuffer);
CHECK_ARG(env, result);

v8::Local<v8::Value> arraybuffer_value =
v8impl::V8LocalValueFromJsValue(arraybuffer);
if (!arraybuffer_value->IsArrayBuffer()) {
return napi_invalid_arg;
}

v8::Local<v8::ArrayBuffer> arraybuffer_obj =
arraybuffer_value.As<v8::ArrayBuffer>();
if (byte_offset + length > arraybuffer_obj->ByteLength()) {
return napi_throw_range_error(
env, "ERR_OUT_OF_RANGE", "The byte offset + length is out of range");
}

v8::Local<v8::Uint8Array> buffer_view =
v8::Uint8Array::New(arraybuffer_obj, byte_offset, length);

*result = v8impl::JsValueFromV8LocalValue(buffer_view);
return napi_ok;
}
55 changes: 49 additions & 6 deletions test/js-native-api/test_typedarray/test_typedarray.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,15 +230,58 @@ static napi_value IsDetached(napi_env env, napi_callback_info info) {
return result;
}

static napi_value BufferFromArrayBuffer(napi_env env, napi_callback_info info) {
napi_status status;
napi_value arraybuffer;
void* data;
napi_value buffer;
size_t byte_length = 1024;
size_t byte_offset = 0;

status = napi_create_arraybuffer(env, byte_length, &data, &arraybuffer);
NODE_API_ASSERT(env, status == napi_ok, "Failed to create arraybuffer");

status = napi_create_buffer_from_arraybuffer(
env, byte_length, arraybuffer, byte_offset, &buffer);
NODE_API_ASSERT(
env, status == napi_ok, "Failed to create buffer from arraybuffer");

void* buffer_data;
size_t buffer_length;
status = napi_get_buffer_info(env, buffer, &buffer_data, &buffer_length);
NODE_API_ASSERT(env, status == napi_ok, "Failed to get buffer info");
NODE_API_ASSERT(env, buffer_length == byte_length, "Buffer length mismatch");

status = napi_create_buffer_from_arraybuffer(
env, byte_length, arraybuffer, byte_length + 1, &buffer);
NODE_API_ASSERT(env,
status == napi_range_error,
"Expected range error for invalid byte offset");

napi_value non_arraybuffer;
status = napi_create_uint32(env, 123, &non_arraybuffer);
NODE_API_ASSERT(
env, status == napi_ok, "Failed to create non-arraybuffer value");

status = napi_create_buffer_from_arraybuffer(
env, byte_length, non_arraybuffer, byte_offset, &buffer);
NODE_API_ASSERT(env,
status == napi_invalid_arg,
"Expected invalid arg error for non-arraybuffer input");

return NULL;
}

EXTERN_C_START
napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor descriptors[] = {
DECLARE_NODE_API_PROPERTY("Multiply", Multiply),
DECLARE_NODE_API_PROPERTY("External", External),
DECLARE_NODE_API_PROPERTY("NullArrayBuffer", NullArrayBuffer),
DECLARE_NODE_API_PROPERTY("CreateTypedArray", CreateTypedArray),
DECLARE_NODE_API_PROPERTY("Detach", Detach),
DECLARE_NODE_API_PROPERTY("IsDetached", IsDetached),
DECLARE_NODE_API_PROPERTY("Multiply", Multiply),
DECLARE_NODE_API_PROPERTY("External", External),
DECLARE_NODE_API_PROPERTY("NullArrayBuffer", NullArrayBuffer),
DECLARE_NODE_API_PROPERTY("CreateTypedArray", CreateTypedArray),
DECLARE_NODE_API_PROPERTY("Detach", Detach),
DECLARE_NODE_API_PROPERTY("IsDetached", IsDetached),
DECLARE_NODE_API_PROPERTY("BufferFromArrayBuffer", BufferFromArrayBuffer),
};

NODE_API_CALL(env, napi_define_properties(
Expand Down

0 comments on commit aaed441

Please sign in to comment.