Files
jsrt/compiler/src/libqjs/mod.rs
T
2026-09-16 07:32:04 +00:00

52 lines
1.4 KiB
Rust

mod ffi;
pub mod parse;
use std::ffi::{CStr, CString};
use parse::QuickJSBinary;
pub fn compile(src: &[u8], filename: &str) -> QuickJSBinary {
unsafe {
let filename = CString::new(filename).unwrap();
let rt = ffi::JS_NewRuntime();
let ctx = ffi::JS_NewContext(rt);
let obj = ffi::JS_Eval(
ctx,
src.as_ptr(),
src.len(),
filename.as_ptr().cast(),
ffi::JS_EVAL_FLAG_COMPILE_ONLY | ffi::JS_EVAL_TYPE_MODULE,
);
assert!(obj.tag != ffi::JS_TAG_EXCEPTION, "{}", get_exception(ctx));
let mut len = 0;
let buf = ffi::JS_WriteObject(ctx, &mut len, obj, ffi::JS_WRITE_OBJ_BYTECODE);
ffi::JS_FreeValue(ctx, obj);
assert!(!buf.is_null());
let bytes = std::slice::from_raw_parts(buf, len).to_vec();
// TODO: Are we sure other cleanup is not necessary?
ffi::JS_FreeContext(ctx);
ffi::JS_FreeRuntime(rt);
QuickJSBinary::parse(&bytes).unwrap().1
}
}
fn get_exception(ctx: *mut ffi::JSContext) -> String {
unsafe {
let err = ffi::JS_GetException(ctx);
let text = ffi::JS_ToCStringLen2(ctx, std::ptr::null_mut(), err, false);
if text.is_null() {
"quickjs raised an exception it could not describe".to_string()
} else {
CStr::from_ptr(text).to_string_lossy().into_owned()
}
}
}