use crate::{CheckSyntaxMode, CheckSyntaxResult, Exception, Value, VirtualMachine};
use glib::{
object::{Cast, IsA},
translate::*,
ToValue,
};
use std::{boxed::Box as Box_, fmt, ptr};
glib::wrapper! {
#[doc(alias = "JSCContext")]
pub struct Context(Object<ffi::JSCContext, ffi::JSCContextClass>);
match fn {
type_ => || ffi::jsc_context_get_type(),
}
}
impl Context {
#[doc(alias = "jsc_context_new")]
pub fn new() -> Context {
unsafe { from_glib_full(ffi::jsc_context_new()) }
}
#[doc(alias = "jsc_context_new_with_virtual_machine")]
#[doc(alias = "new_with_virtual_machine")]
pub fn with_virtual_machine(vm: &impl IsA<VirtualMachine>) -> Context {
unsafe {
from_glib_full(ffi::jsc_context_new_with_virtual_machine(
vm.as_ref().to_glib_none().0,
))
}
}
pub fn builder() -> ContextBuilder {
ContextBuilder::default()
}
#[doc(alias = "jsc_context_get_current")]
#[doc(alias = "get_current")]
pub fn current() -> Option<Context> {
unsafe { from_glib_none(ffi::jsc_context_get_current()) }
}
}
impl Default for Context {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Default)]
pub struct ContextBuilder {
virtual_machine: Option<VirtualMachine>,
}
impl ContextBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn build(self) -> Context {
let mut properties: Vec<(&str, &dyn ToValue)> = vec![];
if let Some(ref virtual_machine) = self.virtual_machine {
properties.push(("virtual-machine", virtual_machine));
}
glib::Object::new::<Context>(&properties)
}
pub fn virtual_machine(mut self, virtual_machine: &impl IsA<VirtualMachine>) -> Self {
self.virtual_machine = Some(virtual_machine.clone().upcast());
self
}
}
pub const NONE_CONTEXT: Option<&Context> = None;
pub trait ContextExt: 'static {
#[doc(alias = "jsc_context_check_syntax")]
fn check_syntax(
&self,
code: &str,
mode: CheckSyntaxMode,
uri: &str,
line_number: u32,
) -> (CheckSyntaxResult, Exception);
#[doc(alias = "jsc_context_clear_exception")]
fn clear_exception(&self);
#[doc(alias = "jsc_context_evaluate")]
fn evaluate(&self, code: &str) -> Option<Value>;
#[doc(alias = "jsc_context_evaluate_with_source_uri")]
fn evaluate_with_source_uri(&self, code: &str, uri: &str, line_number: u32) -> Option<Value>;
#[doc(alias = "jsc_context_get_exception")]
#[doc(alias = "get_exception")]
fn exception(&self) -> Option<Exception>;
#[doc(alias = "jsc_context_get_global_object")]
#[doc(alias = "get_global_object")]
fn global_object(&self) -> Option<Value>;
#[doc(alias = "jsc_context_get_value")]
#[doc(alias = "get_value")]
fn value(&self, name: &str) -> Option<Value>;
#[doc(alias = "jsc_context_get_virtual_machine")]
#[doc(alias = "get_virtual_machine")]
fn virtual_machine(&self) -> Option<VirtualMachine>;
#[doc(alias = "jsc_context_pop_exception_handler")]
fn pop_exception_handler(&self);
#[doc(alias = "jsc_context_push_exception_handler")]
fn push_exception_handler<P: Fn(&Context, &Exception) + 'static>(&self, handler: P);
#[doc(alias = "jsc_context_set_value")]
fn set_value(&self, name: &str, value: &impl IsA<Value>);
#[doc(alias = "jsc_context_throw")]
fn throw(&self, error_message: &str);
#[doc(alias = "jsc_context_throw_exception")]
fn throw_exception(&self, exception: &impl IsA<Exception>);
#[doc(alias = "jsc_context_throw_with_name")]
fn throw_with_name(&self, error_name: &str, error_message: &str);
}
impl<O: IsA<Context>> ContextExt for O {
fn check_syntax(
&self,
code: &str,
mode: CheckSyntaxMode,
uri: &str,
line_number: u32,
) -> (CheckSyntaxResult, Exception) {
let length = code.len() as isize;
unsafe {
let mut exception = ptr::null_mut();
let ret = from_glib(ffi::jsc_context_check_syntax(
self.as_ref().to_glib_none().0,
code.to_glib_none().0,
length,
mode.into_glib(),
uri.to_glib_none().0,
line_number,
&mut exception,
));
(ret, from_glib_full(exception))
}
}
fn clear_exception(&self) {
unsafe {
ffi::jsc_context_clear_exception(self.as_ref().to_glib_none().0);
}
}
fn evaluate(&self, code: &str) -> Option<Value> {
let length = code.len() as isize;
unsafe {
from_glib_full(ffi::jsc_context_evaluate(
self.as_ref().to_glib_none().0,
code.to_glib_none().0,
length,
))
}
}
fn evaluate_with_source_uri(&self, code: &str, uri: &str, line_number: u32) -> Option<Value> {
let length = code.len() as isize;
unsafe {
from_glib_full(ffi::jsc_context_evaluate_with_source_uri(
self.as_ref().to_glib_none().0,
code.to_glib_none().0,
length,
uri.to_glib_none().0,
line_number,
))
}
}
fn exception(&self) -> Option<Exception> {
unsafe {
from_glib_none(ffi::jsc_context_get_exception(
self.as_ref().to_glib_none().0,
))
}
}
fn global_object(&self) -> Option<Value> {
unsafe {
from_glib_full(ffi::jsc_context_get_global_object(
self.as_ref().to_glib_none().0,
))
}
}
fn value(&self, name: &str) -> Option<Value> {
unsafe {
from_glib_full(ffi::jsc_context_get_value(
self.as_ref().to_glib_none().0,
name.to_glib_none().0,
))
}
}
fn virtual_machine(&self) -> Option<VirtualMachine> {
unsafe {
from_glib_none(ffi::jsc_context_get_virtual_machine(
self.as_ref().to_glib_none().0,
))
}
}
fn pop_exception_handler(&self) {
unsafe {
ffi::jsc_context_pop_exception_handler(self.as_ref().to_glib_none().0);
}
}
fn push_exception_handler<P: Fn(&Context, &Exception) + 'static>(&self, handler: P) {
let handler_data: Box_<P> = Box_::new(handler);
unsafe extern "C" fn handler_func<P: Fn(&Context, &Exception) + 'static>(
context: *mut ffi::JSCContext,
exception: *mut ffi::JSCException,
user_data: glib::ffi::gpointer,
) {
let context = from_glib_borrow(context);
let exception = from_glib_borrow(exception);
let callback: &P = &*(user_data as *mut _);
(*callback)(&context, &exception);
}
let handler = Some(handler_func::<P> as _);
unsafe extern "C" fn destroy_notify_func<P: Fn(&Context, &Exception) + 'static>(
data: glib::ffi::gpointer,
) {
let _callback: Box_<P> = Box_::from_raw(data as *mut _);
}
let destroy_call3 = Some(destroy_notify_func::<P> as _);
let super_callback0: Box_<P> = handler_data;
unsafe {
ffi::jsc_context_push_exception_handler(
self.as_ref().to_glib_none().0,
handler,
Box_::into_raw(super_callback0) as *mut _,
destroy_call3,
);
}
}
fn set_value(&self, name: &str, value: &impl IsA<Value>) {
unsafe {
ffi::jsc_context_set_value(
self.as_ref().to_glib_none().0,
name.to_glib_none().0,
value.as_ref().to_glib_none().0,
);
}
}
fn throw(&self, error_message: &str) {
unsafe {
ffi::jsc_context_throw(
self.as_ref().to_glib_none().0,
error_message.to_glib_none().0,
);
}
}
fn throw_exception(&self, exception: &impl IsA<Exception>) {
unsafe {
ffi::jsc_context_throw_exception(
self.as_ref().to_glib_none().0,
exception.as_ref().to_glib_none().0,
);
}
}
fn throw_with_name(&self, error_name: &str, error_message: &str) {
unsafe {
ffi::jsc_context_throw_with_name(
self.as_ref().to_glib_none().0,
error_name.to_glib_none().0,
error_message.to_glib_none().0,
);
}
}
}
impl fmt::Display for Context {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("Context")
}
}