From bcd03dd04d52f8d51199426d61e8512d9e41df3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= Date: Sun, 26 Jan 2020 00:30:38 -0400 Subject: [PATCH] Add ArrayBuffer::Detach() and ::IsDetached() Refs: https://github.com/nodejs/node/pull/29768 Refs: https://github.com/nodejs/node/pull/30613 --- napi-inl.h | 14 ++++++++++++++ napi.h | 5 +++++ test/arraybuffer.cc | 31 ++++++++++++++++++++++++------- test/arraybuffer.js | 5 +++++ 4 files changed, 48 insertions(+), 7 deletions(-) diff --git a/napi-inl.h b/napi-inl.h index 2855e80ef..476edf8cc 100644 --- a/napi-inl.h +++ b/napi-inl.h @@ -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 //////////////////////////////////////////////////////////////////////////////// diff --git a/napi.h b/napi.h index 49435d59b..8c5197536 100644 --- a/napi.h +++ b/napi.h @@ -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. diff --git a/test/arraybuffer.cc b/test/arraybuffer.cc index cc4f1f51c..142f12c84 100644 --- a/test/arraybuffer.cc +++ b/test/arraybuffer.cc @@ -1,3 +1,4 @@ +#define NAPI_EXPERIMENTAL #include "napi.h" using namespace Napi; @@ -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(); - Function detach = info[1].As(); // 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(); + 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(); diff --git a/test/arraybuffer.js b/test/arraybuffer.js index 30136980b..7f222446c 100644 --- a/test/arraybuffer.js +++ b/test/arraybuffer.js @@ -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); }, ]); }