mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
fix: node-api function call should use preamble (#26297)
`napi_call_function` should use our equiv of NAPI_PREAMBLE (`&mut Env` instead of `*mut Env`) since it needs to set error codes based on whether the body of the function raised a JS exception. Fixes: https://github.com/denoland/deno/issues/26282
This commit is contained in:
parent
2929d583d2
commit
ea9c3ffaa2
3 changed files with 49 additions and 11 deletions
|
@ -1694,15 +1694,14 @@ fn napi_get_new_target(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[napi_sym]
|
#[napi_sym]
|
||||||
fn napi_call_function(
|
fn napi_call_function<'s>(
|
||||||
env_ptr: *mut Env,
|
env: &'s mut Env,
|
||||||
recv: napi_value,
|
recv: napi_value<'s>,
|
||||||
func: napi_value,
|
func: napi_value<'s>,
|
||||||
argc: usize,
|
argc: usize,
|
||||||
argv: *const napi_value,
|
argv: *const napi_value<'s>,
|
||||||
result: *mut napi_value,
|
result: *mut napi_value<'s>,
|
||||||
) -> napi_status {
|
) -> napi_status {
|
||||||
let env = check_env!(env_ptr);
|
|
||||||
check_arg!(env, recv);
|
check_arg!(env, recv);
|
||||||
let args = if argc > 0 {
|
let args = if argc > 0 {
|
||||||
check_arg!(env, argv);
|
check_arg!(env, argv);
|
||||||
|
@ -1716,11 +1715,11 @@ fn napi_call_function(
|
||||||
let Some(func) =
|
let Some(func) =
|
||||||
func.and_then(|f| v8::Local::<v8::Function>::try_from(f).ok())
|
func.and_then(|f| v8::Local::<v8::Function>::try_from(f).ok())
|
||||||
else {
|
else {
|
||||||
return napi_set_last_error(env, napi_function_expected);
|
return napi_function_expected;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(v) = func.call(&mut env.scope(), recv.unwrap(), args) else {
|
let Some(v) = func.call(&mut env.scope(), recv.unwrap(), args) else {
|
||||||
return napi_set_last_error(env_ptr, napi_generic_failure);
|
return napi_generic_failure;
|
||||||
};
|
};
|
||||||
|
|
||||||
if !result.is_null() {
|
if !result.is_null() {
|
||||||
|
@ -1729,7 +1728,7 @@ fn napi_call_function(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return napi_clear_last_error(env_ptr);
|
napi_ok
|
||||||
}
|
}
|
||||||
|
|
||||||
#[napi_sym]
|
#[napi_sym]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
import { assertEquals, loadTestLibrary } from "./common.js";
|
import { assertEquals, assertThrows, loadTestLibrary } from "./common.js";
|
||||||
|
|
||||||
const callback = loadTestLibrary();
|
const callback = loadTestLibrary();
|
||||||
|
|
||||||
|
@ -36,3 +36,12 @@ Deno.test("napi callback run with args & recv", function () {
|
||||||
);
|
);
|
||||||
assertEquals(result, 69);
|
assertEquals(result, 69);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Deno.test("napi callback handles errors correctly", function () {
|
||||||
|
const e = new Error("hi!");
|
||||||
|
assertThrows(() => {
|
||||||
|
callback.test_callback_throws(() => {
|
||||||
|
throw e;
|
||||||
|
});
|
||||||
|
}, e);
|
||||||
|
});
|
||||||
|
|
|
@ -8,6 +8,7 @@ use napi_sys::ValueType::napi_object;
|
||||||
use napi_sys::ValueType::napi_undefined;
|
use napi_sys::ValueType::napi_undefined;
|
||||||
use napi_sys::*;
|
use napi_sys::*;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
use Status::napi_pending_exception;
|
||||||
|
|
||||||
/// `test_callback_run((a, b) => a + b, [1, 2])` => 3
|
/// `test_callback_run((a, b) => a + b, [1, 2])` => 3
|
||||||
extern "C" fn test_callback_run(
|
extern "C" fn test_callback_run(
|
||||||
|
@ -98,6 +99,34 @@ extern "C" fn test_callback_run_with_recv(
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" fn test_callback_throws(
|
||||||
|
env: napi_env,
|
||||||
|
info: napi_callback_info,
|
||||||
|
) -> napi_value {
|
||||||
|
let (args, ..) = napi_get_callback_info!(env, info, 1);
|
||||||
|
|
||||||
|
let mut global: napi_value = ptr::null_mut();
|
||||||
|
assert_napi_ok!(napi_get_global(env, &mut global));
|
||||||
|
|
||||||
|
let mut argv = vec![];
|
||||||
|
let mut result: napi_value = ptr::null_mut();
|
||||||
|
assert_eq!(
|
||||||
|
unsafe {
|
||||||
|
napi_call_function(
|
||||||
|
env,
|
||||||
|
global, // recv
|
||||||
|
args[0], // cb
|
||||||
|
argv.len(),
|
||||||
|
argv.as_mut_ptr(),
|
||||||
|
&mut result,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
napi_pending_exception
|
||||||
|
);
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init(env: napi_env, exports: napi_value) {
|
pub fn init(env: napi_env, exports: napi_value) {
|
||||||
let properties = &[
|
let properties = &[
|
||||||
napi_new_property!(env, "test_callback_run", test_callback_run),
|
napi_new_property!(env, "test_callback_run", test_callback_run),
|
||||||
|
@ -106,6 +135,7 @@ pub fn init(env: napi_env, exports: napi_value) {
|
||||||
"test_callback_run_with_recv",
|
"test_callback_run_with_recv",
|
||||||
test_callback_run_with_recv
|
test_callback_run_with_recv
|
||||||
),
|
),
|
||||||
|
napi_new_property!(env, "test_callback_throws", test_callback_throws),
|
||||||
];
|
];
|
||||||
|
|
||||||
assert_napi_ok!(napi_define_properties(
|
assert_napi_ok!(napi_define_properties(
|
||||||
|
|
Loading…
Reference in a new issue