Skip to content

Commit 6afed1d

Browse files
legendecasTrott
authored andcommitted
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 #29674 PR-URL: #29768 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: David Carlier <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Gabriel Schulhof <[email protected]>
1 parent f9caee9 commit 6afed1d

File tree

6 files changed

+92
-1
lines changed

6 files changed

+92
-1
lines changed

doc/api/n-api.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,8 @@ typedef enum {
371371
napi_closing,
372372
napi_bigint_expected,
373373
napi_date_expected,
374+
napi_arraybuffer_expected,
375+
napi_detachable_arraybuffer_expected,
374376
} napi_status;
375377
```
376378

@@ -3148,6 +3150,30 @@ Returns `napi_ok` if the API succeeded.
31483150
This API represents the invocation of the Strict Equality algorithm as
31493151
defined in [Section 7.2.14][] of the ECMAScript Language Specification.
31503152

3153+
### napi_detach_arraybuffer
3154+
<!-- YAML
3155+
added: REPLACEME
3156+
-->
3157+
3158+
```C
3159+
napi_status napi_detach_arraybuffer(napi_env env,
3160+
napi_value arraybuffer)
3161+
```
3162+
3163+
* `[in] env`: The environment that the API is invoked under.
3164+
* `[in] arraybuffer`: The JavaScript `ArrayBuffer` to be detached.
3165+
3166+
Returns `napi_ok` if the API succeeded. If a non-detachable `ArrayBuffer` is
3167+
passed in it returns `napi_detachable_arraybuffer_expected`.
3168+
3169+
Generally, an `ArrayBuffer` is non-detachable if it has been detached before.
3170+
The engine may impose additional conditions on whether an `ArrayBuffer` is
3171+
detachable. For example, V8 requires that the `ArrayBuffer` be external,
3172+
that is, created with [`napi_create_external_arraybuffer`][].
3173+
3174+
This API represents the invocation of the `ArrayBuffer` detach operation as
3175+
defined in [Section 24.1.1.3][] of the ECMAScript Language Specification.
3176+
31513177
## Working with JavaScript Properties
31523178

31533179
N-API exposes a set of APIs to get and set properties on JavaScript
@@ -5144,6 +5170,7 @@ This API may only be called from the main thread.
51445170
[Section 22.1.4.1]: https://tc39.github.io/ecma262/#sec-properties-of-array-instances-length
51455171
[Section 22.2]: https://tc39.github.io/ecma262/#sec-typedarray-objects
51465172
[Section 24.1]: https://tc39.github.io/ecma262/#sec-arraybuffer-objects
5173+
[Section 24.1.1.3]: https://tc39.es/ecma262/#sec-detacharraybuffer
51475174
[Section 24.3]: https://tc39.github.io/ecma262/#sec-dataview-objects
51485175
[Section 25.4]: https://tc39.github.io/ecma262/#sec-promise-objects
51495176
[`Number.MIN_SAFE_INTEGER`]: https://tc39.github.io/ecma262/#sec-number.min_safe_integer

src/js_native_api.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,10 @@ NAPI_EXTERN napi_status napi_set_instance_data(napi_env env,
514514

515515
NAPI_EXTERN napi_status napi_get_instance_data(napi_env env,
516516
void** data);
517+
518+
// ArrayBuffer detaching
519+
NAPI_EXTERN napi_status napi_detach_arraybuffer(napi_env env,
520+
napi_value arraybuffer);
517521
#endif // NAPI_EXPERIMENTAL
518522

519523
EXTERN_C_END

src/js_native_api_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ typedef enum {
8080
napi_closing,
8181
napi_bigint_expected,
8282
napi_date_expected,
83+
napi_arraybuffer_expected,
84+
napi_detachable_arraybuffer_expected,
8385
} napi_status;
8486
// Note: when adding a new enum value to `napi_status`, please also update
8587
// `const int last_status` in `napi_get_last_error_info()' definition,

src/js_native_api_v8.cc

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,8 @@ const char* error_messages[] = {nullptr,
671671
"Thread-safe function handle is closing",
672672
"A bigint was expected",
673673
"A date was expected",
674+
"An arraybuffer was expected",
675+
"A detachable arraybuffer was expected",
674676
};
675677

