54 lines
1.4 KiB
Rust
54 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);
|
|
|
|
let message = if text.is_null() {
|
|
"quickjs raised an exception it could not describe".to_string()
|
|
} else {
|
|
CStr::from_ptr(text).to_string_lossy().into_owned()
|
|
};
|
|
|
|
message
|
|
}
|
|
}
|