summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlegendecas <legendecas@gmail.com>2020-04-26 00:04:17 +0800
committerRichard Lau <riclau@uk.ibm.com>2020-07-01 14:53:26 -0400
commit961598b9be34f1d70a95062633ef6f95f7aeaac3 (patch)
tree888fe919f6736d1f1fb6005825959a793b976ae0
parent3dbd8cd3a9b5786ec3ecb5fac3bec23810324678 (diff)
downloadnode-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.md27
-rw-r--r--src/node_api.cc23
-rw-r--r--src/node_api.h7
-rw-r--r--src/node_api_types.h2
-rw-r--r--test/addons-napi/test_typedarray/test.js18
-rw-r--r--test/addons-napi/test_typedarray/test_typedarray.c19
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(