From a1cbbd1da6d7ea9fbdbdabba6ac78b2b4cef9621 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/js_native_api.h | 4 +++ src/js_native_api_v8.cc | 15 +++++++++ test/js-native-api/test_typedarray/test.js | 13 ++++++++ .../test_typedarray/test_typedarray.c | 32 +++++++++++++++++++ 5 files changed, 90 insertions(+) diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 0e88387e5176b1..c2812c9ebdd674 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -3258,6 +3258,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 @@ -5259,6 +5284,7 @@ This API may only be called from the main thread. [Section 7]: https://tc39.github.io/ecma262/#sec-abstract-operations [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 +[Section 24.1.1.2]: https://tc39.es/ecma262/#sec-isdetachedbuffer [Travis CI]: https://travis-ci.org [Visual Studio]: https://visualstudio.microsoft.com [Working with JavaScript Properties]: #n_api_working_with_javascript_properties diff --git a/src/js_native_api.h b/src/js_native_api.h index cf1596be80e5b1..150103348e4dc6 100644 --- a/src/js_native_api.h +++ b/src/js_native_api.h @@ -518,6 +518,10 @@ NAPI_EXTERN napi_status napi_get_instance_data(napi_env env, // ArrayBuffer detaching 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/src/js_native_api_v8.cc b/src/js_native_api_v8.cc index 5c809e977aea82..05712afde0020f 100644 --- a/src/js_native_api_v8.cc +++ b/src/js_native_api_v8.cc @@ -3040,3 +3040,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()->GetBackingStore()->Data() == nullptr; + + return napi_clear_last_error(env); +} diff --git a/test/js-native-api/test_typedarray/test.js b/test/js-native-api/test_typedarray/test.js index 5f51383254b7ab..0d9594d92933c7 100644 --- a/test/js-native-api/test_typedarray/test.js +++ b/test/js-native-api/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/js-native-api/test_typedarray/test_typedarray.c b/test/js-native-api/test_typedarray/test_typedarray.c index 9d7d394fca7c49..d8b64d06c0c57b 100644 --- a/test/js-native-api/test_typedarray/test_typedarray.c +++ b/test/js-native-api/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,13 +192,36 @@ 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; +} + EXTERN_C_START 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(