Skip to content

Commit

Permalink
fix(napi): add napi_async_init and napi_async_destroy (#19234)
Browse files Browse the repository at this point in the history
We don't have support for "AsyncContext" in "node:async_hooks" 
module, so these two APIs are just noops.

Towards #18610.
  • Loading branch information
bartlomieju authored May 24, 2023
1 parent 0bb5bbc commit e56695d
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 7 deletions.
19 changes: 12 additions & 7 deletions cli/napi/async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

use deno_runtime::deno_napi::*;

use crate::check_env;

#[repr(C)]
pub struct AsyncWork {
pub data: *mut c_void,
Expand Down Expand Up @@ -69,19 +71,22 @@ fn napi_queue_async_work(
napi_ok
}

// TODO: Custom async operations.

// NOTE: we don't support "async_hooks::AsyncContext" so these APIs are noops.
#[napi_sym::napi_sym]
fn napi_async_init(
_env: *mut Env,
env: *mut Env,
_async_resource: napi_value,
_async_resource_name: napi_value,
_result: *mut *mut (),
result: *mut *mut (),
) -> napi_status {
todo!()
check_env!(env);
*result = ptr::null_mut();
napi_ok
}

#[napi_sym::napi_sym]
fn napi_async_destroy(_env: *mut Env, _async_context: *mut ()) -> napi_status {
todo!()
fn napi_async_destroy(env: *mut Env, async_context: *mut ()) -> napi_status {
check_env!(env);
assert!(async_context.is_null());
napi_ok
}
53 changes: 53 additions & 0 deletions test_napi/make_callback_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.

import { assertEquals, loadTestLibrary } from "./common.js";

const mc = loadTestLibrary();

Deno.test("napi makeCallback1", function () {
const resource = {};

let callCount = 0;
function cb() {
callCount++;
assertEquals(arguments.length, 0);
assertEquals(this, globalThis);
return 42;
}
assertEquals(mc.makeCallback(resource, globalThis, cb), 42);
assertEquals(callCount, 1);
});

Deno.test("napi makeCallback2", function () {
const resource = {};

let callCount = 0;
function cb(x) {
callCount++;
assertEquals(arguments.length, 1);
assertEquals(this, globalThis);
assertEquals(x, 1337);
return 42;
}
assertEquals(mc.makeCallback(resource, globalThis, cb, 1337), 42);
assertEquals(callCount, 1);
});

Deno.test("napi makeCallback3", function () {
const resource = {};

let callCount = 0;

function multiArgFunc(arg1, arg2, arg3) {
callCount++;
assertEquals(arg1, 1);
assertEquals(arg2, 2);
assertEquals(arg3, 3);
return 42;
}
assertEquals(
mc.makeCallback(resource, globalThis, multiArgFunc, 1, 2, 3),
42,
);
assertEquals(callCount, 1);
});
2 changes: 2 additions & 0 deletions test_napi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ 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;
Expand Down Expand Up @@ -162,6 +163,7 @@ unsafe extern "C" fn napi_register_module_v1(
mem::init(env, exports);
bigint::init(env, exports);
symbol::init(env, exports);
make_callback::init(env, exports);

init_cleanup_hook(env, exports);

Expand Down
85 changes: 85 additions & 0 deletions test_napi/src/make_callback.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright 2018-2023 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_
));
}

0 comments on commit e56695d

Please sign in to comment.