676678
napi_status napi_get_last_error_info(napi_env env,
@@ -682,7 +684,7 @@ napi_status napi_get_last_error_info(napi_env env,
682684
// message in the `napi_status` enum each time a new error message is added.
683685
// We don't have a napi_status_last as this would result in an ABI
684686
// change each time a message was added.
685-
const int last_status = napi_date_expected;
687+
const int last_status = napi_detachable_arraybuffer_expected;
686688

687689
static_assert(
688690
NAPI_ARRAYSIZE(error_messages) == last_status + 1,
@@ -3003,3 +3005,22 @@ napi_status napi_get_instance_data(napi_env env,
30033005

30043006
return napi_clear_last_error(env);
30053007
}
3008+
3009+
napi_status napi_detach_arraybuffer(napi_env env, napi_value arraybuffer) {
3010+
CHECK_ENV(env);
3011+
CHECK_ARG(env, arraybuffer);
3012+
3013+
v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
3014+
RETURN_STATUS_IF_FALSE(
3015+
env, value->IsArrayBuffer(), napi_arraybuffer_expected);
3016+
3017+
v8::Local<v8::ArrayBuffer> it = value.As<v8::ArrayBuffer>();
3018+
RETURN_STATUS_IF_FALSE(
3019+
env, it->IsExternal(), napi_detachable_arraybuffer_expected);
3020+
RETURN_STATUS_IF_FALSE(
3021+
env, it->IsDetachable(), napi_detachable_arraybuffer_expected);
3022+
3023+
it->Detach();
3024+
3025+
return napi_clear_last_error(env);
3026+
}

test/js-native-api/test_typedarray/test.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,21 @@ nonByteArrayTypes.forEach((currentType) => {
7474
console.log(`start of offset ${currentType}`);
7575
}, RangeError);
7676
});
77+
78+
// Test detaching
79+
arrayTypes.forEach((currentType) => {
80+
const buffer = Reflect.construct(currentType, [8]);
81+
assert.throws(
82+
() => test_typedarray.Detach(buffer),
83+
/A detachable arraybuffer was expected/);
84+
});
85+
{
86+
const buffer = test_typedarray.External();
87+
assert.ok(externalResult instanceof Int8Array);
88+
assert.strictEqual(externalResult.length, 3);
89+
assert.strictEqual(externalResult.byteLength, 3);
90+
test_typedarray.Detach(buffer);
91+
assert.ok(externalResult instanceof Int8Array);
92+
assert.strictEqual(buffer.length, 0);
93+
assert.strictEqual(buffer.byteLength, 0);
94+
}

test/js-native-api/test_typedarray/test_typedarray.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#define NAPI_EXPERIMENTAL
12
#include <js_native_api.h>
23
#include <string.h>
34
#include "../common.h"
@@ -165,12 +166,30 @@ static napi_value CreateTypedArray(napi_env env, napi_callback_info info) {
165166
return output_array;
166167
}
167168

169+
static napi_value Detach(napi_env env, napi_callback_info info) {
170+
size_t argc = 1;
171+
napi_value args[1];
172+
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
173+
NAPI_ASSERT(env, argc == 1, "Wrong number of arguments.");
174+
175+
bool is_typedarray;
176+
NAPI_CALL(env, napi_is_typedarray(env, args[0], &is_typedarray));
177+
NAPI_ASSERT(env, is_typedarray, "Wrong type of arguments. Expects a typedarray as first argument.");
178+
179+
napi_value arraybuffer;
180+
NAPI_CALL(env, napi_get_typedarray_info(env, args[0], NULL, NULL, NULL, &arraybuffer, NULL));
181+
NAPI_CALL(env, napi_detach_arraybuffer(env, arraybuffer));
182+
183+
return NULL;
184+
}
185+
168186
EXTERN_C_START
169187
napi_value Init(napi_env env, napi_value exports) {
170188
napi_property_descriptor descriptors[] = {
171189
DECLARE_NAPI_PROPERTY("Multiply", Multiply),
172190
DECLARE_NAPI_PROPERTY("External", External),
173191
DECLARE_NAPI_PROPERTY("CreateTypedArray", CreateTypedArray),
192+
DECLARE_NAPI_PROPERTY("Detach", Detach),
174193
};
175194

176195
NAPI_CALL(env, napi_define_properties(

0 commit comments

Comments
 (0)