Skip to content

Commit 02cc813

Browse files
committed
feat: add SharedArrayBuffer
1 parent 60d439e commit 02cc813

File tree

11 files changed

+355
-39
lines changed

11 files changed

+355
-39
lines changed

doc/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ The following is the documentation for node-addon-api.
6060
- [ClassPropertyDescriptor](class_property_descriptor.md)
6161
- [Buffer](buffer.md)
6262
- [ArrayBuffer](array_buffer.md)
63+
- [SharedArrayBuffer](shared_array_buffer.md)
6364
- [TypedArray](typed_array.md)
6465
- [TypedArrayOf](typed_array_of.md)
6566
- [DataView](dataview.md)

doc/array_buffer.md

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# ArrayBuffer
22

3-
Class `Napi::ArrayBuffer` inherits from class [`Napi::Object`][].
3+
Class `Napi::ArrayBuffer` inherits from class [`Napi::ArrayBufferLike`][].
44

55
The `Napi::ArrayBuffer` class corresponds to the
66
[JavaScript `ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer)
@@ -128,22 +128,6 @@ Napi::ArrayBuffer::ArrayBuffer(napi_env env, napi_value value);
128128
- `[in] env`: The environment in which to create the `Napi::ArrayBuffer` instance.
129129
- `[in] value`: The `Napi::ArrayBuffer` reference to wrap.
130130
131-
### ByteLength
132-
133-
```cpp
134-
size_t Napi::ArrayBuffer::ByteLength() const;
135-
```
136-
137-
Returns the length of the wrapped data, in bytes.
138-
139-
### Data
140-
141-
```cpp
142-
void* Napi::ArrayBuffer::Data() const;
143-
```
144-
145-
Returns a pointer the wrapped data.
146-
147131
### Detach
148132
149133
```cpp
@@ -160,6 +144,6 @@ bool Napi::ArrayBuffer::IsDetached() const;
160144

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

163-
[`Napi::Object`]: ./object.md
147+
[`Napi::ArrayBufferLike`]: ./array_buffer_like.md
164148
[External Buffer]: ./external_buffer.md
165149
[Finalization]: ./finalization.md

doc/array_buffer_like.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# ArrayBufferLike
2+
3+
Class `Napi::ArrayBufferLike` inherits from class [`Napi::Object`][].
4+
5+
The `Napi::ArrayBufferLike` class is the base class for [`Napi::ArrayBuffer`][]
6+
and [`Napi::SharedArrayBuffer`][]. It adds common array buffer capabilities to
7+
both. It is an abstract-only base class.
8+
9+
### ByteLength
10+
11+
```cpp
12+
size_t Napi::ArrayBufferLike::ByteLength() const;
13+
```
14+
15+
Returns the length of the wrapped data, in bytes.
16+
17+
### Data
18+
19+
```cpp
20+
void* Napi::ArrayBufferLike::Data() const;
21+
```
22+
23+
Returns a pointer the wrapped data.
24+
25+
[`Napi::ArrayBuffer`]: ./array_buffer.md
26+
[`Napi::Object`]: ./object.md
27+
[`Napi::SharedArrayBuffer`]: ./shared_array_buffer.md

doc/shared_array_buffer.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# SharedArrayBuffer
2+
3+
Class `Napi::SharedArrayBuffer` inherits from class [`Napi::ArrayBufferLike`][].
4+
5+
The `Napi::SharedArrayBuffer` class corresponds to the
6+
[JavaScript `SharedArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer)
7+
class.
8+
9+
**NOTE**: The support for `Napi::SharedArrayBuffer` is only available when using
10+
`NAPI_EXPERIMENTAL` and building against Node.js headers that support this
11+
feature.
12+
13+
## Methods
14+
15+
### New
16+
17+
Allocates a new `Napi::SharedArrayBuffer` instance with a given length.
18+
19+
```cpp
20+
static Napi::SharedArrayBuffer Napi::SharedArrayBuffer::New(napi_env env, size_t byteLength);
21+
```
22+
23+
- `[in] env`: The environment in which to create the `Napi::SharedArrayBuffer`
24+
instance.
25+
- `[in] byteLength`: The length to be allocated, in bytes.
26+
27+
Returns a new `Napi::SharedArrayBuffer` instance.
28+
29+
### Constructor
30+
31+
Initializes an empty instance of the `Napi::SharedArrayBuffer` class.
32+
33+
```cpp
34+
Napi::SharedArrayBuffer::SharedArrayBuffer();
35+
```
36+
37+
### Constructor
38+
39+
Initializes a wrapper instance of an existing `Napi::SharedArrayBuffer` object.
40+
41+
```cpp
42+
Napi::SharedArrayBuffer::SharedArrayBuffer(napi_env env, napi_value value);
43+
```
44+
45+
- `[in] env`: The environment in which to create the `Napi::SharedArrayBuffer`
46+
instance.
47+
- `[in] value`: The `Napi::SharedArrayBuffer` reference to wrap.
48+
49+
[`Napi::ArrayBufferLike`]: ./array_buffer_like.md

doc/value.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,19 @@ bool Napi::Value::IsPromise() const;
268268
Returns `true` if the underlying value is a JavaScript `Napi::Promise` or
269269
`false` otherwise.
270270

271+
### IsSharedArrayBuffer
272+
273+
```cpp
274+
bool Napi::Value::IsSharedArrayBuffer() const;
275+
```
276+
277+
Returns `true` if the underlying value is a JavaScript
278+
`Napi::IsSharedArrayBuffer` or `false` otherwise.
279+
280+
**NOTE**: The support for `Napi::SharedArrayBuffer` is only available when using
281+
`NAPI_EXPERIMENTAL` and building against Node.js headers that support this
282+
feature.
283+
271284
### IsString
272285

273286
```cpp

napi-inl.h

Lines changed: 69 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,19 @@ inline bool Value::IsExternal() const {
934934
return Type() == napi_external;
935935
}
936936

937+
#ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
938+
inline bool Value::IsSharedArrayBuffer() const {
939+
if (IsEmpty()) {
940+
return false;
941+
}
942+
943+
bool result;
944+
napi_status status = node_api_is_sharedarraybuffer(_env, _value, &result);
945+
NAPI_THROW_IF_FAILED(_env, status, false);
946+
return result;
947+
}
948+
#endif
949+
937950
template <typename T>
938951
inline T Value::As() const {
939952
#ifdef NODE_ADDON_API_ENABLE_TYPE_CHECK_ON_AS
@@ -2068,6 +2081,60 @@ inline uint32_t Array::Length() const {
20682081
return result;
20692082
}
20702083

2084+
inline ArrayBufferLike::ArrayBufferLike() : Object() {}
2085+
2086+
inline ArrayBufferLike::ArrayBufferLike(napi_env env, napi_value value)
2087+
: Object(env, value) {}
2088+
2089+
inline void* ArrayBufferLike::Data() {
2090+
void* data;
2091+
napi_status status = napi_get_arraybuffer_info(_env, _value, &data, nullptr);
2092+
NAPI_THROW_IF_FAILED(_env, status, nullptr);
2093+
return data;
2094+
}
2095+
2096+
inline size_t ArrayBufferLike::ByteLength() {
2097+
size_t length;
2098+
napi_status status =
2099+
napi_get_arraybuffer_info(_env, _value, nullptr, &length);
2100+
NAPI_THROW_IF_FAILED(_env, status, 0);
2101+
return length;
2102+
}
2103+
2104+
#ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
2105+
////////////////////////////////////////////////////////////////////////////////
2106+
// SharedArrayBuffer class
2107+
////////////////////////////////////////////////////////////////////////////////
2108+
2109+
inline SharedArrayBuffer::SharedArrayBuffer() : ArrayBufferLike() {}
2110+
2111+
inline SharedArrayBuffer::SharedArrayBuffer(napi_env env, napi_value value)
2112+
: ArrayBufferLike(env, value) {}
2113+
2114+
inline void SharedArrayBuffer::CheckCast(napi_env env, napi_value value) {
2115+
NAPI_CHECK(value != nullptr, "SharedArrayBuffer::CheckCast", "empty value");
2116+
2117+
bool result;
2118+
napi_status status = node_api_is_sharedarraybuffer(env, value, &result);
2119+
NAPI_CHECK(status == napi_ok,
2120+
"SharedArrayBuffer::CheckCast",
2121+
"node_api_is_sharedarraybuffer failed");
2122+
NAPI_CHECK(
2123+
result, "SharedArrayBuffer::CheckCast", "value is not sharedarraybuffer");
2124+
}
2125+
2126+
inline SharedArrayBuffer SharedArrayBuffer::New(napi_env env,
2127+
size_t byteLength) {
2128+
napi_value value;
2129+
void* data;
2130+
napi_status status =
2131+
node_api_create_sharedarraybuffer(env, byteLength, &data, &value);
2132+
NAPI_THROW_IF_FAILED(env, status, SharedArrayBuffer());
2133+
2134+
return SharedArrayBuffer(env, value);
2135+
}
2136+
#endif // NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
2137+
20712138
////////////////////////////////////////////////////////////////////////////////
20722139
// ArrayBuffer class
20732140
////////////////////////////////////////////////////////////////////////////////
@@ -2154,25 +2221,10 @@ inline void ArrayBuffer::CheckCast(napi_env env, napi_value value) {
21542221
NAPI_CHECK(result, "ArrayBuffer::CheckCast", "value is not arraybuffer");
21552222
}
21562223

2157-
inline ArrayBuffer::ArrayBuffer() : Object() {}
2224+
inline ArrayBuffer::ArrayBuffer() : ArrayBufferLike() {}
21582225

21592226
inline ArrayBuffer::ArrayBuffer(napi_env env, napi_value value)
2160-
: Object(env, value) {}
2161-
2162-
inline void* ArrayBuffer::Data() {
2163-
void* data;
2164-
napi_status status = napi_get_arraybuffer_info(_env, _value, &data, nullptr);
2165-
NAPI_THROW_IF_FAILED(_env, status, nullptr);
2166-
return data;
2167-
}
2168-
2169-
inline size_t ArrayBuffer::ByteLength() {
2170-
size_t length;
2171-
napi_status status =
2172-
napi_get_arraybuffer_info(_env, _value, nullptr, &length);
2173-
NAPI_THROW_IF_FAILED(_env, status, 0);
2174-
return length;
2175-
}
2227+
: ArrayBufferLike(env, value) {}
21762228

21772229
#if NAPI_VERSION >= 7
21782230
inline bool ArrayBuffer::IsDetached() const {

napi.h

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,9 @@ class Value {
543543
bool IsDataView() const; ///< Tests if a value is a JavaScript data view.
544544
bool IsBuffer() const; ///< Tests if a value is a Node buffer.
545545
bool IsExternal() const; ///< Tests if a value is a pointer to external data.
546+
#ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
547+
bool IsSharedArrayBuffer() const;
548+
#endif
546549

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

1208+
class ArrayBufferLike : public Object {
1209+
public:
1210+
void* Data();
1211+
size_t ByteLength();
1212+
1213+
protected:
1214+
ArrayBufferLike();
1215+
ArrayBufferLike(napi_env env, napi_value value);
1216+
};
1217+
1218+
#ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
1219+
class SharedArrayBuffer : public ArrayBufferLike {
1220+
public:
1221+
SharedArrayBuffer();
1222+
SharedArrayBuffer(napi_env env, napi_value value);
1223+
1224+
static SharedArrayBuffer New(napi_env env, size_t byteLength);
1225+
1226+
static void CheckCast(napi_env env, napi_value value);
1227+
};
1228+
#endif
1229+
12051230
/// A JavaScript array buffer value.
1206-
class ArrayBuffer : public Object {
1231+
class ArrayBuffer : public ArrayBufferLike {
12071232
public:
12081233
/// Creates a new ArrayBuffer instance over a new automatically-allocated
12091234
/// buffer.
@@ -1264,9 +1289,6 @@ class ArrayBuffer : public Object {
12641289
ArrayBuffer(napi_env env,
12651290
napi_value value); ///< Wraps a Node-API value primitive.
12661291

1267-
void* Data(); ///< Gets a pointer to the data buffer.
1268-
size_t ByteLength(); ///< Gets the length of the array buffer in bytes.
1269-
12701292
#if NAPI_VERSION >= 7
12711293
bool IsDetached() const;
12721294
void Detach();

test/binding.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ Object InitTypedThreadSafeFunctionSum(Env env);
6464
Object InitTypedThreadSafeFunctionUnref(Env env);
6565
Object InitTypedThreadSafeFunction(Env env);
6666
#endif
67+
Object InitSharedArrayBuffer(Env env);
6768
Object InitSymbol(Env env);
6869
Object InitTypedArray(Env env);
6970
Object InitGlobalObject(Env env);
@@ -140,6 +141,7 @@ Object Init(Env env, Object exports) {
140141
exports.Set("promise", InitPromise(env));
141142
exports.Set("run_script", InitRunScript(env));
142143
exports.Set("symbol", InitSymbol(env));
144+
exports.Set("sharedarraybuffer", InitSharedArrayBuffer(env));
143145
#if (NAPI_VERSION > 3)
144146
exports.Set("threadsafe_function_ctx", InitThreadSafeFunctionCtx(env));
145147
exports.Set("threadsafe_function_exception",
@@ -194,6 +196,12 @@ Object Init(Env env, Object exports) {
194196
"isExperimental",
195197
Napi::Boolean::New(env, NAPI_VERSION == NAPI_VERSION_EXPERIMENTAL));
196198

199+
#ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
200+
exports.Set("hasSharedArrayBuffer", Napi::Boolean::New(env, true));
201+
#else
202+
exports.Set("hasSharedArrayBuffer", Napi::Boolean::New(env, false));
203+
#endif
204+
197205
return exports;
198206
}
199207

test/binding.gyp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
'object/subscript_operator.cc',
5555
'promise.cc',
5656
'run_script.cc',
57+
'shared_array_buffer.cc',
5758
'symbol.cc',
5859
'threadsafe_function/threadsafe_function_ctx.cc',
5960
'threadsafe_function/threadsafe_function_exception.cc',

0 commit comments

Comments
 (0)