use crate::{
js::{
SmartJSValue, quickjs,
var::{js_into_pxs, pxs_into_js},
}, pxs_debug, shared::{PXS_PTR_NAME, func::call_function, object::ObjectFlags, pxs_Runtime, var::pxs_Var}
};
unsafe extern "C" fn object_trampoline(
ctx: *mut quickjs::JSContext,
this_val: quickjs::JSValue,
argc: i32,
argv: *mut quickjs::JSValue,
_magic: i32,
func_data: *mut quickjs::JSValue,
) -> quickjs::JSValue {
let mut pxs_args = vec![
pxs_Runtime::pxs_JavaScript.into_var()
];
let smart_this = SmartJSValue::new_borrow(this_val, ctx);
unsafe {
let flags = SmartJSValue::new_borrow(*func_data.offset(1), ctx).as_i32().unwrap() as u8;
if flags & (ObjectFlags::UsesId as u8) != 0 {
let pxs_ptr = smart_this.get_prop(PXS_PTR_NAME).as_i32().unwrap();
pxs_args.push(pxs_Var::new_i64(pxs_ptr as i64));
} else {
let js_ref = js_into_pxs(&smart_this);
if let Err(err) = js_ref {
let message = format!("JS Ref could not be created: {err}");
return SmartJSValue::new_exception(ctx, message, "CallbackRefError".to_string()).dupped_value();
} else {
pxs_args.push(js_ref.unwrap());
}
}
}
for i in 0..argc {
let val = unsafe { argv.offset(i as isize) };
let smart_val = SmartJSValue::new_borrow(unsafe{ *val }, ctx);
let pxs_val = js_into_pxs(&smart_val);
if pxs_val.is_err() {
pxs_debug!("Error in callback: {:#?}", pxs_val.unwrap_err());
continue;
}
pxs_args.push(pxs_val.unwrap());
}
let fn_idx = unsafe{
SmartJSValue::new_borrow(*func_data.offset(0), ctx).as_i32().unwrap()
};
let res = unsafe{call_function(fn_idx, pxs_args)};
let js_res = pxs_into_js(ctx, &res);
if let Err(err) = js_res {
let error_msg = format!("Error in callback: {}", err);
pxs_debug!("{error_msg}");
let res = SmartJSValue::new_exception(ctx, error_msg, "CallbackError".to_string());
res.dupped_value()
} else {
let res = js_res.unwrap();
res.dupped_value()
}
}
unsafe extern "C" fn method_trampoline(
ctx: *mut quickjs::JSContext,
_this_val: quickjs::JSValue,
argc: i32,
argv: *mut quickjs::JSValue,
_magic: i32,
func_data: *mut quickjs::JSValue,
) -> quickjs::JSValue {
let mut pxs_args = vec![
pxs_Runtime::pxs_JavaScript.into_var()
];
for i in 0..argc {
let val = unsafe { argv.offset(i as isize) };
let smart_val = SmartJSValue::new_borrow(unsafe{ *val }, ctx);
let pxs_val = js_into_pxs(&smart_val);
if pxs_val.is_err() {
pxs_debug!("Error in callback: {:#?}", pxs_val.unwrap_err());
continue;
}
pxs_args.push(pxs_val.unwrap());
}
let fn_idx = unsafe{
SmartJSValue::new_borrow(*func_data.offset(0), ctx).as_i32().unwrap()
};
let res = unsafe{call_function(fn_idx, pxs_args)};
let js_res = pxs_into_js(ctx, &res);
if let Err(err) = js_res {
let error_msg = format!("Error in callback: {}", err);
pxs_debug!("{error_msg}");
let res = SmartJSValue::new_exception(ctx, error_msg, "CallbackError".to_string());
res.dupped_value()
} else {
let res = js_res.unwrap();
res.dupped_value()
}
}
pub(super) fn create_callback(ctx: *mut quickjs::JSContext, fn_idx: i32) -> SmartJSValue {
let idx_wrapper = SmartJSValue::new_i32(ctx, fn_idx);
let mut func_data = vec![
idx_wrapper.dupped_value()
];
let func_data_ptr = func_data.as_mut_ptr();
let function = unsafe {
quickjs::JS_NewCFunctionData(ctx, Some(method_trampoline), 0, 0, 1, func_data_ptr)
};
SmartJSValue::new_owned(function, ctx)
}
pub(super) fn create_object_callback(ctx: *mut quickjs::JSContext, fn_idx: i32, flags: u8) -> SmartJSValue {
let idx_wrapper = SmartJSValue::new_i32(ctx, fn_idx);
let flags_wrapper = SmartJSValue::new_i32(ctx, flags as i32);
let mut func_data = vec![
idx_wrapper.dupped_value(),
flags_wrapper.dupped_value()
];
let func_data_ptr = func_data.as_mut_ptr();
let function = unsafe {
quickjs::JS_NewCFunctionData(ctx, Some(object_trampoline), 0, 0, 2, func_data_ptr)
};
SmartJSValue::new_owned(function, ctx)
}