Skip to content

Commit 32529a6

Browse files
author
Mert Can Altin
committed
node-api: add napi_create_buffer_from_arraybuffer method
1 parent e70bd47 commit 32529a6

File tree

4 files changed

+108
-0
lines changed

4 files changed

+108
-0
lines changed

doc/api/n-api.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2696,6 +2696,35 @@ is raised.
26962696
JavaScript `TypedArray` objects are described in
26972697
[Section 22.2][] of the ECMAScript Language Specification.
26982698

2699+
#### `napi_create_buffer_from_arraybuffer`
2700+
2701+
<!-- YAML
2702+
added: v22.7.0
2703+
napiVersion: 1
2704+
-->
2705+
2706+
```c
2707+
napi_status NAPI_CDECL napi_create_buffer_from_arraybuffer(napi_env env,
2708+
size_t length,
2709+
napi_value arraybuffer,
2710+
size_t byte_offset,
2711+
napi_value* result)
2712+
```
2713+
2714+
* `[in] env`: The environment that the API is invoked under.
2715+
* `[in] length`: The length of the buffer to be created from the `ArrayBuffer`.
2716+
* `[in] arraybuffer`: The `ArrayBuffer` from which the buffer will be created.
2717+
* `[in] byte_offset`: The byte offset within the `ArrayBuffer` from which to start creating the buffer.
2718+
* `[out] result`: A `napi_value` representing a JavaScript `Buffer` object.
2719+
2720+
Returns `napi_ok` if the API succeeded.
2721+
2722+
This API creates a JavaScript `Buffer` object from an existing `ArrayBuffer`.
2723+
The `Buffer` object is a node-specific class that provides a way to work with binary data directly in JavaScript.
2724+
2725+
The byte range `[byte_offset, byte_offset + length)` must be within the bounds of the `ArrayBuffer`.
2726+
If `byte_offset + length` exceeds the size of the `ArrayBuffer`, a `RangeError` exception is raised.
2727+
26992728
#### `napi_create_dataview`
27002729

27012730
<!-- YAML

src/js_native_api.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,12 @@ napi_create_typedarray(napi_env env,
450450
size_t byte_offset,
451451
napi_value* result);
452452
NAPI_EXTERN napi_status NAPI_CDECL
453+
napi_create_buffer_from_arraybuffer(napi_env env,
454+
napi_value arraybuffer,
455+
size_t byte_offset,
456+
size_t byte_length,
457+
napi_value* result);
458+
NAPI_EXTERN napi_status NAPI_CDECL
453459
napi_get_typedarray_info(napi_env env,
454460
napi_value typedarray,
455461
napi_typedarray_type* type,

src/js_native_api_v8.cc

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3535,3 +3535,33 @@ napi_status NAPI_CDECL napi_is_detached_arraybuffer(napi_env env,
35353535

35363536
return napi_clear_last_error(env);
35373537
}
3538+
3539+
napi_status NAPI_CDECL
3540+
napi_create_buffer_from_arraybuffer(napi_env env,
3541+
size_t length,
3542+
napi_value arraybuffer,
3543+
size_t byte_offset,
3544+
napi_value* result) {
3545+
NAPI_PREAMBLE(env);
3546+
CHECK_ARG(env, arraybuffer);
3547+
CHECK_ARG(env, result);
3548+
3549+
v8::Local<v8::Value> arraybuffer_value =
3550+
v8impl::V8LocalValueFromJsValue(arraybuffer);
3551+
if (!arraybuffer_value->IsArrayBuffer()) {
3552+
return napi_invalid_arg;
3553+
}
3554+
3555+
v8::Local<v8::ArrayBuffer> arraybuffer_obj =
3556+
arraybuffer_value.As<v8::ArrayBuffer>();
3557+
if (byte_offset + length > arraybuffer_obj->ByteLength()) {
3558+
return napi_throw_range_error(
3559+
env, "ERR_OUT_OF_RANGE", "The byte offset + length is out of range");
3560+
}
3561+
3562+
v8::Local<v8::Uint8Array> buffer_view =
3563+
v8::Uint8Array::New(arraybuffer_obj, byte_offset, length);
3564+
3565+
*result = v8impl::JsValueFromV8LocalValue(buffer_view);
3566+
return napi_ok;
3567+
}

test/js-native-api/test_typedarray/test_typedarray.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,48 @@ static napi_value IsDetached(napi_env env, napi_callback_info info) {
230230
return result;
231231
}
232232

233+
static napi_value BufferFromArrayBuffer(napi_env env, napi_callback_info info) {
234+
napi_status status;
235+
napi_value arraybuffer;
236+
void* data;
237+
napi_value buffer;
238+
size_t byte_length = 1024;
239+
size_t byte_offset = 0;
240+
241+
status = napi_create_arraybuffer(env, byte_length, &data, &arraybuffer);
242+
NODE_API_ASSERT(env, status == napi_ok, "Failed to create arraybuffer");
243+
244+
status = napi_create_buffer_from_arraybuffer(
245+
env, byte_length, arraybuffer, byte_offset, &buffer);
246+
NODE_API_ASSERT(
247+
env, status == napi_ok, "Failed to create buffer from arraybuffer");
248+
249+
void* buffer_data;
250+
size_t buffer_length;
251+
status = napi_get_buffer_info(env, buffer, &buffer_data, &buffer_length);
252+
NODE_API_ASSERT(env, status == napi_ok, "Failed to get buffer info");
253+
NODE_API_ASSERT(env, buffer_length == byte_length, "Buffer length mismatch");
254+
255+
status = napi_create_buffer_from_arraybuffer(
256+
env, byte_length, arraybuffer, byte_length + 1, &buffer);
257+
NODE_API_ASSERT(env,
258+
status == napi_range_error,
259+
"Expected range error for invalid byte offset");
260+
261+
napi_value non_arraybuffer;
262+
status = napi_create_uint32(env, 123, &non_arraybuffer);
263+
NODE_API_ASSERT(
264+
env, status == napi_ok, "Failed to create non-arraybuffer value");
265+
266+
status = napi_create_buffer_from_arraybuffer(
267+
env, byte_length, non_arraybuffer, byte_offset, &buffer);
268+
NODE_API_ASSERT(env,
269+
status == napi_invalid_arg,
270+
"Expected invalid arg error for non-arraybuffer input");
271+
272+
return NULL;
273+
}
274+
233275
EXTERN_C_START
234276
napi_value Init(napi_env env, napi_value exports) {
235277
napi_property_descriptor descriptors[] = {
@@ -239,6 +281,7 @@ napi_value Init(napi_env env, napi_value exports) {
239281
DECLARE_NODE_API_PROPERTY("CreateTypedArray", CreateTypedArray),
240282
DECLARE_NODE_API_PROPERTY("Detach", Detach),
241283
DECLARE_NODE_API_PROPERTY("IsDetached", IsDetached),
284+
DECLARE_NODE_API_PROPERTY("BufferFromArrayBuffer", BufferFromArrayBuffer),
242285
};
243286

244287
NODE_API_CALL(env, napi_define_properties(

0 commit comments

Comments
 (0)