use std::ptr;
use chakracore_sys::*;
use error::*;
use context::{Context, ContextGuard};
use value;
pub type StringCall = unsafe extern "system" fn(JsRef, *mut i8, usize, *mut usize) -> JsErrorCode;
pub fn to_string_impl(reference: JsRef, callback: StringCall) -> Result<String> {
let mut size = 0;
unsafe {
jstry!(callback(reference, ptr::null_mut(), 0, &mut size));
let mut buffer: Vec<u8> = vec![0; size];
jstry!(callback(reference,
buffer.as_mut_ptr() as _,
buffer.len(),
ptr::null_mut()));
Ok(String::from_utf8_unchecked(buffer))
}
}
pub fn release_reference(reference: JsRef) {
let mut count = 0;
jsassert!(unsafe { JsRelease(reference, &mut count) });
debug_assert!(count < ::libc::c_uint::max_value());
}
pub fn jsfunc(guard: &ContextGuard, function: &str) -> Option<value::Function> {
::script::eval(guard, function).ok().and_then(|val| val.into_function())
}
pub fn jstry(code: JsErrorCode) -> Result<()> {
match code {
JsErrorCode::NoError => Ok(()),
JsErrorCode::ScriptException | JsErrorCode::ScriptCompile => {
Context::exec_with_current(|guard| {
let exception = get_and_clear_exception(guard);
let message = exception.to_string(guard);
Err(if code == JsErrorCode::ScriptException {
ErrorKind::ScriptException(message).into()
} else {
ErrorKind::ScriptCompile(message).into()
})
}).expect("active context in result handler")
},
error @ _ => Err(format!("JSRT call failed with: {:?}", error).into()),
}
}
fn get_and_clear_exception(_guard: &ContextGuard) -> value::Value {
let mut exception = JsValueRef::new();
unsafe {
jsassert!(JsGetAndClearException(&mut exception));
value::Value::from_raw(exception)
}
}