diff --git a/BUILD.gn b/BUILD.gn index 2e743ea90bf845..e007840f656571 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -78,7 +78,7 @@ rust_test("test_rs") { source_root = "src/main.rs" extern = main_extern deps = [ - ":deno_bindings", + ":libdeno", ] } diff --git a/src/binding.cc b/src/binding.cc index 7b5da2d7fc1fbd..ff2f8bd848ba29 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -288,6 +288,8 @@ void deno_init() { v8::V8::Initialize(); } +void* deno_get_data(Deno* d) { return d->data; } + const char* deno_v8_version() { return v8::V8::GetVersion(); } // TODO(ry) Remove these when we call deno_reply_start from Rust. diff --git a/src/binding.rs b/src/binding.rs index 1ef376dff19e0a..a846401bcdeaac 100644 --- a/src/binding.rs +++ b/src/binding.rs @@ -27,6 +27,7 @@ extern "C" { pub fn deno_new(data: *const c_void, cb: DenoRecvCb) -> *const DenoC; pub fn deno_delete(d: *const DenoC); pub fn deno_last_exception(d: *const DenoC) -> *const c_char; + pub fn deno_get_data(d: *const DenoC) -> *const c_void; pub fn deno_set_response(d: *const DenoC, buf: deno_buf); pub fn deno_execute( d: *const DenoC, diff --git a/src/deno.h b/src/deno.h index bb4c91f1c4bf13..7bde5ab9d1873f 100644 --- a/src/deno.h +++ b/src/deno.h @@ -31,6 +31,9 @@ void deno_set_flags(int* argc, char** argv); Deno* deno_new(void* data, deno_recv_cb cb); void deno_delete(Deno* d); +// Returns the void* data provided in deno_new. +void* deno_get_data(Deno*); + // Returns false on error. // Get error text with deno_last_exception(). // 0 = fail, 1 = success diff --git a/src/main.rs b/src/main.rs index 67f4473b8f291e..38ba654b95b9ac 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,19 +6,15 @@ extern crate msg_rs as msg_generated; extern crate url; use libc::c_int; +use libc::c_void; use std::env; use std::ffi::CStr; use std::ffi::CString; use std::mem; -use std::ptr; mod handlers; pub use handlers::*; mod binding; -use binding::{ - deno_delete, deno_execute, deno_handle_msg_from_js, deno_init, - deno_last_exception, deno_new, deno_set_flags, DenoC, -}; // Returns args passed to V8, followed by args passed to JS fn parse_core_args(args: Vec) -> (Vec, Vec) { @@ -71,7 +67,7 @@ fn set_flags(args: Vec) -> Vec { let mut c_argc = c_argv.len() as c_int; // Let v8 parse the arguments it recognizes and remove them from c_argv. unsafe { - deno_set_flags(&mut c_argc, c_argv.as_mut_ptr()); + binding::deno_set_flags(&mut c_argc, c_argv.as_mut_ptr()); }; // If c_argc was updated we have to change the length of c_argv to match. c_argv.truncate(c_argc as usize); @@ -89,14 +85,28 @@ fn set_flags(args: Vec) -> Vec { type DenoException<'a> = &'a str; -struct Deno { - ptr: *const DenoC, +pub struct Deno { + ptr: *const binding::DenoC, } +static DENO_INIT: std::sync::Once = std::sync::ONCE_INIT; + impl Deno { - fn new() -> Deno { - let ptr = unsafe { deno_new(ptr::null(), deno_handle_msg_from_js) }; - Deno { ptr: ptr } + fn new<'a>() -> &'a mut Deno { + DENO_INIT.call_once(|| { + unsafe { binding::deno_init() }; + }); + + let deno_box = Box::new(Deno { + ptr: 0 as *const binding::DenoC, + }); + let deno: &'a mut Deno = Box::leak(deno_box); + let external_ptr = deno as *mut _ as *const c_void; + let internal_deno_ptr = unsafe { + binding::deno_new(external_ptr, binding::deno_handle_msg_from_js) + }; + deno.ptr = internal_deno_ptr; + deno } fn execute( @@ -106,10 +116,11 @@ impl Deno { ) -> Result<(), DenoException> { let filename = CString::new(js_filename).unwrap(); let source = CString::new(js_source).unwrap(); - let r = - unsafe { deno_execute(self.ptr, filename.as_ptr(), source.as_ptr()) }; + let r = unsafe { + binding::deno_execute(self.ptr, filename.as_ptr(), source.as_ptr()) + }; if r == 0 { - let ptr = unsafe { deno_last_exception(self.ptr) }; + let ptr = unsafe { binding::deno_last_exception(self.ptr) }; let cstr = unsafe { CStr::from_ptr(ptr) }; return Err(cstr.to_str().unwrap()); } @@ -119,7 +130,7 @@ impl Deno { impl Drop for Deno { fn drop(&mut self) { - unsafe { deno_delete(self.ptr) } + unsafe { binding::deno_delete(self.ptr) } } } @@ -136,6 +147,19 @@ fn test_parse_core_args_2() { assert!(js_args == (vec!["deno".to_string()], vec!["--help".to_string()])); } +pub fn from_c<'a>(d: *const binding::DenoC) -> &'a mut Deno { + let ptr = unsafe { binding::deno_get_data(d) }; + let deno_ptr = ptr as *mut Deno; + let deno_box = unsafe { Box::from_raw(deno_ptr) }; + Box::leak(deno_box) +} + +#[test] +fn test_c_to_rust() { + let d = Deno::new(); + let d2 = from_c(d.ptr); + assert!(d.ptr == d2.ptr); +} static LOGGER: Logger = Logger; @@ -158,8 +182,6 @@ fn main() { log::set_logger(&LOGGER).unwrap(); log::set_max_level(log::LevelFilter::Info); - unsafe { deno_init() }; - let _js_args = set_flags(env::args().collect()); /* @@ -169,7 +191,7 @@ fn main() { println!("version: {}", version); */ - let mut d = Deno::new(); + let d = Deno::new(); d.execute("deno_main.js", "denoMain();") .unwrap_or_else(|err| {