From 5cb875286272eb5dac8384ad74b85e784b954ad3 Mon Sep 17 00:00:00 2001 From: Denys Otrishko Date: Sat, 23 Nov 2019 23:08:11 +0200 Subject: [PATCH 1/4] 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 --- doc/api/n-api.md | 24 +++++++++++++++ src/js_native_api.h | 4 +++ src/js_native_api_v8.cc | 14 +++++++++ test/js-native-api/test_typedarray/test.js | 13 ++++++++ .../test_typedarray/test_typedarray.c | 30 +++++++++++++++++++ 5 files changed, 85 insertions(+) diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 0e88387e5176b1..7fea9b0f97c7fe 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -3258,6 +3258,29 @@ 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 + + +```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 +5282,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 6484afaaac629e..1593fe17d0bf8a 100644 --- a/src/js_native_api_v8.cc +++ b/src/js_native_api_v8.cc @@ -3039,3 +3039,17 @@ 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); + + 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..ec68d9cdf16b65 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.EmptyArrayBuffer(); + 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..ef59f2bad96ba7 100644 --- a/test/js-native-api/test_typedarray/test_typedarray.c +++ b/test/js-native-api/test_typedarray/test_typedarray.c @@ -97,6 +97,14 @@ static napi_value External(napi_env env, napi_callback_info info) { return output_array; } + +static napi_value EmptyArrayBuffer(napi_env env, napi_callback_info info) { + void* null_data = NULL; + napi_value array_buffer; + NAPI_CALL(env, napi_create_arraybuffer(env, 0, &null_data, &array_buffer)); + return array_buffer; +} + static napi_value CreateTypedArray(napi_env env, napi_callback_info info) { size_t argc = 4; napi_value args[4]; @@ -183,13 +191,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; +} + 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("EmptyArrayBuffer", EmptyArrayBuffer), DECLARE_NAPI_PROPERTY("CreateTypedArray", CreateTypedArray), DECLARE_NAPI_PROPERTY("Detach", Detach), + DECLARE_NAPI_PROPERTY("IsDetached", IsDetached), }; NAPI_CALL(env, napi_define_properties( From 5bf270e66b4fb6a3df79bbd630cc883dc452eb88 Mon Sep 17 00:00:00 2001 From: Denys Otrishko Date: Sun, 24 Nov 2019 15:41:58 +0200 Subject: [PATCH 2/4] fixup! n-api: implement napi_is_detached_arraybuffer --- src/js_native_api_v8.cc | 2 +- test/js-native-api/test_typedarray/test.js | 2 +- .../test_typedarray/test_typedarray.c | 16 +++++++++------- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/js_native_api_v8.cc b/src/js_native_api_v8.cc index 1593fe17d0bf8a..51873332a2aa16 100644 --- a/src/js_native_api_v8.cc +++ b/src/js_native_api_v8.cc @@ -3049,7 +3049,7 @@ napi_status napi_is_detached_arraybuffer(napi_env env, v8::Local value = v8impl::V8LocalValueFromJsValue(arraybuffer); *result = value->IsArrayBuffer() && - value.As()->GetBackingStore()->Data() == nullptr; + 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 ec68d9cdf16b65..0d9594d92933c7 100644 --- a/test/js-native-api/test_typedarray/test.js +++ b/test/js-native-api/test_typedarray/test.js @@ -101,7 +101,7 @@ arrayTypes.forEach((currentType) => { } { - const buffer = test_typedarray.EmptyArrayBuffer(); + 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 ef59f2bad96ba7..d8b64d06c0c57b 100644 --- a/test/js-native-api/test_typedarray/test_typedarray.c +++ b/test/js-native-api/test_typedarray/test_typedarray.c @@ -98,11 +98,12 @@ static napi_value External(napi_env env, napi_callback_info info) { } -static napi_value EmptyArrayBuffer(napi_env env, napi_callback_info info) { - void* null_data = NULL; - napi_value array_buffer; - NAPI_CALL(env, napi_create_arraybuffer(env, 0, &null_data, &array_buffer)); - return array_buffer; +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) { @@ -200,7 +201,8 @@ static napi_value IsDetached(napi_env env, napi_callback_info info) { 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."); + 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)); @@ -216,7 +218,7 @@ 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("EmptyArrayBuffer", EmptyArrayBuffer), + DECLARE_NAPI_PROPERTY("NullArrayBuffer", NullArrayBuffer), DECLARE_NAPI_PROPERTY("CreateTypedArray", CreateTypedArray), DECLARE_NAPI_PROPERTY("Detach", Detach), DECLARE_NAPI_PROPERTY("IsDetached", IsDetached), From 7352a88db42ce1c6a43559d28d528a549b1d6634 Mon Sep 17 00:00:00 2001 From: Denys Otrishko Date: Sun, 24 Nov 2019 16:18:19 +0200 Subject: [PATCH 3/4] fixup! n-api: implement napi_is_detached_arraybuffer --- src/js_native_api_v8.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/js_native_api_v8.cc b/src/js_native_api_v8.cc index 51873332a2aa16..87501957d59157 100644 --- a/src/js_native_api_v8.cc +++ b/src/js_native_api_v8.cc @@ -3045,6 +3045,7 @@ napi_status napi_is_detached_arraybuffer(napi_env env, bool* result) { CHECK_ENV(env); CHECK_ARG(env, arraybuffer); + CHECK_ARG(env, result); v8::Local value = v8impl::V8LocalValueFromJsValue(arraybuffer); From 8dc4a18a25ad8f6c3dcd2b6dcb37bd588b86afad Mon Sep 17 00:00:00 2001 From: Denys Otrishko Date: Thu, 28 Nov 2019 08:44:27 +0200 Subject: [PATCH 4/4] fixup! n-api: implement napi_is_detached_arraybuffer --- doc/api/n-api.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 7fea9b0f97c7fe..c2812c9ebdd674 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -3263,6 +3263,8 @@ defined in [Section 24.1.1.3][] of the ECMAScript Language Specification. added: REPLACEME --> +> Stability: 1 - Experimental + ```C napi_status napi_is_detached_arraybuffer(napi_env env, napi_value arraybuffer,