Skip to content

Commit

Permalink
Add ArrayBuffer::Detach() and ::IsDetached()
Browse files Browse the repository at this point in the history
  • Loading branch information
tniessen committed Jan 26, 2020
1 parent 4648420 commit bcd03dd
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 7 deletions.
14 changes: 14 additions & 0 deletions napi-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1415,6 +1415,20 @@ inline size_t ArrayBuffer::ByteLength() {
return length;
}

#ifdef NAPI_EXPERIMENTAL
inline bool ArrayBuffer::IsDetached() const {
bool detached;
napi_status status = napi_is_detached_arraybuffer(_env, _value, &detached);
NAPI_THROW_IF_FAILED(_env, status, false);
return detached;
}

inline void ArrayBuffer::Detach() {
napi_status status = napi_detach_arraybuffer(_env, _value);
NAPI_THROW_IF_FAILED_VOID(_env, status);
}
#endif // NAPI_EXPERIMENTAL

////////////////////////////////////////////////////////////////////////////////
// DataView class
////////////////////////////////////////////////////////////////////////////////
Expand Down
5 changes: 5 additions & 0 deletions napi.h
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,11 @@ namespace Napi {

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

#ifdef NAPI_EXPERIMENTAL
bool IsDetached() const;
void Detach();
#endif // NAPI_EXPERIMENTAL
};

/// A JavaScript typed-array value with unknown array type.
Expand Down
31 changes: 24 additions & 7 deletions test/arraybuffer.cc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#define NAPI_EXPERIMENTAL
#include "napi.h"

using namespace Napi;
Expand Down Expand Up @@ -157,19 +158,35 @@ void CheckDetachUpdatesData(const CallbackInfo& info) {
return;
}

if (!info[1].IsFunction()) {
Error::New(info.Env(), "A function was expected.").ThrowAsJavaScriptException();
return;
}

ArrayBuffer buffer = info[0].As<ArrayBuffer>();
Function detach = info[1].As<Function>();

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

detach.Call({});
if (buffer.IsDetached()) {
Error::New(info.Env(), "Buffer should not be detached.").ThrowAsJavaScriptException();
return;
}

if (info.Length() == 2) {
// Detach externally (in JavaScript).
if (!info[1].IsFunction()) {
Error::New(info.Env(), "A function was expected.").ThrowAsJavaScriptException();
return;
}

Function detach = info[1].As<Function>();
detach.Call({});
} else {
// Detach directly.
buffer.Detach();
}

if (!buffer.IsDetached()) {
Error::New(info.Env(), "Buffer should be detached.").ThrowAsJavaScriptException();
return;
}

if (buffer.Data() != nullptr) {
Error::New(info.Env(), "Incorrect data pointer.").ThrowAsJavaScriptException();
Expand Down
5 changes: 5 additions & 0 deletions test/arraybuffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,13 @@ function test(binding) {

'ArrayBuffer updates data pointer and length when detached',
() => {
// Detach the ArrayBuffer in JavaScript.
const mem = new WebAssembly.Memory({ initial: 1 });
binding.arraybuffer.checkDetachUpdatesData(mem.buffer, () => mem.grow(1));

// Let C++ detach the ArrayBuffer.
const extBuffer = binding.arraybuffer.createExternalBuffer();
binding.arraybuffer.checkDetachUpdatesData(extBuffer);
},
]);
}

0 comments on commit bcd03dd

Please sign in to comment.