use std::sync::Arc;
use crate::{borrow_string, js::{JSModuleMethod, SmartJSValue, create_callback, get_js_state, pxs_into_js, quickjs}, pxs_debug, shared::{module::pxs_Module, utils::CStringSafe}};
unsafe extern "C" fn init_module_function(ctx: *mut quickjs::JSContext, m: *mut quickjs::JSModuleDef) -> i32 {
let module_name = unsafe {
let mna = quickjs::JS_GetModuleName(ctx, m);
let mnp = quickjs::JS_AtomToCStringLen(ctx, std::ptr::null_mut(), mna);
borrow_string!(mnp).to_string()
};
let state = get_js_state();
if let Some(exports) = state.module_exports.borrow().get(&module_name) {
let mut cstrsafe = CStringSafe::new();
for export in exports {
unsafe {
quickjs::JS_SetModuleExport(ctx, m, cstrsafe.new_string(&export.name), export.value.value);
}
}
}
0
}
pub(super) fn add_module(context: *mut quickjs::JSContext, module: &Arc<pxs_Module>) {
let mut cstrsafe = CStringSafe::new();
let js_mod = unsafe {
quickjs::JS_NewCModule(context, cstrsafe.new_string(&module.name), Some(init_module_function))
};
let mut exports = vec![];
for method in module.callbacks.iter() {
let mut cbk = create_callback(context, method.idx);
cbk.owned = false;
exports.push(JSModuleMethod{
name: method.name.clone(),
value: cbk
});
unsafe {
quickjs::JS_AddModuleExport(context, js_mod, cstrsafe.new_string(&method.name));
}
}
for module_var in module.variables.iter() {
let var = pxs_into_js(context, &module_var.var);
if let Err(err) = var {
let err_msg = err.to_string();
let mut exception = SmartJSValue::new_exception(context, err_msg, "PXSJSConversionError".to_string());
exception.owned = false;
exports.push(JSModuleMethod{
name: module_var.name.clone(),
value: exception
});
} else {
let mut res = var.unwrap();
res.owned = false;
exports.push(JSModuleMethod {
name: module_var.name.clone(),
value: res,
});
}
unsafe {
quickjs::JS_AddModuleExport(context, js_mod, cstrsafe.new_string(&module_var.name));
}
}
let state = get_js_state();
let mut module_exports = state.module_exports.borrow_mut();
module_exports.insert(module.name.clone(), exports);
let mut modules = state.modules.borrow_mut();
modules.insert(module.name.clone(), js_mod);
drop(modules);
drop(module_exports);
drop(state);
for child in module.modules.iter() {
add_module(context, child);
}
}
pub(super) fn add_local_module(context: *mut quickjs::JSContext, code: &str, name: &str) -> *mut quickjs::JSModuleDef {
let mut cstrsafe = CStringSafe::new();
let smart_module = SmartJSValue::new_owned(unsafe {
quickjs::JS_Eval(context, cstrsafe.new_string(code), code.len(), cstrsafe.new_string(name), (quickjs::JS_EVAL_TYPE_MODULE | quickjs::JS_EVAL_FLAG_COMPILE_ONLY) as i32)
}, context);
if smart_module.is_exception() || smart_module.is_error() {
pxs_debug!("Error compiling module");
return std::ptr::null_mut();
}
smart_module.get_module_ptr()
}