summaryrefslogtreecommitdiff
path: root/tests/napi/src
diff options
context:
space:
mode:
authorMatt Mastracci <matthew@mastracci.com>2024-02-12 13:46:50 -0700
committerGitHub <noreply@github.com>2024-02-12 13:46:50 -0700
commitf60720090c7bd8cdf91d7aebd0c42e01c86b3b83 (patch)
tree9becb7ff7e40d37769601fa049beccd101d58a98 /tests/napi/src
parentbd1358efab8ba7339a8e70034315fa7da840292e (diff)
chore: move test_ffi and test_nap to tests/ [WIP] (#22394)
Moving some additional NAPI and. FFI tests out of the tree root.
Diffstat (limited to 'tests/napi/src')
-rw-r--r--tests/napi/src/array.rs73
-rw-r--r--tests/napi/src/arraybuffer.rs52
-rw-r--r--tests/napi/src/async.rs114
-rw-r--r--tests/napi/src/bigint.rs205
-rw-r--r--tests/napi/src/callback.rs117
-rw-r--r--tests/napi/src/coerce.rs70
-rw-r--r--tests/napi/src/date.rs74
-rw-r--r--tests/napi/src/env.rs31
-rw-r--r--tests/napi/src/error.rs288
-rw-r--r--tests/napi/src/finalizer.rs141
-rw-r--r--tests/napi/src/lib.rs171
-rw-r--r--tests/napi/src/make_callback.rs85
-rw-r--r--tests/napi/src/mem.rs34
-rw-r--r--tests/napi/src/numbers.rs60
-rw-r--r--tests/napi/src/object_wrap.rs156
-rw-r--r--tests/napi/src/primitives.rs30
-rw-r--r--tests/napi/src/promise.rs74
-rw-r--r--tests/napi/src/properties.rs113
-rw-r--r--tests/napi/src/strings.rs49
-rw-r--r--tests/napi/src/symbol.rs39
-rw-r--r--tests/napi/src/tsfn.rs108
-rw-r--r--tests/napi/src/typedarray.rs157
22 files changed, 2241 insertions, 0 deletions
diff --git a/tests/napi/src/array.rs b/tests/napi/src/array.rs
new file mode 100644
index 000000000..6df420eb5
--- /dev/null
+++ b/tests/napi/src/array.rs
@@ -0,0 +1,73 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::napi_get_callback_info;
+use crate::napi_new_property;
+use napi_sys::ValueType::napi_number;
+use napi_sys::ValueType::napi_object;
+use napi_sys::*;
+use std::ptr;
+
+extern "C" fn test_array_new(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[0], &mut ty));
+ assert_eq!(ty, napi_object);
+
+ let mut value: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_array(env, &mut value));
+
+ let mut length: u32 = 0;
+ assert_napi_ok!(napi_get_array_length(env, args[0], &mut length));
+
+ for i in 0..length {
+ let mut e: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_get_element(env, args[0], i, &mut e));
+ assert_napi_ok!(napi_set_element(env, value, i, e));
+ }
+
+ value
+}
+
+extern "C" fn test_array_new_with_length(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[0], &mut ty));
+ assert_eq!(ty, napi_number);
+
+ let mut len: u32 = 0;
+ assert_napi_ok!(napi_get_value_uint32(env, args[0], &mut len));
+
+ let mut value: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_array_with_length(env, len as usize, &mut value));
+
+ value
+}
+
+pub fn init(env: napi_env, exports: napi_value) {
+ let properties = &[
+ napi_new_property!(env, "test_array_new", test_array_new),
+ napi_new_property!(
+ env,
+ "test_array_new_with_length",
+ test_array_new_with_length
+ ),
+ ];
+
+ assert_napi_ok!(napi_define_properties(
+ env,
+ exports,
+ properties.len(),
+ properties.as_ptr()
+ ));
+}
diff --git a/tests/napi/src/arraybuffer.rs b/tests/napi/src/arraybuffer.rs
new file mode 100644
index 000000000..8402f5d86
--- /dev/null
+++ b/tests/napi/src/arraybuffer.rs
@@ -0,0 +1,52 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::napi_get_callback_info;
+use crate::napi_new_property;
+use napi_sys::*;
+
+extern "C" fn test_detached(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ let mut value = false;
+ assert_napi_ok!(napi_is_detached_arraybuffer(env, args[0], &mut value));
+ assert!(!value);
+ assert_napi_ok!(napi_detach_arraybuffer(env, args[0]));
+ assert_napi_ok!(napi_is_detached_arraybuffer(env, args[0], &mut value));
+ assert!(value);
+ args[0]
+}
+
+extern "C" fn is_detached(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ let mut value = false;
+ assert_napi_ok!(napi_is_detached_arraybuffer(env, args[0], &mut value));
+
+ let mut result = std::ptr::null_mut();
+ assert_napi_ok!(napi_get_boolean(env, value, &mut result));
+
+ result
+}
+
+pub fn init(env: napi_env, exports: napi_value) {
+ let properties = &[
+ napi_new_property!(env, "test_detached", test_detached),
+ napi_new_property!(env, "is_detached", is_detached),
+ ];
+
+ assert_napi_ok!(napi_define_properties(
+ env,
+ exports,
+ properties.len(),
+ properties.as_ptr()
+ ));
+}
diff --git a/tests/napi/src/async.rs b/tests/napi/src/async.rs
new file mode 100644
index 000000000..3d3827b51
--- /dev/null
+++ b/tests/napi/src/async.rs
@@ -0,0 +1,114 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::napi_get_callback_info;
+use crate::napi_new_property;
+use napi_sys::Status::napi_ok;
+use napi_sys::ValueType::napi_function;
+use napi_sys::*;
+use std::os::raw::c_char;
+use std::os::raw::c_void;
+use std::ptr;
+
+pub struct Baton {
+ called: bool,
+ func: napi_ref,
+ task: napi_async_work,
+}
+
+unsafe extern "C" fn execute(_env: napi_env, data: *mut c_void) {
+ let baton: &mut Baton = &mut *(data as *mut Baton);
+ assert!(!baton.called);
+ assert!(!baton.func.is_null());
+
+ baton.called = true;
+}
+
+unsafe extern "C" fn complete(
+ env: napi_env,
+ status: napi_status,
+ data: *mut c_void,
+) {
+ assert!(status == napi_ok);
+ let baton: Box<Baton> = Box::from_raw(data as *mut Baton);
+ assert!(baton.called);
+ assert!(!baton.func.is_null());
+
+ let mut global: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_get_global(env, &mut global));
+
+ let mut callback: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_get_reference_value(env, baton.func, &mut callback));
+
+ let mut _result: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_call_function(
+ env,
+ global,
+ callback,
+ 0,
+ ptr::null(),
+ &mut _result
+ ));
+ assert_napi_ok!(napi_delete_reference(env, baton.func));
+ assert_napi_ok!(napi_delete_async_work(env, baton.task));
+}
+
+extern "C" fn test_async_work(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[0], &mut ty));
+ assert_eq!(ty, napi_function);
+
+ let mut resource_name: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_string_utf8(
+ env,
+ "test_async_resource".as_ptr() as *const c_char,
+ usize::MAX,
+ &mut resource_name,
+ ));
+
+ let async_work: napi_async_work = ptr::null_mut();
+
+ let mut func: napi_ref = ptr::null_mut();
+ assert_napi_ok!(napi_create_reference(env, args[0], 1, &mut func));
+ let baton = Box::new(Baton {
+ called: false,
+ func,
+ task: async_work,
+ });
+ let mut async_work = baton.task;
+ let baton_ptr = Box::into_raw(baton) as *mut c_void;
+
+ assert_napi_ok!(napi_create_async_work(
+ env,
+ ptr::null_mut(),
+ resource_name,
+ Some(execute),
+ Some(complete),
+ baton_ptr,
+ &mut async_work,
+ ));
+ let mut baton = unsafe { Box::from_raw(baton_ptr as *mut Baton) };
+ baton.task = async_work;
+ Box::into_raw(baton);
+ assert_napi_ok!(napi_queue_async_work(env, async_work));
+
+ ptr::null_mut()
+}
+
+pub fn init(env: napi_env, exports: napi_value) {
+ let properties =
+ &[napi_new_property!(env, "test_async_work", test_async_work)];
+
+ assert_napi_ok!(napi_define_properties(
+ env,
+ exports,
+ properties.len(),
+ properties.as_ptr()
+ ));
+}
diff --git a/tests/napi/src/bigint.rs b/tests/napi/src/bigint.rs
new file mode 100644
index 000000000..d86782331
--- /dev/null
+++ b/tests/napi/src/bigint.rs
@@ -0,0 +1,205 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::cstr;
+use crate::napi_get_callback_info;
+use crate::napi_new_property;
+use napi_sys::Status::napi_pending_exception;
+use napi_sys::ValueType::napi_bigint;
+use napi_sys::*;
+use std::ptr;
+
+extern "C" fn is_lossless(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 2);
+ assert_eq!(argc, 2);
+
+ let mut is_signed = false;
+ assert_napi_ok!(napi_get_value_bool(env, args[1], &mut is_signed));
+
+ let mut lossless = false;
+
+ if is_signed {
+ let mut input: i64 = 0;
+ assert_napi_ok!(napi_get_value_bigint_int64(
+ env,
+ args[0],
+ &mut input,
+ &mut lossless
+ ));
+ } else {
+ let mut input: u64 = 0;
+ assert_napi_ok!(napi_get_value_bigint_uint64(
+ env,
+ args[0],
+ &mut input,
+ &mut lossless
+ ));
+ }
+
+ let mut output: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_get_boolean(env, lossless, &mut output));
+
+ output
+}
+
+extern "C" fn test_int64(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, _argc, _) = napi_get_callback_info!(env, info, 2);
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[0], &mut ty));
+ assert_eq!(ty, napi_bigint);
+
+ let mut input: i64 = 0;
+ let mut lossless = false;
+ assert_napi_ok!(napi_get_value_bigint_int64(
+ env,
+ args[0],
+ &mut input,
+ &mut lossless
+ ));
+
+ let mut output: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_bigint_int64(env, input, &mut output));
+
+ output
+}
+
+extern "C" fn test_uint64(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, _argc, _) = napi_get_callback_info!(env, info, 2);
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[0], &mut ty));
+ assert_eq!(ty, napi_bigint);
+
+ let mut input: u64 = 0;
+ let mut lossless = false;
+ assert_napi_ok!(napi_get_value_bigint_uint64(
+ env,
+ args[0],
+ &mut input,
+ &mut lossless
+ ));
+
+ let mut output: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_bigint_uint64(env, input, &mut output));
+
+ output
+}
+
+extern "C" fn test_words(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, _argc, _) = napi_get_callback_info!(env, info, 1);
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[0], &mut ty));
+ assert_eq!(ty, napi_bigint);
+
+ let mut expected_work_count = 0;
+ assert_napi_ok!(napi_get_value_bigint_words(
+ env,
+ args[0],
+ ptr::null_mut(),
+ &mut expected_work_count,
+ ptr::null_mut()
+ ));
+
+ let mut sign_bit = 0;
+ let mut word_count: usize = 10;
+ let mut words: Vec<u64> = Vec::with_capacity(10);
+
+ assert_napi_ok!(napi_get_value_bigint_words(
+ env,
+ args[0],
+ &mut sign_bit,
+ &mut word_count,
+ words.as_mut_ptr(),
+ ));
+
+ assert_eq!(word_count, expected_work_count);
+ let mut output: napi_value = ptr::null_mut();
+
+ assert_napi_ok!(napi_create_bigint_words(
+ env,
+ sign_bit,
+ word_count,
+ words.as_ptr(),
+ &mut output,
+ ));
+ output
+}
+
+extern "C" fn create_too_big_big_int(
+ env: napi_env,
+ _info: napi_callback_info,
+) -> napi_value {
+ let sign_bit = 0;
+ let word_count = usize::MAX;
+ let words: Vec<u64> = Vec::with_capacity(10);
+
+ let mut output: napi_value = ptr::null_mut();
+ let result = unsafe {
+ napi_create_bigint_words(
+ env,
+ sign_bit,
+ word_count,
+ words.as_ptr(),
+ &mut output,
+ )
+ };
+ assert_eq!(result, 1);
+
+ output
+}
+
+extern "C" fn make_big_int_words_throw(
+ env: napi_env,
+ _info: napi_callback_info,
+) -> napi_value {
+ let words: Vec<u64> = Vec::with_capacity(10);
+ let mut output = ptr::null_mut();
+
+ let status = unsafe {
+ napi_create_bigint_words(env, 0, usize::MAX, words.as_ptr(), &mut output)
+ };
+
+ if status != napi_pending_exception {
+ unsafe {
+ napi_throw_error(
+ env,
+ ptr::null_mut(),
+ cstr!("Expected status 'napi_pending_exception'"),
+ )
+ };
+ }
+
+ ptr::null_mut()
+}
+
+pub fn init(env: napi_env, exports: napi_value) {
+ let properties = &[
+ napi_new_property!(env, "isLossless", is_lossless),
+ napi_new_property!(env, "testInt64", test_int64),
+ napi_new_property!(env, "testUint64", test_uint64),
+ napi_new_property!(env, "testWords", test_words),
+ napi_new_property!(env, "createTooBigBigInt", create_too_big_big_int),
+ napi_new_property!(env, "makeBigIntWordsThrow", make_big_int_words_throw),
+ ];
+
+ assert_napi_ok!(napi_define_properties(
+ env,
+ exports,
+ properties.len(),
+ properties.as_ptr()
+ ));
+}
diff --git a/tests/napi/src/callback.rs b/tests/napi/src/callback.rs
new file mode 100644
index 000000000..8909f5176
--- /dev/null
+++ b/tests/napi/src/callback.rs
@@ -0,0 +1,117 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::napi_get_callback_info;
+use crate::napi_new_property;
+use napi_sys::ValueType::napi_function;
+use napi_sys::ValueType::napi_object;
+use napi_sys::ValueType::napi_undefined;
+use napi_sys::*;
+use std::ptr;
+
+/// `test_callback_run((a, b) => a + b, [1, 2])` => 3
+extern "C" fn test_callback_run(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ // We want to have argv with size 4, even though the callback will have
+ // only two arguments. We'll assert that the remaining two args are undefined.
+ let (args, argc, _) = napi_get_callback_info!(env, info, 4);
+ assert_eq!(argc, 2);
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[0], &mut ty));
+ assert_eq!(ty, napi_function);
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[1], &mut ty));
+ assert_eq!(ty, napi_object);
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[2], &mut ty));
+ assert_eq!(ty, napi_undefined);
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[3], &mut ty));
+ assert_eq!(ty, napi_undefined);
+
+ let mut len = 0;
+ assert_napi_ok!(napi_get_array_length(env, args[1], &mut len));
+
+ let mut argv = Vec::with_capacity(len as usize);
+ for index in 0..len {
+ let mut value: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_get_element(env, args[1], index, &mut value));
+ argv.push(value);
+ }
+ let mut global: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_get_global(env, &mut global));
+
+ let mut result: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_call_function(
+ env,
+ global,
+ args[0],
+ argv.len(),
+ argv.as_mut_ptr(),
+ &mut result,
+ ));
+
+ result
+}
+
+extern "C" fn test_callback_run_with_recv(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 3);
+ assert_eq!(argc, 3);
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[0], &mut ty));
+ assert_eq!(ty, napi_function);
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[1], &mut ty));
+ assert_eq!(ty, napi_object);
+
+ let mut len = 0;
+ assert_napi_ok!(napi_get_array_length(env, args[1], &mut len));
+
+ let mut argv = Vec::with_capacity(len as usize);
+ for index in 0..len {
+ let mut value: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_get_element(env, args[1], index, &mut value));
+ argv.push(value);
+ }
+
+ let mut result: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_call_function(
+ env,
+ args[2], // recv
+ args[0], // cb
+ argv.len(),
+ argv.as_mut_ptr(),
+ &mut result,
+ ));
+
+ result
+}
+
+pub fn init(env: napi_env, exports: napi_value) {
+ let properties = &[
+ napi_new_property!(env, "test_callback_run", test_callback_run),
+ napi_new_property!(
+ env,
+ "test_callback_run_with_recv",
+ test_callback_run_with_recv
+ ),
+ ];
+
+ assert_napi_ok!(napi_define_properties(
+ env,
+ exports,
+ properties.len(),
+ properties.as_ptr()
+ ));
+}
diff --git a/tests/napi/src/coerce.rs b/tests/napi/src/coerce.rs
new file mode 100644
index 000000000..a40578384
--- /dev/null
+++ b/tests/napi/src/coerce.rs
@@ -0,0 +1,70 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::napi_get_callback_info;
+use crate::napi_new_property;
+use napi_sys::*;
+use std::ptr;
+
+extern "C" fn test_coerce_bool(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ let mut value: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_coerce_to_bool(env, args[0], &mut value));
+ value
+}
+
+extern "C" fn test_coerce_number(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ let mut value: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_coerce_to_number(env, args[0], &mut value));
+ value
+}
+
+extern "C" fn test_coerce_object(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ let mut value: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_coerce_to_object(env, args[0], &mut value));
+ value
+}
+
+extern "C" fn test_coerce_string(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ let mut value: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_coerce_to_string(env, args[0], &mut value));
+ value
+}
+pub fn init(env: napi_env, exports: napi_value) {
+ let properties = &[
+ napi_new_property!(env, "test_coerce_bool", test_coerce_bool),
+ napi_new_property!(env, "test_coerce_number", test_coerce_number),
+ napi_new_property!(env, "test_coerce_object", test_coerce_object),
+ napi_new_property!(env, "test_coerce_string", test_coerce_string),
+ ];
+
+ assert_napi_ok!(napi_define_properties(
+ env,
+ exports,
+ properties.len(),
+ properties.as_ptr()
+ ));
+}
diff --git a/tests/napi/src/date.rs b/tests/napi/src/date.rs
new file mode 100644
index 000000000..4d3c155c3
--- /dev/null
+++ b/tests/napi/src/date.rs
@@ -0,0 +1,74 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::napi_get_callback_info;
+use crate::napi_new_property;
+use napi_sys::ValueType::napi_number;
+use napi_sys::*;
+use std::ptr;
+
+extern "C" fn create_date(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[0], &mut ty));
+ assert_eq!(ty, napi_number);
+
+ let mut time = -1.0;
+ assert_napi_ok!(napi_get_value_double(env, args[0], &mut time));
+
+ let mut date: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_date(env, time, &mut date));
+
+ date
+}
+
+extern "C" fn is_date(env: napi_env, info: napi_callback_info) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ let date: napi_value = args[0];
+ let mut result: napi_value = std::ptr::null_mut();
+ let mut is_date = false;
+
+ assert_napi_ok!(napi_is_date(env, date, &mut is_date));
+ assert_napi_ok!(napi_get_boolean(env, is_date, &mut result));
+
+ result
+}
+
+extern "C" fn get_date_value(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ let date: napi_value = args[0];
+ let mut result: napi_value = std::ptr::null_mut();
+ let mut value = 0.0;
+
+ assert_napi_ok!(napi_get_date_value(env, date, &mut value));
+ assert_napi_ok!(napi_create_double(env, value, &mut result));
+
+ result
+}
+
+pub fn init(env: napi_env, exports: napi_value) {
+ let properties = &[
+ napi_new_property!(env, "createDate", create_date),
+ napi_new_property!(env, "isDate", is_date),
+ napi_new_property!(env, "getDateValue", get_date_value),
+ ];
+
+ assert_napi_ok!(napi_define_properties(
+ env,
+ exports,
+ properties.len(),
+ properties.as_ptr()
+ ));
+}
diff --git a/tests/napi/src/env.rs b/tests/napi/src/env.rs
new file mode 100644
index 000000000..ebc6532a3
--- /dev/null
+++ b/tests/napi/src/env.rs
@@ -0,0 +1,31 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::napi_get_callback_info;
+use crate::napi_new_property;
+use napi_sys::*;
+
+extern "C" fn get_node_global(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (_, argc, _) = napi_get_callback_info!(env, info, 0);
+ assert_eq!(argc, 0);
+
+ let mut result: napi_value = std::ptr::null_mut();
+ assert_napi_ok!(napi_get_global(env, &mut result));
+
+ result
+}
+
+pub fn init(env: napi_env, exports: napi_value) {
+ let properties =
+ &[napi_new_property!(env, "testNodeGlobal", get_node_global)];
+
+ assert_napi_ok!(napi_define_properties(
+ env,
+ exports,
+ properties.len(),
+ properties.as_ptr()
+ ));
+}
diff --git a/tests/napi/src/error.rs b/tests/napi/src/error.rs
new file mode 100644
index 000000000..e0d79c836
--- /dev/null
+++ b/tests/napi/src/error.rs
@@ -0,0 +1,288 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::cstr;
+use crate::napi_get_callback_info;
+use crate::napi_new_property;
+use napi_sys::*;
+use std::ptr;
+
+extern "C" fn check_error(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+ let mut r = false;
+ assert_napi_ok!(napi_is_error(env, args[0], &mut r));
+ let mut result: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_get_boolean(env, r, &mut result));
+ result
+}
+
+extern "C" fn create_error(
+ env: napi_env,
+ _info: napi_callback_info,
+) -> napi_value {
+ let mut result: napi_value = ptr::null_mut();
+ let mut message: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_string_utf8(
+ env,
+ cstr!("error"),
+ usize::MAX,
+ &mut message
+ ));
+ assert_napi_ok!(napi_create_error(
+ env,
+ ptr::null_mut(),
+ message,
+ &mut result
+ ));
+ result
+}
+
+extern "C" fn create_range_error(
+ env: napi_env,
+ _info: napi_callback_info,
+) -> napi_value {
+ let mut result: napi_value = ptr::null_mut();
+ let mut message: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_string_utf8(
+ env,
+ cstr!("range error"),
+ usize::MAX,
+ &mut message
+ ));
+ assert_napi_ok!(napi_create_range_error(
+ env,
+ ptr::null_mut(),
+ message,
+ &mut result
+ ));
+ result
+}
+
+extern "C" fn create_type_error(
+ env: napi_env,
+ _info: napi_callback_info,
+) -> napi_value {
+ let mut result: napi_value = ptr::null_mut();
+ let mut message: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_string_utf8(
+ env,
+ cstr!("type error"),
+ usize::MAX,
+ &mut message
+ ));
+ assert_napi_ok!(napi_create_type_error(
+ env,
+ ptr::null_mut(),
+ message,
+ &mut result
+ ));
+ result
+}
+
+extern "C" fn create_error_code(
+ env: napi_env,
+ _info: napi_callback_info,
+) -> napi_value {
+ let mut result: napi_value = ptr::null_mut();
+ let mut message: napi_value = ptr::null_mut();
+ let mut code: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_string_utf8(
+ env,
+ cstr!("Error [error]"),
+ usize::MAX,
+ &mut message
+ ));
+ assert_napi_ok!(napi_create_string_utf8(
+ env,
+ cstr!("ERR_TEST_CODE"),
+ usize::MAX,
+ &mut code
+ ));
+ assert_napi_ok!(napi_create_error(env, code, message, &mut result));
+ result
+}
+
+extern "C" fn create_range_error_code(
+ env: napi_env,
+ _info: napi_callback_info,
+) -> napi_value {
+ let mut result: napi_value = ptr::null_mut();
+ let mut message: napi_value = ptr::null_mut();
+ let mut code: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_string_utf8(
+ env,
+ cstr!("RangeError [range error]"),
+ usize::MAX,
+ &mut message
+ ));
+ assert_napi_ok!(napi_create_string_utf8(
+ env,
+ cstr!("ERR_TEST_CODE"),
+ usize::MAX,
+ &mut code
+ ));
+ assert_napi_ok!(napi_create_range_error(env, code, message, &mut result));
+ result
+}
+
+extern "C" fn create_type_error_code(
+ env: napi_env,
+ _info: napi_callback_info,
+) -> napi_value {
+ let mut result: napi_value = ptr::null_mut();
+ let mut message: napi_value = ptr::null_mut();
+ let mut code: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_string_utf8(
+ env,
+ cstr!("TypeError [type error]"),
+ usize::MAX,
+ &mut message
+ ));
+ assert_napi_ok!(napi_create_string_utf8(
+ env,
+ cstr!("ERR_TEST_CODE"),
+ usize::MAX,
+ &mut code
+ ));
+ assert_napi_ok!(napi_create_type_error(env, code, message, &mut result));
+ result
+}
+
+extern "C" fn throw_existing_error(
+ env: napi_env,
+ _info: napi_callback_info,
+) -> napi_value {
+ let mut message: napi_value = ptr::null_mut();
+ let mut error: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_string_utf8(
+ env,
+ cstr!("existing error"),
+ usize::MAX,
+ &mut message
+ ));
+ assert_napi_ok!(napi_create_error(
+ env,
+ std::ptr::null_mut(),
+ message,
+ &mut error
+ ));
+ assert_napi_ok!(napi_throw(env, error));
+ std::ptr::null_mut()
+}
+
+extern "C" fn throw_error(
+ env: napi_env,
+ _info: napi_callback_info,
+) -> napi_value {
+ assert_napi_ok!(napi_throw_error(env, std::ptr::null_mut(), cstr!("error"),));
+ std::ptr::null_mut()
+}
+
+extern "C" fn throw_range_error(
+ env: napi_env,
+ _info: napi_callback_info,
+) -> napi_value {
+ assert_napi_ok!(napi_throw_range_error(
+ env,
+ std::ptr::null_mut(),
+ cstr!("range error"),
+ ));
+ std::ptr::null_mut()
+}
+
+extern "C" fn throw_type_error(
+ env: napi_env,
+ _info: napi_callback_info,
+) -> napi_value {
+ assert_napi_ok!(napi_throw_type_error(
+ env,
+ std::ptr::null_mut(),
+ cstr!("type error"),
+ ));
+ std::ptr::null_mut()
+}
+
+extern "C" fn throw_arbitrary(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+ assert_napi_ok!(napi_throw(env, args[0]));
+ std::ptr::null_mut()
+}
+
+extern "C" fn throw_error_code(
+ env: napi_env,
+ _info: napi_callback_info,
+) -> napi_value {
+ assert_napi_ok!(napi_throw_error(
+ env,
+ cstr!("ERR_TEST_CODE"),
+ cstr!("Error [error]"),
+ ));
+ std::ptr::null_mut()
+}
+
+extern "C" fn throw_range_error_code(
+ env: napi_env,
+ _info: napi_callback_info,
+) -> napi_value {
+ assert_napi_ok!(napi_throw_range_error(
+ env,
+ cstr!("ERR_TEST_CODE"),
+ cstr!("RangeError [range error]"),
+ ));
+ std::ptr::null_mut()
+}
+
+extern "C" fn throw_type_error_code(
+ env: napi_env,
+ _info: napi_callback_info,
+) -> napi_value {
+ assert_napi_ok!(napi_throw_type_error(
+ env,
+ cstr!("ERR_TEST_CODE"),
+ cstr!("TypeError [type error]"),
+ ));
+ std::ptr::null_mut()
+}
+
+pub fn init(env: napi_env, exports: napi_value) {
+ let properties = &[
+ napi_new_property!(env, "checkError", check_error),
+ napi_new_property!(env, "throwExistingError", throw_existing_error),
+ napi_new_property!(env, "throwError", throw_error),
+ napi_new_property!(env, "throwRangeError", throw_range_error),
+ napi_new_property!(env, "throwTypeError", throw_type_error),
+ // NOTE(bartlomieju): currently experimental api
+ // napi_new_property!(env, "throwSyntaxError", throw_syntax_error),
+ napi_new_property!(env, "throwErrorCode", throw_error_code),
+ napi_new_property!(env, "throwRangeErrorCode", throw_range_error_code),
+ napi_new_property!(env, "throwTypeErrorCode", throw_type_error_code),
+ // NOTE(bartlomieju): currently experimental api
+ // napi_new_property!(env, "throwSyntaxErrorCode", throw_syntax_error_code),
+ napi_new_property!(env, "throwArbitrary", throw_arbitrary),
+ napi_new_property!(env, "createError", create_error),
+ napi_new_property!(env, "createRangeError", create_range_error),
+ napi_new_property!(env, "createTypeError", create_type_error),
+ // NOTE(bartlomieju): currently experimental api
+ // napi_new_property!(env, "createSyntaxError", create_syntax_error),
+ napi_new_property!(env, "createErrorCode", create_error_code),
+ napi_new_property!(env, "createRangeErrorCode", create_range_error_code),
+ napi_new_property!(env, "createTypeErrorCode", create_type_error_code),
+ // NOTE(bartlomieju): currently experimental api
+ // napi_new_property!(env, "createSyntaxErrorCode", create_syntax_error_code),
+ ];
+
+ assert_napi_ok!(napi_define_properties(
+ env,
+ exports,
+ properties.len(),
+ properties.as_ptr()
+ ));
+}
diff --git a/tests/napi/src/finalizer.rs b/tests/napi/src/finalizer.rs
new file mode 100644
index 000000000..9769e775e
--- /dev/null
+++ b/tests/napi/src/finalizer.rs
@@ -0,0 +1,141 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::napi_get_callback_info;
+use crate::napi_new_property;
+use napi_sys::ValueType::napi_object;
+use napi_sys::*;
+use std::ptr;
+
+unsafe extern "C" fn finalize_cb(
+ _env: napi_env,
+ data: *mut ::std::os::raw::c_void,
+ hint: *mut ::std::os::raw::c_void,
+) {
+ assert!(data.is_null());
+ assert!(hint.is_null());
+}
+
+extern "C" fn test_bind_finalizer(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[0], &mut ty));
+ assert_eq!(ty, napi_object);
+
+ let obj = args[0];
+ unsafe {
+ napi_add_finalizer(
+ env,
+ obj,
+ ptr::null_mut(),
+ Some(finalize_cb),
+ ptr::null_mut(),
+ ptr::null_mut(),
+ )
+ };
+ obj
+}
+
+struct Thing {
+ _allocation: Vec<u8>,
+}
+
+unsafe extern "C" fn finalize_cb_drop(
+ _env: napi_env,
+ data: *mut ::std::os::raw::c_void,
+ hint: *mut ::std::os::raw::c_void,
+) {
+ let _ = Box::from_raw(data as *mut Thing);
+ assert!(hint.is_null());
+}
+
+extern "C" fn test_external_finalizer(
+ env: napi_env,
+ _: napi_callback_info,
+) -> napi_value {
+ let data = Box::into_raw(Box::new(Thing {
+ _allocation: vec![1, 2, 3],
+ }));
+
+ let mut result = ptr::null_mut();
+ assert_napi_ok!(napi_create_external(
+ env,
+ data as _,
+ Some(finalize_cb_drop),
+ ptr::null_mut(),
+ &mut result
+ ));
+ result
+}
+
+unsafe extern "C" fn finalize_cb_vec(
+ _env: napi_env,
+ data: *mut ::std::os::raw::c_void,
+ hint: *mut ::std::os::raw::c_void,
+) {
+ let _ = Vec::from_raw_parts(data as *mut u8, 3, 3);
+ assert!(hint.is_null());
+}
+
+extern "C" fn test_external_buffer(
+ env: napi_env,
+ _: napi_callback_info,
+) -> napi_value {
+ let mut result = ptr::null_mut();
+ let buf: Vec<u8> = vec![1, 2, 3];
+ assert_napi_ok!(napi_create_external_buffer(
+ env,
+ 3,
+ buf.as_ptr() as _,
+ Some(finalize_cb_vec),
+ ptr::null_mut(),
+ &mut result
+ ));
+ std::mem::forget(buf);
+
+ result
+}
+
+extern "C" fn test_external_arraybuffer(
+ env: napi_env,
+ _: napi_callback_info,
+) -> napi_value {
+ let mut result = ptr::null_mut();
+ let buf: Vec<u8> = vec![1, 2, 3];
+ assert_napi_ok!(napi_create_external_arraybuffer(
+ env,
+ buf.as_ptr() as _,
+ 3,
+ Some(finalize_cb_vec),
+ ptr::null_mut(),
+ &mut result
+ ));
+ std::mem::forget(buf);
+
+ result
+}
+
+pub fn init(env: napi_env, exports: napi_value) {
+ let properties = &[
+ napi_new_property!(env, "test_bind_finalizer", test_bind_finalizer),
+ napi_new_property!(env, "test_external_finalizer", test_external_finalizer),
+ napi_new_property!(env, "test_external_buffer", test_external_buffer),
+ napi_new_property!(
+ env,
+ "test_external_arraybuffer",
+ test_external_arraybuffer
+ ),
+ ];
+
+ assert_napi_ok!(napi_define_properties(
+ env,
+ exports,
+ properties.len(),
+ properties.as_ptr()
+ ));
+}
diff --git a/tests/napi/src/lib.rs b/tests/napi/src/lib.rs
new file mode 100644
index 000000000..b9f93fbd6
--- /dev/null
+++ b/tests/napi/src/lib.rs
@@ -0,0 +1,171 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+#![allow(clippy::all)]
+#![allow(clippy::undocumented_unsafe_blocks)]
+
+use std::ffi::c_void;
+
+use napi_sys::*;
+
+pub mod array;
+pub mod arraybuffer;
+pub mod r#async;
+pub mod bigint;
+pub mod callback;
+pub mod coerce;
+pub mod date;
+pub mod env;
+pub mod error;
+pub mod finalizer;
+pub mod make_callback;
+pub mod mem;
+pub mod numbers;
+pub mod object_wrap;
+pub mod primitives;
+pub mod promise;
+pub mod properties;
+pub mod strings;
+pub mod symbol;
+pub mod tsfn;
+pub mod typedarray;
+
+#[macro_export]
+macro_rules! cstr {
+ ($s: literal) => {{
+ std::ffi::CString::new($s).unwrap().into_raw()
+ }};
+}
+
+#[macro_export]
+macro_rules! assert_napi_ok {
+ ($call: expr) => {{
+ assert_eq!(unsafe { $call }, napi_sys::Status::napi_ok);
+ }};
+}
+
+#[macro_export]
+macro_rules! napi_get_callback_info {
+ ($env: expr, $callback_info: expr, $size: literal) => {{
+ let mut args = [std::ptr::null_mut(); $size];
+ let mut argc = $size;
+ let mut this = std::ptr::null_mut();
+ crate::assert_napi_ok!(napi_get_cb_info(
+ $env,
+ $callback_info,
+ &mut argc,
+ args.as_mut_ptr(),
+ &mut this,
+ std::ptr::null_mut(),
+ ));
+ (args, argc, this)
+ }};
+}
+
+#[macro_export]
+macro_rules! napi_new_property {
+ ($env: expr, $name: expr, $value: expr) => {
+ napi_property_descriptor {
+ utf8name: concat!($name, "\0").as_ptr() as *const std::os::raw::c_char,
+ name: std::ptr::null_mut(),
+ method: Some($value),
+ getter: None,
+ setter: None,
+ data: std::ptr::null_mut(),
+ attributes: 0,
+ value: std::ptr::null_mut(),
+ }
+ };
+}
+
+extern "C" fn cleanup(arg: *mut c_void) {
+ println!("cleanup({})", arg as i64);
+}
+
+extern "C" fn remove_this_hook(arg: *mut c_void) {
+ let env = arg as napi_env;
+ unsafe { napi_remove_env_cleanup_hook(env, Some(remove_this_hook), arg) };
+}
+
+static SECRET: i64 = 42;
+static WRONG_SECRET: i64 = 17;
+static THIRD_SECRET: i64 = 18;
+
+extern "C" fn install_cleanup_hook(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (_args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 0);
+
+ unsafe {
+ napi_add_env_cleanup_hook(env, Some(cleanup), WRONG_SECRET as *mut c_void);
+ napi_add_env_cleanup_hook(env, Some(cleanup), SECRET as *mut c_void);
+ napi_add_env_cleanup_hook(env, Some(cleanup), THIRD_SECRET as *mut c_void);
+ napi_add_env_cleanup_hook(env, Some(remove_this_hook), env as *mut c_void);
+ napi_remove_env_cleanup_hook(
+ env,
+ Some(cleanup),
+ WRONG_SECRET as *mut c_void,
+ );
+ }
+
+ std::ptr::null_mut()
+}
+
+pub fn init_cleanup_hook(env: napi_env, exports: napi_value) {
+ let properties = &[napi_new_property!(
+ env,
+ "installCleanupHook",
+ install_cleanup_hook
+ )];
+
+ assert_napi_ok!(napi_define_properties(
+ env,
+ exports,
+ properties.len(),
+ properties.as_ptr()
+ ));
+}
+
+#[no_mangle]
+unsafe extern "C" fn napi_register_module_v1(
+ env: napi_env,
+ _: napi_value,
+) -> napi_value {
+ #[cfg(windows)]
+ {
+ napi_sys::setup();
+ }
+
+ // We create a fresh exports object and leave the passed
+ // exports object empty.
+ //
+ // https://github.com/denoland/deno/issues/17349
+ let mut exports = std::ptr::null_mut();
+ assert_napi_ok!(napi_create_object(env, &mut exports));
+
+ strings::init(env, exports);
+ numbers::init(env, exports);
+ typedarray::init(env, exports);
+ arraybuffer::init(env, exports);
+ array::init(env, exports);
+ env::init(env, exports);
+ error::init(env, exports);
+ finalizer::init(env, exports);
+ primitives::init(env, exports);
+ properties::init(env, exports);
+ promise::init(env, exports);
+ coerce::init(env, exports);
+ object_wrap::init(env, exports);
+ callback::init(env, exports);
+ r#async::init(env, exports);
+ date::init(env, exports);
+ tsfn::init(env, exports);
+ mem::init(env, exports);
+ bigint::init(env, exports);
+ symbol::init(env, exports);
+ make_callback::init(env, exports);
+
+ init_cleanup_hook(env, exports);
+
+ exports
+}
diff --git a/tests/napi/src/make_callback.rs b/tests/napi/src/make_callback.rs
new file mode 100644
index 000000000..945df3452
--- /dev/null
+++ b/tests/napi/src/make_callback.rs
@@ -0,0 +1,85 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::cstr;
+use napi_sys::ValueType::napi_function;
+use napi_sys::*;
+use std::ptr;
+
+extern "C" fn make_callback(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ const MAX_ARGUMENTS: usize = 10;
+ const RESERVED_ARGUMENTS: usize = 3;
+
+ let mut args = [std::ptr::null_mut(); MAX_ARGUMENTS];
+ let mut argc = MAX_ARGUMENTS;
+ assert_napi_ok!(napi_get_cb_info(
+ env,
+ info,
+ &mut argc,
+ args.as_mut_ptr(),
+ ptr::null_mut(),
+ ptr::null_mut(),
+ ));
+
+ assert!(argc > 0);
+ let resource = args[0];
+ let recv = args[1];
+ let func = args[2];
+
+ let mut argv: Vec<napi_value> = Vec::new();
+ argv.resize(MAX_ARGUMENTS - RESERVED_ARGUMENTS, ptr::null_mut());
+ for i in RESERVED_ARGUMENTS..argc {
+ argv[i - RESERVED_ARGUMENTS] = args[i];
+ }
+
+ let mut func_type: napi_valuetype = -1;
+ assert_napi_ok!(napi_typeof(env, func, &mut func_type));
+
+ let mut resource_name = ptr::null_mut();
+ assert_napi_ok!(napi_create_string_utf8(
+ env,
+ cstr!("test"),
+ usize::MAX,
+ &mut resource_name
+ ));
+
+ let mut context: napi_async_context = ptr::null_mut();
+ assert_napi_ok!(napi_async_init(env, resource, resource_name, &mut context));
+
+ let mut result = ptr::null_mut();
+ assert_eq!(func_type, napi_function);
+ assert_napi_ok!(napi_make_callback(
+ env,
+ context,
+ recv,
+ func,
+ argc - RESERVED_ARGUMENTS,
+ argv.as_mut_ptr(),
+ &mut result
+ ));
+
+ assert_napi_ok!(napi_async_destroy(env, context));
+ result
+}
+
+pub fn init(env: napi_env, exports: napi_value) {
+ let mut fn_: napi_value = ptr::null_mut();
+
+ assert_napi_ok!(napi_create_function(
+ env,
+ ptr::null_mut(),
+ usize::MAX,
+ Some(make_callback),
+ ptr::null_mut(),
+ &mut fn_,
+ ));
+ assert_napi_ok!(napi_set_named_property(
+ env,
+ exports,
+ cstr!("makeCallback"),
+ fn_
+ ));
+}
diff --git a/tests/napi/src/mem.rs b/tests/napi/src/mem.rs
new file mode 100644
index 000000000..ebb6a5c7a
--- /dev/null
+++ b/tests/napi/src/mem.rs
@@ -0,0 +1,34 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::napi_new_property;
+use napi_sys::*;
+use std::ptr;
+
+extern "C" fn adjust_external_memory(
+ env: napi_env,
+ _: napi_callback_info,
+) -> napi_value {
+ let mut adjusted_value = 0;
+
+ assert_napi_ok!(napi_adjust_external_memory(env, 1024, &mut adjusted_value));
+
+ let mut result = ptr::null_mut();
+ assert_napi_ok!(napi_create_int64(env, adjusted_value, &mut result));
+ result
+}
+
+pub fn init(env: napi_env, exports: napi_value) {
+ let properties = &[napi_new_property!(
+ env,
+ "adjust_external_memory",
+ adjust_external_memory
+ )];
+
+ assert_napi_ok!(napi_define_properties(
+ env,
+ exports,
+ properties.len(),
+ properties.as_ptr()
+ ));
+}
diff --git a/tests/napi/src/numbers.rs b/tests/napi/src/numbers.rs
new file mode 100644
index 000000000..777ccbfac
--- /dev/null
+++ b/tests/napi/src/numbers.rs
@@ -0,0 +1,60 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::napi_get_callback_info;
+use crate::napi_new_property;
+use napi_sys::ValueType::napi_number;
+use napi_sys::*;
+use std::ptr;
+
+extern "C" fn test_int32(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[0], &mut ty));
+ assert_eq!(ty, napi_number);
+
+ let mut int32 = -1;
+ assert_napi_ok!(napi_get_value_int32(env, args[0], &mut int32));
+
+ let mut value: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_int32(env, int32, &mut value));
+ value
+}
+
+extern "C" fn test_int64(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[0], &mut ty));
+ assert_eq!(ty, napi_number);
+
+ let mut int64 = -1;
+ assert_napi_ok!(napi_get_value_int64(env, args[0], &mut int64));
+
+ let mut value: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_int64(env, int64, &mut value));
+ value
+}
+
+pub fn init(env: napi_env, exports: napi_value) {
+ let properties = &[
+ napi_new_property!(env, "test_int32", test_int32),
+ napi_new_property!(env, "test_int64", test_int64),
+ ];
+
+ assert_napi_ok!(napi_define_properties(
+ env,
+ exports,
+ properties.len(),
+ properties.as_ptr()
+ ));
+}
diff --git a/tests/napi/src/object_wrap.rs b/tests/napi/src/object_wrap.rs
new file mode 100644
index 000000000..d04107cf0
--- /dev/null
+++ b/tests/napi/src/object_wrap.rs
@@ -0,0 +1,156 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::napi_get_callback_info;
+use crate::napi_new_property;
+use napi_sys::ValueType::napi_number;
+use napi_sys::*;
+use std::os::raw::c_char;
+use std::os::raw::c_void;
+use std::ptr;
+
+pub struct NapiObject {
+ counter: i32,
+ _wrapper: napi_ref,
+}
+
+impl NapiObject {
+ #[allow(clippy::new_ret_no_self)]
+ pub extern "C" fn new(env: napi_env, info: napi_callback_info) -> napi_value {
+ let mut new_target: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_get_new_target(env, info, &mut new_target));
+ let is_constructor = !new_target.is_null();
+
+ let (args, argc, this) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ if is_constructor {
+ let mut value = 0;
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[0], &mut ty));
+ assert_eq!(ty, napi_number);
+
+ assert_napi_ok!(napi_get_value_int32(env, args[0], &mut value));
+
+ let mut wrapper: napi_ref = ptr::null_mut();
+ let obj = Box::new(Self {
+ counter: value,
+ _wrapper: wrapper,
+ });
+ assert_napi_ok!(napi_wrap(
+ env,
+ this,
+ Box::into_raw(obj) as *mut c_void,
+ None,
+ ptr::null_mut(),
+ &mut wrapper,
+ ));
+
+ return this;
+ }
+
+ unreachable!();
+ }
+
+ pub extern "C" fn set_value(
+ env: napi_env,
+ info: napi_callback_info,
+ ) -> napi_value {
+ let (args, argc, this) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+ let mut obj: *mut Self = ptr::null_mut();
+ assert_napi_ok!(napi_unwrap(
+ env,
+ this,
+ &mut obj as *mut _ as *mut *mut c_void
+ ));
+
+ assert_napi_ok!(napi_get_value_int32(env, args[0], &mut (*obj).counter));
+
+ ptr::null_mut()
+ }
+
+ pub extern "C" fn get_value(
+ env: napi_env,
+ info: napi_callback_info,
+ ) -> napi_value {
+ let (_args, argc, this) = napi_get_callback_info!(env, info, 0);
+ assert_eq!(argc, 0);
+ let mut obj: *mut Self = ptr::null_mut();
+ assert_napi_ok!(napi_unwrap(
+ env,
+ this,
+ &mut obj as *mut _ as *mut *mut c_void
+ ));
+
+ let mut num: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_int32(env, (*obj).counter, &mut num));
+
+ num
+ }
+
+ pub extern "C" fn increment(
+ env: napi_env,
+ info: napi_callback_info,
+ ) -> napi_value {
+ let (_args, argc, this) = napi_get_callback_info!(env, info, 0);
+ assert_eq!(argc, 0);
+ let mut obj: *mut Self = ptr::null_mut();
+ assert_napi_ok!(napi_unwrap(
+ env,
+ this,
+ &mut obj as *mut _ as *mut *mut c_void
+ ));
+
+ unsafe {
+ (*obj).counter += 1;
+ }
+
+ ptr::null_mut()
+ }
+
+ pub extern "C" fn factory(
+ env: napi_env,
+ info: napi_callback_info,
+ ) -> napi_value {
+ let (_args, argc, _this) = napi_get_callback_info!(env, info, 0);
+ assert_eq!(argc, 0);
+
+ let int64 = 64;
+ let mut value: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_int64(env, int64, &mut value));
+ value
+ }
+}
+
+pub fn init(env: napi_env, exports: napi_value) {
+ let mut static_prop = napi_new_property!(env, "factory", NapiObject::factory);
+ static_prop.attributes = PropertyAttributes::static_;
+
+ let properties = &[
+ napi_new_property!(env, "set_value", NapiObject::set_value),
+ napi_new_property!(env, "get_value", NapiObject::get_value),
+ napi_new_property!(env, "increment", NapiObject::increment),
+ static_prop,
+ ];
+
+ let mut cons: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_define_class(
+ env,
+ "NapiObject\0".as_ptr() as *mut c_char,
+ usize::MAX,
+ Some(NapiObject::new),
+ ptr::null_mut(),
+ properties.len(),
+ properties.as_ptr(),
+ &mut cons,
+ ));
+
+ assert_napi_ok!(napi_set_named_property(
+ env,
+ exports,
+ "NapiObject\0".as_ptr() as *const c_char,
+ cons,
+ ));
+}
diff --git a/tests/napi/src/primitives.rs b/tests/napi/src/primitives.rs
new file mode 100644
index 000000000..28fb8ec3d
--- /dev/null
+++ b/tests/napi/src/primitives.rs
@@ -0,0 +1,30 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::napi_new_property;
+use napi_sys::*;
+use std::ptr;
+
+extern "C" fn test_get_undefined(
+ env: napi_env,
+ _: napi_callback_info,
+) -> napi_value {
+ let mut result = ptr::null_mut();
+ assert_napi_ok!(napi_get_undefined(env, &mut result));
+ result
+}
+
+pub fn init(env: napi_env, exports: napi_value) {
+ let properties = &[napi_new_property!(
+ env,
+ "test_get_undefined",
+ test_get_undefined
+ )];
+
+ assert_napi_ok!(napi_define_properties(
+ env,
+ exports,
+ properties.len(),
+ properties.as_ptr()
+ ));
+}
diff --git a/tests/napi/src/promise.rs b/tests/napi/src/promise.rs
new file mode 100644
index 000000000..82cd7a160
--- /dev/null
+++ b/tests/napi/src/promise.rs
@@ -0,0 +1,74 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::napi_get_callback_info;
+use crate::napi_new_property;
+use napi_sys::*;
+use std::ptr;
+
+static mut CURRENT_DEFERRED: napi_deferred = ptr::null_mut();
+
+extern "C" fn test_promise_new(
+ env: napi_env,
+ _info: napi_callback_info,
+) -> napi_value {
+ let mut value: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_promise(env, &mut CURRENT_DEFERRED, &mut value));
+ value
+}
+
+extern "C" fn test_promise_resolve(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ assert_napi_ok!(napi_resolve_deferred(env, CURRENT_DEFERRED, args[0]));
+ unsafe { CURRENT_DEFERRED = ptr::null_mut() };
+ ptr::null_mut()
+}
+
+extern "C" fn test_promise_reject(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ assert_napi_ok!(napi_reject_deferred(env, CURRENT_DEFERRED, args[0]));
+ unsafe { CURRENT_DEFERRED = ptr::null_mut() };
+ ptr::null_mut()
+}
+
+extern "C" fn test_promise_is(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ let mut is_promise: bool = false;
+ assert_napi_ok!(napi_is_promise(env, args[0], &mut is_promise));
+
+ let mut result: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_get_boolean(env, is_promise, &mut result));
+
+ result
+}
+
+pub fn init(env: napi_env, exports: napi_value) {
+ let properties = &[
+ napi_new_property!(env, "test_promise_new", test_promise_new),
+ napi_new_property!(env, "test_promise_resolve", test_promise_resolve),
+ napi_new_property!(env, "test_promise_reject", test_promise_reject),
+ napi_new_property!(env, "test_promise_is", test_promise_is),
+ ];
+
+ assert_napi_ok!(napi_define_properties(
+ env,
+ exports,
+ properties.len(),
+ properties.as_ptr()
+ ));
+}
diff --git a/tests/napi/src/properties.rs b/tests/napi/src/properties.rs
new file mode 100644
index 000000000..43bef1949
--- /dev/null
+++ b/tests/napi/src/properties.rs
@@ -0,0 +1,113 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::cstr;
+use napi_sys::PropertyAttributes::*;
+use napi_sys::*;
+use std::ptr;
+
+static NICE: i64 = 69;
+
+fn init_constants(env: napi_env) -> napi_value {
+ let mut constants: napi_value = ptr::null_mut();
+ let mut value: napi_value = ptr::null_mut();
+
+ assert_napi_ok!(napi_create_object(env, &mut constants));
+ assert_napi_ok!(napi_create_int64(env, NICE, &mut value));
+ assert_napi_ok!(napi_set_named_property(
+ env,
+ constants,
+ cstr!("nice"),
+ value
+ ));
+ constants
+}
+
+pub fn init(env: napi_env, exports: napi_value) {
+ let mut number: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_double(env, 1.0, &mut number));
+
+ // Key name as napi_value representing `v8::String`
+ let mut name_value: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_string_utf8(
+ env,
+ cstr!("key_v8_string"),
+ usize::MAX,
+ &mut name_value,
+ ));
+
+ // Key symbol
+ let mut symbol_description: napi_value = ptr::null_mut();
+ let mut name_symbol: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_string_utf8(
+ env,
+ cstr!("key_v8_symbol"),
+ usize::MAX,
+ &mut symbol_description,
+ ));
+ assert_napi_ok!(napi_create_symbol(
+ env,
+ symbol_description,
+ &mut name_symbol
+ ));
+
+ let properties = &[
+ napi_property_descriptor {
+ utf8name: cstr!("test_simple_property"),
+ name: ptr::null_mut(),
+ method: None,
+ getter: None,
+ setter: None,
+ data: ptr::null_mut(),
+ attributes: enumerable | writable,
+ value: init_constants(env),
+ },
+ napi_property_descriptor {
+ utf8name: cstr!("test_property_rw"),
+ name: ptr::null_mut(),
+ method: None,
+ getter: None,
+ setter: None,
+ data: ptr::null_mut(),
+ attributes: enumerable | writable,
+ value: number,
+ },
+ napi_property_descriptor {
+ utf8name: cstr!("test_property_r"),
+ name: ptr::null_mut(),
+ method: None,
+ getter: None,
+ setter: None,
+ data: ptr::null_mut(),
+ attributes: enumerable,
+ value: number,
+ },
+ napi_property_descriptor {
+ utf8name: ptr::null(),
+ name: name_value,
+ method: None,
+ getter: None,
+ setter: None,
+ data: ptr::null_mut(),
+ attributes: enumerable,
+ value: number,
+ },
+ napi_property_descriptor {
+ utf8name: ptr::null(),
+ name: name_symbol,
+ method: None,
+ getter: None,
+ setter: None,
+ data: ptr::null_mut(),
+ attributes: enumerable,
+ value: number,
+ },
+ ];
+
+ assert_napi_ok!(napi_define_properties(
+ env,
+ exports,
+ properties.len(),
+ properties.as_ptr()
+ ));
+}
diff --git a/tests/napi/src/strings.rs b/tests/napi/src/strings.rs
new file mode 100644
index 000000000..301ab23df
--- /dev/null
+++ b/tests/napi/src/strings.rs
@@ -0,0 +1,49 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::napi_get_callback_info;
+use crate::napi_new_property;
+use napi_sys::ValueType::napi_string;
+use napi_sys::*;
+
+extern "C" fn test_utf8(env: napi_env, info: napi_callback_info) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[0], &mut ty));
+ assert_eq!(ty, napi_string);
+
+ args[0]
+}
+
+extern "C" fn test_utf16(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+ assert_eq!(argc, 1);
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[0], &mut ty));
+ assert_eq!(ty, napi_string);
+
+ args[0]
+}
+
+pub fn init(env: napi_env, exports: napi_value) {
+ let properties = &[
+ // utf8
+ napi_new_property!(env, "test_utf8", test_utf8),
+ // utf16
+ napi_new_property!(env, "test_utf16", test_utf16),
+ // latin1
+ ];
+
+ assert_napi_ok!(napi_define_properties(
+ env,
+ exports,
+ properties.len(),
+ properties.as_ptr()
+ ));
+}
diff --git a/tests/napi/src/symbol.rs b/tests/napi/src/symbol.rs
new file mode 100644
index 000000000..6387d449f
--- /dev/null
+++ b/tests/napi/src/symbol.rs
@@ -0,0 +1,39 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::napi_get_callback_info;
+use crate::napi_new_property;
+use napi_sys::ValueType::napi_string;
+use napi_sys::*;
+
+extern "C" fn symbol_new(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 1);
+
+ let mut description: napi_value = std::ptr::null_mut();
+
+ if argc >= 1 {
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[0], &mut ty));
+ assert_eq!(ty, napi_string);
+ description = args[0];
+ }
+
+ let mut symbol: napi_value = std::ptr::null_mut();
+ assert_napi_ok!(napi_create_symbol(env, description, &mut symbol));
+
+ symbol
+}
+
+pub fn init(env: napi_env, exports: napi_value) {
+ let properties = &[napi_new_property!(env, "symbolNew", symbol_new)];
+
+ assert_napi_ok!(napi_define_properties(
+ env,
+ exports,
+ properties.len(),
+ properties.as_ptr()
+ ));
+}
diff --git a/tests/napi/src/tsfn.rs b/tests/napi/src/tsfn.rs
new file mode 100644
index 000000000..dabc96f83
--- /dev/null
+++ b/tests/napi/src/tsfn.rs
@@ -0,0 +1,108 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+// This test performs initialization similar to napi-rs.
+// https://github.com/napi-rs/napi-rs/commit/a5a04a4e545f268769cc78e2bd6c45af4336aac3
+
+use napi_sys as sys;
+use std::ffi::c_char;
+use std::ffi::c_void;
+use std::ptr;
+
+macro_rules! check_status_or_panic {
+ ($code:expr, $msg:expr) => {{
+ let c = $code;
+ match c {
+ sys::Status::napi_ok => {}
+ _ => panic!($msg),
+ }
+ }};
+}
+
+fn create_custom_gc(env: sys::napi_env) {
+ let mut custom_gc_fn = ptr::null_mut();
+ check_status_or_panic!(
+ unsafe {
+ sys::napi_create_function(
+ env,
+ "custom_gc".as_ptr() as *const c_char,
+ 9,
+ Some(empty),
+ ptr::null_mut(),
+ &mut custom_gc_fn,
+ )
+ },
+ "Create Custom GC Function in napi_register_module_v1 failed"
+ );
+ let mut async_resource_name = ptr::null_mut();
+ check_status_or_panic!(
+ unsafe {
+ sys::napi_create_string_utf8(
+ env,
+ "CustomGC".as_ptr() as *const c_char,
+ 8,
+ &mut async_resource_name,
+ )
+ },
+ "Create async resource string in napi_register_module_v1 napi_register_module_v1"
+ );
+ let mut custom_gc_tsfn = ptr::null_mut();
+ check_status_or_panic!(
+ unsafe {
+ sys::napi_create_threadsafe_function(
+ env,
+ custom_gc_fn,
+ ptr::null_mut(),
+ async_resource_name,
+ 0,
+ 1,
+ ptr::null_mut(),
+ Some(custom_gc_finalize),
+ ptr::null_mut(),
+ Some(custom_gc),
+ &mut custom_gc_tsfn,
+ )
+ },
+ "Create Custom GC ThreadsafeFunction in napi_register_module_v1 failed"
+ );
+ check_status_or_panic!(
+ unsafe { sys::napi_unref_threadsafe_function(env, custom_gc_tsfn) },
+ "Unref Custom GC ThreadsafeFunction in napi_register_module_v1 failed"
+ );
+}
+
+unsafe extern "C" fn empty(
+ _env: sys::napi_env,
+ _info: sys::napi_callback_info,
+) -> sys::napi_value {
+ ptr::null_mut()
+}
+
+unsafe extern "C" fn custom_gc_finalize(
+ _env: sys::napi_env,
+ _finalize_data: *mut c_void,
+ _finalize_hint: *mut c_void,
+) {
+}
+
+extern "C" fn custom_gc(
+ env: sys::napi_env,
+ _js_callback: sys::napi_value,
+ _context: *mut c_void,
+ data: *mut c_void,
+) {
+ let mut ref_count = 0;
+ check_status_or_panic!(
+ unsafe {
+ sys::napi_reference_unref(env, data as sys::napi_ref, &mut ref_count)
+ },
+ "Failed to unref Buffer reference in Custom GC"
+ );
+ check_status_or_panic!(
+ unsafe { sys::napi_delete_reference(env, data as sys::napi_ref) },
+ "Failed to delete Buffer reference in Custom GC"
+ );
+}
+
+pub fn init(env: sys::napi_env, _exports: sys::napi_value) {
+ create_custom_gc(env);
+}
diff --git a/tests/napi/src/typedarray.rs b/tests/napi/src/typedarray.rs
new file mode 100644
index 000000000..b512bd32f
--- /dev/null
+++ b/tests/napi/src/typedarray.rs
@@ -0,0 +1,157 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+use crate::assert_napi_ok;
+use crate::napi_get_callback_info;
+use crate::napi_new_property;
+use core::ffi::c_void;
+use napi_sys::Status::napi_ok;
+use napi_sys::TypedarrayType;
+use napi_sys::ValueType::napi_number;
+use napi_sys::ValueType::napi_object;
+use napi_sys::*;
+use std::os::raw::c_char;
+use std::ptr;
+
+extern "C" fn test_multiply(
+ env: napi_env,
+ info: napi_callback_info,
+) -> napi_value {
+ let (args, argc, _) = napi_get_callback_info!(env, info, 2);
+ assert_eq!(argc, 2);
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[0], &mut ty));
+ assert_eq!(ty, napi_object);
+
+ let input_array = args[0];
+ let mut is_typed_array = false;
+ assert!(
+ unsafe { napi_is_typedarray(env, input_array, &mut is_typed_array) }
+ == napi_ok
+ );
+
+ let mut ty = -1;
+ assert_napi_ok!(napi_typeof(env, args[1], &mut ty));
+ assert_eq!(ty, napi_number);
+
+ let mut multiplier: f64 = 0.0;
+ assert_napi_ok!(napi_get_value_double(env, args[1], &mut multiplier));
+
+ let mut ty = -1;
+ let mut input_buffer = ptr::null_mut();
+ let mut byte_offset = 0;
+ let mut length = 0;
+
+ assert_napi_ok!(napi_get_typedarray_info(
+ env,
+ input_array,
+ &mut ty,
+ &mut length,
+ ptr::null_mut(),
+ &mut input_buffer,
+ &mut byte_offset,
+ ));
+
+ let mut data = ptr::null_mut();
+ let mut byte_length = 0;
+
+ assert_napi_ok!(napi_get_arraybuffer_info(
+ env,
+ input_buffer,
+ &mut data,
+ &mut byte_length
+ ));
+
+ let mut output_buffer = ptr::null_mut();
+ let mut output_ptr = ptr::null_mut();
+ assert_napi_ok!(napi_create_arraybuffer(
+ env,
+ byte_length,
+ &mut output_ptr,
+ &mut output_buffer,
+ ));
+
+ let mut output_array: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_typedarray(
+ env,
+ ty,
+ length,
+ output_buffer,
+ byte_offset,
+ &mut output_array,
+ ));
+
+ if ty == TypedarrayType::uint8_array {
+ let input_bytes = unsafe { (data as *mut u8).offset(byte_offset as isize) };
+ let output_bytes = output_ptr as *mut u8;
+ for i in 0..length {
+ unsafe {
+ *output_bytes.offset(i as isize) =
+ (*input_bytes.offset(i as isize) as f64 * multiplier) as u8;
+ }
+ }
+ } else if ty == TypedarrayType::float64_array {
+ let input_doubles =
+ unsafe { (data as *mut f64).offset(byte_offset as isize) };
+ let output_doubles = output_ptr as *mut f64;
+ for i in 0..length {
+ unsafe {
+ *output_doubles.offset(i as isize) =
+ *input_doubles.offset(i as isize) * multiplier;
+ }
+ }
+ } else {
+ assert_napi_ok!(napi_throw_error(
+ env,
+ ptr::null(),
+ "Typed array was of a type not expected by test.".as_ptr()
+ as *const c_char,
+ ));
+ return ptr::null_mut();
+ }
+
+ output_array
+}
+
+extern "C" fn test_external(
+ env: napi_env,
+ _info: napi_callback_info,
+) -> napi_value {
+ let mut arraybuffer: napi_value = ptr::null_mut();
+ let mut external: Box<[u8; 4]> = Box::new([0, 1, 2, 3]);
+ assert_napi_ok!(napi_create_external_arraybuffer(
+ env,
+ external.as_mut_ptr() as *mut c_void,
+ external.len(),
+ None,
+ ptr::null_mut(),
+ &mut arraybuffer,
+ ));
+
+ let mut typedarray: napi_value = ptr::null_mut();
+ assert_napi_ok!(napi_create_typedarray(
+ env,
+ TypedarrayType::uint8_array,
+ external.len(),
+ arraybuffer,
+ 0,
+ &mut typedarray,
+ ));
+
+ std::mem::forget(external); // Leak into JS land
+ typedarray
+}
+
+pub fn init(env: napi_env, exports: napi_value) {
+ let properties = &[
+ napi_new_property!(env, "test_external", test_external),
+ napi_new_property!(env, "test_multiply", test_multiply),
+ ];
+
+ assert_napi_ok!(napi_define_properties(
+ env,
+ exports,
+ properties.len(),
+ properties.as_ptr()
+ ));
+}