Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ The following is the documentation for node-addon-api.
- [ClassPropertyDescriptor](class_property_descriptor.md)
- [Buffer](buffer.md)
- [ArrayBuffer](array_buffer.md)
- [SharedArrayBuffer](shared_array_buffer.md)
- [TypedArray](typed_array.md)
- [TypedArrayOf](typed_array_of.md)
- [DataView](dataview.md)
Expand Down
20 changes: 2 additions & 18 deletions doc/array_buffer.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ArrayBuffer

Class `Napi::ArrayBuffer` inherits from class [`Napi::Object`][].
Class `Napi::ArrayBuffer` inherits from class [`Napi::ArrayBufferLike`][].

The `Napi::ArrayBuffer` class corresponds to the
[JavaScript `ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer)
Expand Down Expand Up @@ -128,22 +128,6 @@ Napi::ArrayBuffer::ArrayBuffer(napi_env env, napi_value value);
- `[in] env`: The environment in which to create the `Napi::ArrayBuffer` instance.
- `[in] value`: The `Napi::ArrayBuffer` reference to wrap.

### ByteLength

```cpp
size_t Napi::ArrayBuffer::ByteLength() const;
```

Returns the length of the wrapped data, in bytes.

### Data

```cpp
void* Napi::ArrayBuffer::Data() const;
```

Returns a pointer the wrapped data.

### Detach

```cpp
Expand All @@ -160,6 +144,6 @@ bool Napi::ArrayBuffer::IsDetached() const;

Returns `true` if this `ArrayBuffer` has been detached.

[`Napi::Object`]: ./object.md
[`Napi::ArrayBufferLike`]: ./array_buffer_like.md
[External Buffer]: ./external_buffer.md
[Finalization]: ./finalization.md
27 changes: 27 additions & 0 deletions doc/array_buffer_like.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# ArrayBufferLike

Class `Napi::ArrayBufferLike` inherits from class [`Napi::Object`][].

The `Napi::ArrayBufferLike` class is the base class for [`Napi::ArrayBuffer`][]
and [`Napi::SharedArrayBuffer`][]. It adds common array buffer capabilities to
both. It is an abstract-only base class.

### ByteLength

```cpp
size_t Napi::ArrayBufferLike::ByteLength() const;
```

Returns the length of the wrapped data, in bytes.

### Data

```cpp
void* Napi::ArrayBufferLike::Data() const;
```

Returns a pointer the wrapped data.

[`Napi::ArrayBuffer`]: ./array_buffer.md
[`Napi::Object`]: ./object.md
[`Napi::SharedArrayBuffer`]: ./shared_array_buffer.md
49 changes: 49 additions & 0 deletions doc/shared_array_buffer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# SharedArrayBuffer

Class `Napi::SharedArrayBuffer` inherits from class [`Napi::ArrayBufferLike`][].

The `Napi::SharedArrayBuffer` class corresponds to the
[JavaScript `SharedArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer)
class.

**NOTE**: The support for `Napi::SharedArrayBuffer` is only available when using
`NAPI_EXPERIMENTAL` and building against Node.js headers that support this
feature.

## Methods

### New

Allocates a new `Napi::SharedArrayBuffer` instance with a given length.

```cpp
static Napi::SharedArrayBuffer Napi::SharedArrayBuffer::New(napi_env env, size_t byteLength);
```

- `[in] env`: The environment in which to create the `Napi::SharedArrayBuffer`
instance.
- `[in] byteLength`: The length to be allocated, in bytes.

Returns a new `Napi::SharedArrayBuffer` instance.

### Constructor

Initializes an empty instance of the `Napi::SharedArrayBuffer` class.

```cpp
Napi::SharedArrayBuffer::SharedArrayBuffer();
```

### Constructor

Initializes a wrapper instance of an existing `Napi::SharedArrayBuffer` object.

```cpp
Napi::SharedArrayBuffer::SharedArrayBuffer(napi_env env, napi_value value);
```

- `[in] env`: The environment in which to create the `Napi::SharedArrayBuffer`
instance.
- `[in] value`: The `Napi::SharedArrayBuffer` reference to wrap.

[`Napi::ArrayBufferLike`]: ./array_buffer_like.md
13 changes: 13 additions & 0 deletions doc/value.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,19 @@ bool Napi::Value::IsPromise() const;
Returns `true` if the underlying value is a JavaScript `Napi::Promise` or
`false` otherwise.

### IsSharedArrayBuffer

```cpp
bool Napi::Value::IsSharedArrayBuffer() const;
```

Returns `true` if the underlying value is a JavaScript
`Napi::IsSharedArrayBuffer` or `false` otherwise.

**NOTE**: The support for `Napi::SharedArrayBuffer` is only available when using
`NAPI_EXPERIMENTAL` and building against Node.js headers that support this
feature.

### IsString

```cpp
Expand Down
86 changes: 69 additions & 17 deletions napi-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,19 @@ inline bool Value::IsExternal() const {
return Type() == napi_external;
}

#ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
inline bool Value::IsSharedArrayBuffer() const {
if (IsEmpty()) {
return false;
}

bool result;
napi_status status = node_api_is_sharedarraybuffer(_env, _value, &result);
NAPI_THROW_IF_FAILED(_env, status, false);
return result;
}
#endif

template <typename T>
inline T Value::As() const {
#ifdef NODE_ADDON_API_ENABLE_TYPE_CHECK_ON_AS
Expand Down Expand Up @@ -2068,6 +2081,60 @@ inline uint32_t Array::Length() const {
return result;
}

inline ArrayBufferLike::ArrayBufferLike() : Object() {}

inline ArrayBufferLike::ArrayBufferLike(napi_env env, napi_value value)
: Object(env, value) {}

inline void* ArrayBufferLike::Data() {
void* data;
napi_status status = napi_get_arraybuffer_info(_env, _value, &data, nullptr);
NAPI_THROW_IF_FAILED(_env, status, nullptr);
return data;
}

inline size_t ArrayBufferLike::ByteLength() {
size_t length;
napi_status status =
napi_get_arraybuffer_info(_env, _value, nullptr, &length);
NAPI_THROW_IF_FAILED(_env, status, 0);
return length;
}

#ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
////////////////////////////////////////////////////////////////////////////////
// SharedArrayBuffer class
////////////////////////////////////////////////////////////////////////////////

inline SharedArrayBuffer::SharedArrayBuffer() : ArrayBufferLike() {}

inline SharedArrayBuffer::SharedArrayBuffer(napi_env env, napi_value value)
: ArrayBufferLike(env, value) {}

inline void SharedArrayBuffer::CheckCast(napi_env env, napi_value value) {
NAPI_CHECK(value != nullptr, "SharedArrayBuffer::CheckCast", "empty value");

bool result;
napi_status status = node_api_is_sharedarraybuffer(env, value, &result);
NAPI_CHECK(status == napi_ok,
"SharedArrayBuffer::CheckCast",
"node_api_is_sharedarraybuffer failed");
NAPI_CHECK(
result, "SharedArrayBuffer::CheckCast", "value is not sharedarraybuffer");
}

inline SharedArrayBuffer SharedArrayBuffer::New(napi_env env,
size_t byteLength) {
napi_value value;
void* data;
napi_status status =
node_api_create_sharedarraybuffer(env, byteLength, &data, &value);
NAPI_THROW_IF_FAILED(env, status, SharedArrayBuffer());

return SharedArrayBuffer(env, value);
}
#endif // NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER

////////////////////////////////////////////////////////////////////////////////
// ArrayBuffer class
////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -2154,25 +2221,10 @@ inline void ArrayBuffer::CheckCast(napi_env env, napi_value value) {
NAPI_CHECK(result, "ArrayBuffer::CheckCast", "value is not arraybuffer");
}

inline ArrayBuffer::ArrayBuffer() : Object() {}
inline ArrayBuffer::ArrayBuffer() : ArrayBufferLike() {}

inline ArrayBuffer::ArrayBuffer(napi_env env, napi_value value)
: Object(env, value) {}

inline void* ArrayBuffer::Data() {
void* data;
napi_status status = napi_get_arraybuffer_info(_env, _value, &data, nullptr);
NAPI_THROW_IF_FAILED(_env, status, nullptr);
return data;
}

inline size_t ArrayBuffer::ByteLength() {
size_t length;
napi_status status =
napi_get_arraybuffer_info(_env, _value, nullptr, &length);
NAPI_THROW_IF_FAILED(_env, status, 0);
return length;
}
: ArrayBufferLike(env, value) {}

#if NAPI_VERSION >= 7
inline bool ArrayBuffer::IsDetached() const {
Expand Down
30 changes: 26 additions & 4 deletions napi.h
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,9 @@ class Value {
bool IsDataView() const; ///< Tests if a value is a JavaScript data view.
bool IsBuffer() const; ///< Tests if a value is a Node buffer.
bool IsExternal() const; ///< Tests if a value is a pointer to external data.
#ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
bool IsSharedArrayBuffer() const;
#endif

/// Casts to another type of `Napi::Value`, when the actual type is known or
/// assumed.
Expand Down Expand Up @@ -1202,8 +1205,30 @@ class Object::iterator {
};
#endif // NODE_ADDON_API_CPP_EXCEPTIONS

class ArrayBufferLike : public Object {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually we use the name XxxLike when it describes a shape of a protocol. For ArrayBuffer and SharedArrayBuffer, this is not the case. The Napi::ArrayBuffer and Napi::SharedArrayBuffer do not work with a JavaScript mocked ArrayBuffer-like objects.

I think a better name can be ArrayBufferBase. Or just duplicate these two methods as in JavaScript, ArrayBuffer and SharedArrayBuffer have no common ancestry.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in f861d36

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with the approach of:

Or just duplicate these two methods as in JavaScript, ArrayBuffer and SharedArrayBuffer have no common ancestry.

public:
void* Data();
size_t ByteLength();

protected:
ArrayBufferLike();
ArrayBufferLike(napi_env env, napi_value value);
};

#ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
class SharedArrayBuffer : public ArrayBufferLike {
public:
SharedArrayBuffer();
SharedArrayBuffer(napi_env env, napi_value value);

static SharedArrayBuffer New(napi_env env, size_t byteLength);

static void CheckCast(napi_env env, napi_value value);
};
#endif

/// A JavaScript array buffer value.
class ArrayBuffer : public Object {
class ArrayBuffer : public ArrayBufferLike {
public:
/// Creates a new ArrayBuffer instance over a new automatically-allocated
/// buffer.
Expand Down Expand Up @@ -1264,9 +1289,6 @@ class ArrayBuffer : public Object {
ArrayBuffer(napi_env env,
napi_value value); ///< Wraps a Node-API value primitive.

void* Data(); ///< Gets a pointer to the data buffer.
size_t ByteLength(); ///< Gets the length of the array buffer in bytes.

#if NAPI_VERSION >= 7
bool IsDetached() const;
void Detach();
Expand Down
8 changes: 8 additions & 0 deletions test/binding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ Object InitTypedThreadSafeFunctionSum(Env env);
Object InitTypedThreadSafeFunctionUnref(Env env);
Object InitTypedThreadSafeFunction(Env env);
#endif
Object InitSharedArrayBuffer(Env env);
Object InitSymbol(Env env);
Object InitTypedArray(Env env);
Object InitGlobalObject(Env env);
Expand Down Expand Up @@ -140,6 +141,7 @@ Object Init(Env env, Object exports) {
exports.Set("promise", InitPromise(env));
exports.Set("run_script", InitRunScript(env));
exports.Set("symbol", InitSymbol(env));
exports.Set("sharedarraybuffer", InitSharedArrayBuffer(env));
#if (NAPI_VERSION > 3)
exports.Set("threadsafe_function_ctx", InitThreadSafeFunctionCtx(env));
exports.Set("threadsafe_function_exception",
Expand Down Expand Up @@ -194,6 +196,12 @@ Object Init(Env env, Object exports) {
"isExperimental",
Napi::Boolean::New(env, NAPI_VERSION == NAPI_VERSION_EXPERIMENTAL));

#ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
exports.Set("hasSharedArrayBuffer", Napi::Boolean::New(env, true));
#else
exports.Set("hasSharedArrayBuffer", Napi::Boolean::New(env, false));
#endif

return exports;
}

Expand Down
1 change: 1 addition & 0 deletions test/binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
'object/subscript_operator.cc',
'promise.cc',
'run_script.cc',
'shared_array_buffer.cc',
'symbol.cc',
'threadsafe_function/threadsafe_function_ctx.cc',
'threadsafe_function/threadsafe_function_exception.cc',
Expand Down
Loading