use crate::prelude::*;
use std::ffi::c_void;
pub mod global_rsvim;
pub mod global_this;
pub fn create_new_context<'s>(
scope: &mut v8::HandleScope<'s, ()>,
) -> v8::Local<'s, v8::Context> {
let scope = &mut v8::EscapableHandleScope::new(scope);
let context = v8::Context::new(scope, Default::default());
let global = context.global(scope);
let scope = &mut v8::ContextScope::new(scope, context);
let vim = create_object_under(scope, global, "__InternalRsvimGlobalObject");
{
set_function_to(
scope,
vim,
"global_set_timeout",
global_this::timeout::set_timeout,
);
set_function_to(
scope,
vim,
"global_clear_timeout",
global_this::timeout::clear_timeout,
);
}
{
set_function_to(
scope,
vim,
"buf_write_sync",
global_rsvim::buf::write_sync,
);
set_function_to(scope, vim, "buf_current", global_rsvim::buf::current);
set_function_to(scope, vim, "buf_list", global_rsvim::buf::list);
}
{
set_function_to(scope, vim, "cmd_echo", global_rsvim::cmd::echo);
}
{
set_function_to(scope, vim, "opt_get_wrap", global_rsvim::opt::get_wrap);
set_function_to(scope, vim, "opt_set_wrap", global_rsvim::opt::set_wrap);
set_function_to(
scope,
vim,
"opt_get_line_break",
global_rsvim::opt::get_line_break,
);
set_function_to(
scope,
vim,
"opt_set_line_break",
global_rsvim::opt::set_line_break,
);
set_function_to(
scope,
vim,
"opt_get_tab_stop",
global_rsvim::opt::get_tab_stop,
);
set_function_to(
scope,
vim,
"opt_set_tab_stop",
global_rsvim::opt::set_tab_stop,
);
set_function_to(
scope,
vim,
"opt_get_expand_tab",
global_rsvim::opt::get_expand_tab,
);
set_function_to(
scope,
vim,
"opt_set_expand_tab",
global_rsvim::opt::set_expand_tab,
);
set_function_to(
scope,
vim,
"opt_get_shift_width",
global_rsvim::opt::get_shift_width,
);
set_function_to(
scope,
vim,
"opt_set_shift_width",
global_rsvim::opt::set_shift_width,
);
set_function_to(
scope,
vim,
"opt_get_file_encoding",
global_rsvim::opt::get_file_encoding,
);
set_function_to(
scope,
vim,
"opt_set_file_encoding",
global_rsvim::opt::set_file_encoding,
);
set_function_to(
scope,
vim,
"opt_get_file_format",
global_rsvim::opt::get_file_format,
);
set_function_to(
scope,
vim,
"opt_set_file_format",
global_rsvim::opt::set_file_format,
);
}
{
set_function_to(scope, vim, "rt_exit", global_rsvim::rt::exit);
}
scope.escape(context)
}
pub fn set_property_to(
scope: &mut v8::HandleScope<'_>,
target: v8::Local<v8::Object>,
name: &'static str,
value: v8::Local<v8::Value>,
) {
let key = v8::String::new(scope, name).unwrap();
target.set(scope, key.into(), value);
}
pub fn set_constant_to(
scope: &mut v8::HandleScope<'_>,
target: v8::Local<v8::Object>,
name: &str,
value: v8::Local<v8::Value>,
) {
let key = v8::String::new(scope, name).unwrap();
target.define_own_property(
scope,
key.into(),
value,
v8::PropertyAttribute::READ_ONLY,
);
}
pub fn set_function_to(
scope: &mut v8::HandleScope<'_>,
target: v8::Local<v8::Object>,
name: &'static str,
callback: impl v8::MapFnTo<v8::FunctionCallback>,
) {
let key = v8::String::new(scope, name).unwrap();
let template = v8::FunctionTemplate::new(scope, callback);
let val = template.get_function(scope).unwrap();
target.set(scope, key.into(), val.into());
}
pub fn create_object_under<'s>(
scope: &mut v8::HandleScope<'s>,
target: v8::Local<v8::Object>,
name: &'static str,
) -> v8::Local<'s, v8::Object> {
let template = v8::ObjectTemplate::new(scope);
let key = v8::String::new(scope, name).unwrap();
let value = template.new_instance(scope).unwrap();
target.set(scope, key.into(), value.into());
value
}
pub fn set_internal_ref<T>(
scope: &mut v8::HandleScope<'_>,
target: v8::Local<v8::Object>,
index: usize,
data: T,
) {
let boxed_ref = Box::new(data);
let addr = Box::leak(boxed_ref) as *mut T as *mut c_void;
let v8_ext = v8::External::new(scope, addr);
target.set_internal_field(index, v8_ext.into());
}
pub fn get_internal_ref<'s, T>(
scope: &mut v8::HandleScope<'s>,
source: v8::Local<v8::Object>,
index: usize,
) -> &'s mut T {
let v8_ref = source.get_internal_field(scope, index).unwrap();
let external = v8_ref.cast::<v8::External>();
let value = external.value() as *mut T;
unsafe { &mut *value }
}
pub fn set_exception_code(
scope: &mut v8::HandleScope<'_>,
exception: v8::Local<v8::Value>,
error: &AnyErr,
) {
let exception = exception.to_object(scope).unwrap();
if let Some(error) = error.downcast_ref::<IoErr>() {
let key = v8::String::new(scope, "code").unwrap();
let value = v8::String::new(scope, &format!("{:?}", error.kind())).unwrap();
exception.set(scope, key.into(), value.into());
}
}
pub fn throw_exception(scope: &mut v8::HandleScope, error: &AnyErr) {
let message = error.to_string().to_owned();
let message = v8::String::new(scope, &message).unwrap();
let exception = v8::Exception::error(scope, message);
set_exception_code(scope, exception, error);
scope.throw_exception(exception);
}
pub fn throw_type_error(scope: &mut v8::HandleScope, message: &str) {
let message = v8::String::new(scope, message).unwrap();
let exception = v8::Exception::type_error(scope, message);
scope.throw_exception(exception);
}