Skip to content

Commit bcd03dd

Browse files
committed
Add ArrayBuffer::Detach() and ::IsDetached()
Refs: nodejs/node#29768 Refs: nodejs/node#30613
1 parent 4648420 commit bcd03dd

File tree

4 files changed

+48
-7
lines changed

4 files changed

+48
-7
lines changed

napi-inl.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,6 +1415,20 @@ inline size_t ArrayBuffer::ByteLength() {
14151415
return length;
14161416
}
14171417

1418+
#ifdef NAPI_EXPERIMENTAL
1419+
inline bool ArrayBuffer::IsDetached() const {
1420+
bool detached;
1421+
napi_status status = napi_is_detached_arraybuffer(_env, _value, &detached);
1422+
NAPI_THROW_IF_FAILED(_env, status, false);
1423+
return detached;
1424+
}
1425+
1426+
inline void ArrayBuffer::Detach() {
1427+
napi_status status = napi_detach_arraybuffer(_env, _value);
1428+
NAPI_THROW_IF_FAILED_VOID(_env, status);
1429+
}
1430+
#endif // NAPI_EXPERIMENTAL
1431+
14181432
////////////////////////////////////////////////////////////////////////////////
14191433
// DataView class
14201434
////////////////////////////////////////////////////////////////////////////////

napi.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,11 @@ namespace Napi {
813813

814814
void* Data(); ///< Gets a pointer to the data buffer.
815815
size_t ByteLength(); ///< Gets the length of the array buffer in bytes.
816+
817+
#ifdef NAPI_EXPERIMENTAL
818+
bool IsDetached() const;
819+
void Detach();
820+
#endif // NAPI_EXPERIMENTAL
816821
};
817822

818823
/// A JavaScript typed-array value with unknown array type.

test/arraybuffer.cc

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#define NAPI_EXPERIMENTAL
12
#include "napi.h"
23

34
using namespace Napi;
@@ -157,19 +158,35 @@ void CheckDetachUpdatesData(const CallbackInfo& info) {
157158
return;
158159
}
159160

160-
if (!info[1].IsFunction()) {
161-
Error::New(info.Env(), "A function was expected.").ThrowAsJavaScriptException();
162-
return;
163-
}
164-
165161
ArrayBuffer buffer = info[0].As<ArrayBuffer>();
166-
Function detach = info[1].As<Function>();
167162

168163
// This potentially causes the buffer to cache its data pointer and length.
169164
buffer.Data();
170165
buffer.ByteLength();
171166

172-
detach.Call({});
167+
if (buffer.IsDetached()) {
168+
Error::New(info.Env(), "Buffer should not be detached.").ThrowAsJavaScriptException();
169+
return;
170+
}
171+
172+
if (info.Length() == 2) {
173+
// Detach externally (in JavaScript).
174+
if (!info[1].IsFunction()) {
175+
Error::New(info.Env(), "A function was expected.").ThrowAsJavaScriptException();
176+
return;
177+
}
178+
179+
Function detach = info[1].As<Function>();
180+
detach.Call({});
181+
} else {
182+
// Detach directly.
183+
buffer.Detach();
184+
}
185+
186+
if (!buffer.IsDetached()) {
187+
Error::New(info.Env(), "Buffer should be detached.").ThrowAsJavaScriptException();
188+
return;
189+
}
173190

174191
if (buffer.Data() != nullptr) {
175192
Error::New(info.Env(), "Incorrect data pointer.").ThrowAsJavaScriptException();

test/arraybuffer.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,13 @@ function test(binding) {
6464

6565
'ArrayBuffer updates data pointer and length when detached',
6666
() => {
67+
// Detach the ArrayBuffer in JavaScript.
6768
const mem = new WebAssembly.Memory({ initial: 1 });
6869
binding.arraybuffer.checkDetachUpdatesData(mem.buffer, () => mem.grow(1));
70+
71+
// Let C++ detach the ArrayBuffer.
72+
const extBuffer = binding.arraybuffer.createExternalBuffer();
73+
binding.arraybuffer.checkDetachUpdatesData(extBuffer);
6974
},
7075
]);
7176
}

0 commit comments

Comments
 (0)