From 8ec28f5731470b5a2db6a99a33205adc11d77dd5 Mon Sep 17 00:00:00 2001 From: Denys Otrishko Date: Sat, 23 Nov 2019 23:08:11 +0200 Subject: [PATCH] n-api: implement napi_is_detached_arraybuffer This implements ArrayBuffer#IsDetachedBuffer operation as per ECMAScript specification Section 24.1.1.2 https://tc39.es/ecma262/#sec-isdetachedbuffer Closes: https://github.com/nodejs/node/issues/29955 PR-URL: https://github.com/nodejs/node/pull/30613 Fixes: https://github.com/nodejs/node/issues/29955 Reviewed-By: Anna Henningsen Reviewed-By: Gus Caplan Reviewed-By: David Carlier Reviewed-By: Chengzhong Wu Reviewed-By: Michael Dawson --- doc/api/n-api.md | 26 +++++++++++++++ src/node_api.cc | 15 +++++++++ src/node_api.h | 5 +++ test/addons-napi/test_typedarray/test.js | 13 ++++++++ .../test_typedarray/test_typedarray.c | 32 +++++++++++++++++++ 5 files changed, 91 insertions(+) diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 5324285630baec..8f0ef2de53847f 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -2972,6 +2972,31 @@ that is, created with [`napi_create_external_arraybuffer`][]. This API represents the invocation of the `ArrayBuffer` detach operation as defined in [Section 24.1.1.3][] of the ECMAScript Language Specification. +### napi_is_detached_arraybuffer + + +> Stability: 1 - Experimental + +```C +napi_status napi_is_detached_arraybuffer(napi_env env, + napi_value arraybuffer, + bool* result) +``` + +* `[in] env`: The environment that the API is invoked under. +* `[in] arraybuffer`: The JavaScript `ArrayBuffer` to be checked. +* `[out] result`: Whether the `arraybuffer` is detached. + +Returns `napi_ok` if the API succeeded. + +The `ArrayBuffer` is considered detached if its internal data is `null`. + +This API represents the invocation of the `ArrayBuffer` `IsDetachedBuffer` +operation as defined in [Section 24.1.1.2][] of the ECMAScript Language +Specification. + ## Working with JavaScript Properties N-API exposes a set of APIs to get and set properties on JavaScript @@ -4924,6 +4949,7 @@ This API may only be called from the main thread. [Section 8.7]: https://tc39.es/ecma262/#sec-agents [Section 9.1.6]: https://tc39.github.io/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-defineownproperty-p-desc [Working with JavaScript Functions]: #n_api_working_with_javascript_functions +[Section 24.1.1.2]: https://tc39.es/ecma262/#sec-isdetachedbuffer [Working with JavaScript Properties]: #n_api_working_with_javascript_properties [Working with JavaScript Values - Abstract Operations]: #n_api_working_with_javascript_values_abstract_operations [Working with JavaScript Values]: #n_api_working_with_javascript_values diff --git a/src/node_api.cc b/src/node_api.cc index a6b506b3b5920f..aef818f2091e04 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -4403,3 +4403,18 @@ napi_status napi_detach_arraybuffer(napi_env env, napi_value arraybuffer) { return napi_clear_last_error(env); } + +napi_status napi_is_detached_arraybuffer(napi_env env, + napi_value arraybuffer, + bool* result) { + CHECK_ENV(env); + CHECK_ARG(env, arraybuffer); + CHECK_ARG(env, result); + + v8::Local value = v8impl::V8LocalValueFromJsValue(arraybuffer); + + *result = value->IsArrayBuffer() && + value.As()->GetContents().Data() == nullptr; + + return napi_clear_last_error(env); +} diff --git a/src/node_api.h b/src/node_api.h index 7dc9cfdd04b564..3b1ee6eaf6a1f4 100644 --- a/src/node_api.h +++ b/src/node_api.h @@ -752,6 +752,11 @@ napi_get_all_property_names(napi_env env, NAPI_EXTERN napi_status napi_detach_arraybuffer(napi_env env, napi_value arraybuffer); + +NAPI_EXTERN napi_status +napi_is_detached_arraybuffer(napi_env env, + napi_value value, + bool* result); #endif // NAPI_EXPERIMENTAL EXTERN_C_END diff --git a/test/addons-napi/test_typedarray/test.js b/test/addons-napi/test_typedarray/test.js index 8f35005b03dbef..3130176cbbc379 100644 --- a/test/addons-napi/test_typedarray/test.js +++ b/test/addons-napi/test_typedarray/test.js @@ -87,8 +87,21 @@ arrayTypes.forEach((currentType) => { assert.ok(externalResult instanceof Int8Array); assert.strictEqual(externalResult.length, 3); assert.strictEqual(externalResult.byteLength, 3); + assert.ok(!test_typedarray.IsDetached(buffer.buffer)); test_typedarray.Detach(buffer); + assert.ok(test_typedarray.IsDetached(buffer.buffer)); assert.ok(externalResult instanceof Int8Array); assert.strictEqual(buffer.length, 0); assert.strictEqual(buffer.byteLength, 0); } + +{ + const buffer = new ArrayBuffer(128); + assert.ok(!test_typedarray.IsDetached(buffer)); +} + +{ + const buffer = test_typedarray.NullArrayBuffer(); + assert.ok(buffer instanceof ArrayBuffer); + assert.ok(test_typedarray.IsDetached(buffer)); +} diff --git a/test/addons-napi/test_typedarray/test_typedarray.c b/test/addons-napi/test_typedarray/test_typedarray.c index 9966cad7123446..00ceabdb964962 100644 --- a/test/addons-napi/test_typedarray/test_typedarray.c +++ b/test/addons-napi/test_typedarray/test_typedarray.c @@ -97,6 +97,15 @@ static napi_value External(napi_env env, napi_callback_info info) { return output_array; } + +static napi_value NullArrayBuffer(napi_env env, napi_callback_info info) { + static void* data = NULL; + napi_value arraybuffer; + NAPI_CALL(env, + napi_create_external_arraybuffer(env, data, 0, NULL, NULL, &arraybuffer)); + return arraybuffer; +} + static napi_value CreateTypedArray(napi_env env, napi_callback_info info) { size_t argc = 4; napi_value args[4]; @@ -183,12 +192,35 @@ static napi_value Detach(napi_env env, napi_callback_info info) { return NULL; } +static napi_value IsDetached(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value args[1]; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NAPI_ASSERT(env, argc == 1, "Wrong number of arguments."); + + napi_value array_buffer = args[0]; + bool is_arraybuffer; + NAPI_CALL(env, napi_is_arraybuffer(env, array_buffer, &is_arraybuffer)); + NAPI_ASSERT(env, is_arraybuffer, + "Wrong type of arguments. Expects an array buffer as first argument."); + + bool is_detached; + NAPI_CALL(env, napi_is_detached_arraybuffer(env, array_buffer, &is_detached)); + + napi_value result; + NAPI_CALL(env, napi_get_boolean(env, is_detached, &result)); + + return result; +} + static napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { DECLARE_NAPI_PROPERTY("Multiply", Multiply), DECLARE_NAPI_PROPERTY("External", External), + DECLARE_NAPI_PROPERTY("NullArrayBuffer", NullArrayBuffer), DECLARE_NAPI_PROPERTY("CreateTypedArray", CreateTypedArray), DECLARE_NAPI_PROPERTY("Detach", Detach), + DECLARE_NAPI_PROPERTY("IsDetached", IsDetached), }; NAPI_CALL(env, napi_define_properties(