diff options
author | legendecas <legendecas@gmail.com> | 2020-04-26 00:04:17 +0800 |
---|---|---|
committer | Richard Lau <riclau@uk.ibm.com> | 2020-07-01 14:53:26 -0400 |
commit | 961598b9be34f1d70a95062633ef6f95f7aeaac3 (patch) | |
tree | 888fe919f6736d1f1fb6005825959a793b976ae0 | |
parent | 3dbd8cd3a9b5786ec3ecb5fac3bec23810324678 (diff) | |
download | node-new-961598b9be34f1d70a95062633ef6f95f7aeaac3.tar.gz |
n-api: add `napi_detach_arraybuffer`
As ArrayBuffer#detach is an ecma spec operation
([Section 24.1.1.3](https://tc39.es/ecma262/#sec-detacharraybuffer)),
it might be good to have it in N-API.
Fixes: https://github.com/nodejs/node/issues/29674
PR-URL: https://github.com/nodejs/node/pull/29768
Backport-PR-URL: https://github.com/nodejs/node/pull/33061
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: David Carlier <devnexen@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gabriel Schulhof <gabriel.schulhof@intel.com>
-rw-r--r-- | doc/api/n-api.md | 27 | ||||
-rw-r--r-- | src/node_api.cc | 23 | ||||
-rw-r--r-- | src/node_api.h | 7 | ||||
-rw-r--r-- | src/node_api_types.h | 2 | ||||
-rw-r--r-- | test/addons-napi/test_typedarray/test.js | 18 | ||||
-rw-r--r-- | test/addons-napi/test_typedarray/test_typedarray.c | 19 |
6 files changed, 95 insertions, 1 deletions
diff --git a/doc/api/n-api.md b/doc/api/n-api.md index b84ce8d55b..5324285630 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -265,6 +265,8 @@ typedef enum { napi_closing, napi_bigint_expected, napi_date_expected, + napi_arraybuffer_expected, + napi_detachable_arraybuffer_expected, } napi_status; ``` If additional information is required upon an API returning a failed status, @@ -2946,6 +2948,30 @@ defined in [Section 7.2.14](https://tc39.github.io/ecma262/#sec-strict-equality-comparison) of the ECMAScript Language Specification. +### napi_detach_arraybuffer +<!-- YAML +added: REPLACEME +--> + +```C +napi_status napi_detach_arraybuffer(napi_env env, + napi_value arraybuffer) +``` + +* `[in] env`: The environment that the API is invoked under. +* `[in] arraybuffer`: The JavaScript `ArrayBuffer` to be detached. + +Returns `napi_ok` if the API succeeded. If a non-detachable `ArrayBuffer` is +passed in it returns `napi_detachable_arraybuffer_expected`. + +Generally, an `ArrayBuffer` is non-detachable if it has been detached before. +The engine may impose additional conditions on whether an `ArrayBuffer` is +detachable. For example, V8 requires that the `ArrayBuffer` be external, +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. + ## Working with JavaScript Properties N-API exposes a set of APIs to get and set properties on JavaScript @@ -4889,6 +4915,7 @@ This API may only be called from the main thread. [Section 22.1]: https://tc39.github.io/ecma262/#sec-array-objects [Section 22.2]: https://tc39.github.io/ecma262/#sec-typedarray-objects [Section 24.1]: https://tc39.github.io/ecma262/#sec-arraybuffer-objects +[Section 24.1.1.3]: https://tc39.es/ecma262/#sec-detacharraybuffer [Section 24.3]: https://tc39.github.io/ecma262/#sec-dataview-objects [Section 25.4]: https://tc39.github.io/ecma262/#sec-promise-objects [Section 6.1.4]: https://tc39.github.io/ecma262/#sec-ecmascript-language-types-string-type diff --git a/src/node_api.cc b/src/node_api.cc index c444ad91a5..a6b506b3b5 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -1386,6 +1386,8 @@ const char* error_messages[] = {nullptr, "Thread-safe function handle is closing", "A bigint was expected", "A date was expected", + "An arraybuffer was expected", + "A detachable arraybuffer was expected", }; static inline napi_status napi_clear_last_error(napi_env env) { @@ -1416,7 +1418,7 @@ napi_status napi_get_last_error_info(napi_env env, // message in the `napi_status` enum each time a new error message is added. // We don't have a napi_status_last as this would result in an ABI // change each time a message was added. - const int last_status = napi_date_expected; + const int last_status = napi_detachable_arraybuffer_expected; static_assert( node::arraysize(error_messages) == last_status + 1, @@ -4382,3 +4384,22 @@ napi_status napi_get_instance_data(napi_env env, return napi_clear_last_error(env); } + +napi_status napi_detach_arraybuffer(napi_env env, napi_value arraybuffer) { + CHECK_ENV(env); + CHECK_ARG(env, arraybuffer); + + v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer); + RETURN_STATUS_IF_FALSE( + env, value->IsArrayBuffer(), napi_arraybuffer_expected); + + v8::Local<v8::ArrayBuffer> it = value.As<v8::ArrayBuffer>(); + RETURN_STATUS_IF_FALSE( + env, it->IsExternal(), napi_detachable_arraybuffer_expected); + RETURN_STATUS_IF_FALSE( + env, it->IsNeuterable(), napi_detachable_arraybuffer_expected); + + it->Neuter(); + + return napi_clear_last_error(env); +} diff --git a/src/node_api.h b/src/node_api.h index 4b88102749..7dc9cfdd04 100644 --- a/src/node_api.h +++ b/src/node_api.h @@ -747,6 +747,13 @@ napi_get_all_property_names(napi_env env, #endif // NAPI_VERSION >= 6 +#ifdef NAPI_EXPERIMENTAL +// ArrayBuffer detaching +NAPI_EXTERN napi_status +napi_detach_arraybuffer(napi_env env, + napi_value arraybuffer); +#endif // NAPI_EXPERIMENTAL + EXTERN_C_END #endif // SRC_NODE_API_H_ diff --git a/src/node_api_types.h b/src/node_api_types.h index 55158fa412..f3b1c5642f 100644 --- a/src/node_api_types.h +++ b/src/node_api_types.h @@ -83,6 +83,8 @@ typedef enum { napi_closing, napi_bigint_expected, napi_date_expected, + napi_arraybuffer_expected, + napi_detachable_arraybuffer_expected, } napi_status; // Note: when adding a new enum value to `napi_status`, please also update // `const int last_status` in `napi_get_last_error_info()' definition, diff --git a/test/addons-napi/test_typedarray/test.js b/test/addons-napi/test_typedarray/test.js index 2a8cf18feb..8f35005b03 100644 --- a/test/addons-napi/test_typedarray/test.js +++ b/test/addons-napi/test_typedarray/test.js @@ -74,3 +74,21 @@ nonByteArrayTypes.forEach((currentType) => { console.log(`start of offset ${currentType}`); }, RangeError); }); + +// Test detaching +arrayTypes.forEach((currentType) => { + const buffer = Reflect.construct(currentType, [8]); + assert.throws( + () => test_typedarray.Detach(buffer), + /A detachable arraybuffer was expected/); +}); +{ + const buffer = test_typedarray.External(); + assert.ok(externalResult instanceof Int8Array); + assert.strictEqual(externalResult.length, 3); + assert.strictEqual(externalResult.byteLength, 3); + test_typedarray.Detach(buffer); + assert.ok(externalResult instanceof Int8Array); + assert.strictEqual(buffer.length, 0); + assert.strictEqual(buffer.byteLength, 0); +} diff --git a/test/addons-napi/test_typedarray/test_typedarray.c b/test/addons-napi/test_typedarray/test_typedarray.c index a0ac026658..9966cad712 100644 --- a/test/addons-napi/test_typedarray/test_typedarray.c +++ b/test/addons-napi/test_typedarray/test_typedarray.c @@ -1,3 +1,4 @@ +#define NAPI_EXPERIMENTAL #include <node_api.h> #include <string.h> #include "../common.h" @@ -165,11 +166,29 @@ static napi_value CreateTypedArray(napi_env env, napi_callback_info info) { return output_array; } +static napi_value Detach(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."); + + bool is_typedarray; + NAPI_CALL(env, napi_is_typedarray(env, args[0], &is_typedarray)); + NAPI_ASSERT(env, is_typedarray, "Wrong type of arguments. Expects a typedarray as first argument."); + + napi_value arraybuffer; + NAPI_CALL(env, napi_get_typedarray_info(env, args[0], NULL, NULL, NULL, &arraybuffer, NULL)); + NAPI_CALL(env, napi_detach_arraybuffer(env, arraybuffer)); + + return NULL; +} + 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("CreateTypedArray", CreateTypedArray), + DECLARE_NAPI_PROPERTY("Detach", Detach), }; NAPI_CALL(env, napi_define_properties( |