summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/dts/lib.deno.unstable.d.ts2
-rw-r--r--ext/ffi/lib.rs14
-rw-r--r--test_ffi/tests/ffi_types.ts2
-rw-r--r--test_ffi/tests/test.js6
4 files changed, 21 insertions, 3 deletions
diff --git a/cli/dts/lib.deno.unstable.d.ts b/cli/dts/lib.deno.unstable.d.ts
index d82e07be0..2b4e1015a 100644
--- a/cli/dts/lib.deno.unstable.d.ts
+++ b/cli/dts/lib.deno.unstable.d.ts
@@ -430,6 +430,8 @@ declare namespace Deno {
result: Result;
/** When true, function calls will run on a dedicated blocking thread and will return a Promise resolving to the `result`. */
nonblocking?: NonBlocking;
+ /** When true, function calls can safely callback into JS or trigger a GC event. Default is `false`. */
+ callback?: boolean;
}
export interface ForeignStatic<Type extends NativeType = NativeType> {
diff --git a/ext/ffi/lib.rs b/ext/ffi/lib.rs
index d998c8138..a5a156727 100644
--- a/ext/ffi/lib.rs
+++ b/ext/ffi/lib.rs
@@ -72,6 +72,7 @@ struct Symbol {
ptr: libffi::middle::CodePtr,
parameter_types: Vec<NativeType>,
result_type: NativeType,
+ can_callback: bool,
}
#[allow(clippy::non_send_fields_in_send_ty)]
@@ -433,6 +434,13 @@ struct ForeignFunction {
result: NativeType,
#[serde(rename = "nonblocking")]
non_blocking: Option<bool>,
+ #[serde(rename = "callback")]
+ #[serde(default = "default_callback")]
+ callback: bool,
+}
+
+fn default_callback() -> bool {
+ false
}
// ForeignStatic's name and type fields are read and used by
@@ -599,6 +607,7 @@ where
ptr,
parameter_types: foreign_fn.parameters,
result_type: foreign_fn.result,
+ can_callback: foreign_fn.callback,
});
resource.symbols.insert(symbol_key, sym.clone());
@@ -689,7 +698,8 @@ fn make_sync_fn<'s>(
) -> v8::Local<'s, v8::Function> {
let mut fast_ffi_templ = None;
- if !sym.parameter_types.iter().any(|t| !is_fast_api(*t))
+ if !sym.can_callback
+ && !sym.parameter_types.iter().any(|t| !is_fast_api(*t))
&& is_fast_api(sym.result_type)
{
let mut args = sym
@@ -941,6 +951,7 @@ where
result_type,
cif,
ptr: fun_ptr,
+ ..
} = symbol;
let mut ffi_args: Vec<NativeValue> =
Vec::with_capacity(parameter_types.len());
@@ -1814,6 +1825,7 @@ fn op_ffi_call_nonblocking<'scope>(
ptr,
parameter_types,
result_type,
+ ..
} = symbol.clone();
ffi_call(call_args, &cif, ptr, &parameter_types, result_type)
});
diff --git a/test_ffi/tests/ffi_types.ts b/test_ffi/tests/ffi_types.ts
index dde08155d..172c429e8 100644
--- a/test_ffi/tests/ffi_types.ts
+++ b/test_ffi/tests/ffi_types.ts
@@ -5,7 +5,7 @@
const remote = Deno.dlopen(
"dummy_lib.so",
{
- method1: { parameters: ["usize", "usize"], result: "void" },
+ method1: { parameters: ["usize", "usize"], result: "void", callback: true },
method2: { parameters: [], result: "void" },
method3: { parameters: ["usize"], result: "void" },
method4: { parameters: ["isize"], result: "void" },
diff --git a/test_ffi/tests/test.js b/test_ffi/tests/test.js
index af2f522a6..94c2069c0 100644
--- a/test_ffi/tests/test.js
+++ b/test_ffi/tests/test.js
@@ -164,10 +164,12 @@ const dylib = Deno.dlopen(libPath, {
call_stored_function: {
parameters: [],
result: "void",
+ callback: true,
},
call_stored_function_2: {
parameters: ["u8"],
result: "void",
+ callback: true,
},
// Statics
"static_u32": {
@@ -372,12 +374,14 @@ assertThrows(
"hi",
);
+const { call_stored_function } = dylib.symbols;
+
dylib.symbols.call_fn_ptr(ptr(logCallback));
dylib.symbols.call_fn_ptr_many_parameters(ptr(logManyParametersCallback));
dylib.symbols.call_fn_ptr_return_u8(ptr(returnU8Callback));
dylib.symbols.call_fn_ptr_return_buffer(ptr(returnBufferCallback));
dylib.symbols.store_function(ptr(logCallback));
-dylib.symbols.call_stored_function();
+call_stored_function();
dylib.symbols.store_function_2(ptr(add10Callback));
dylib.symbols.call_stored_function_2(20);