diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2019-01-01 06:24:05 -0500 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2019-01-03 09:45:40 -0500 |
commit | 7024d9f25394453d49486d5b2b1b5da6d369acb9 (patch) | |
tree | a54e95908fae946d7711bef0c90b27a0536921c8 /src | |
parent | bba0ed3185f30218e015ccd32cc0c8ae14ebba01 (diff) |
Add rust binding and test for deno_execute_mod()
Diffstat (limited to 'src')
-rw-r--r-- | src/deno_dir.rs | 9 | ||||
-rw-r--r-- | src/isolate.rs | 72 | ||||
-rw-r--r-- | src/libdeno.rs | 19 |
3 files changed, 100 insertions, 0 deletions
diff --git a/src/deno_dir.rs b/src/deno_dir.rs index 5ae1c66d9..71a0f7a12 100644 --- a/src/deno_dir.rs +++ b/src/deno_dir.rs @@ -28,6 +28,15 @@ pub struct CodeFetchOutput { pub maybe_source_map: Option<Vec<u8>>, } +impl CodeFetchOutput { + pub fn js_source<'a>(&'a self) -> &'a Vec<u8> { + match self.maybe_output_code { + None => &self.source_code, + Some(ref output_code) => output_code, + } + } +} + /// Gets corresponding MediaType given extension fn extmap(ext: &str) -> msg::MediaType { match ext { diff --git a/src/isolate.rs b/src/isolate.rs index b70e47912..6bdf32c1d 100644 --- a/src/isolate.rs +++ b/src/isolate.rs @@ -13,6 +13,7 @@ use libdeno; use permissions::DenoPermissions; use futures::Future; +use libc::c_char; use libc::c_void; use std; use std::cell::Cell; @@ -148,6 +149,7 @@ impl Isolate { load_snapshot: snapshot, shared: libdeno::deno_buf::empty(), // TODO Use for message passing. recv_cb: pre_dispatch, + resolve_cb, }; let libdeno_isolate = unsafe { libdeno::deno_new(config) }; // This channel handles sending async messages back to the runtime. @@ -228,6 +230,30 @@ impl Isolate { Ok(()) } + /// Executes the provided JavaScript module. + pub fn execute_mod(&self, js_filename: &str) -> Result<(), JSError> { + let out = self.state.dir.code_fetch(js_filename, ".").unwrap(); + debug!("module_resolve complete {}", out.filename); + + // TODO js_source is not null terminated, therefore the clone. + let js_source = CString::new(out.js_source().clone()).unwrap(); + let js_source_ptr = js_source.as_ptr() as *const i8; + + let r = unsafe { + libdeno::deno_execute_mod( + self.libdeno_isolate, + self.as_raw_ptr(), + js_filename.as_ptr() as *const i8, + js_source_ptr, + ) + }; + if r == 0 { + let js_error = self.last_exception().unwrap(); + return Err(js_error); + } + Ok(()) + } + pub fn respond(&self, req_id: i32, buf: Buf) { self.state.metrics_op_completed(buf.len()); // deno_respond will memcpy the buf into V8's heap, @@ -315,6 +341,33 @@ impl Drop for Isolate { } } +extern "C" fn resolve_cb( + user_data: *mut c_void, + specifier_ptr: *const c_char, + referrer_ptr: *const c_char, +) { + let specifier_c: &CStr = unsafe { CStr::from_ptr(specifier_ptr) }; + let specifier: &str = specifier_c.to_str().unwrap(); + + let referrer_c: &CStr = unsafe { CStr::from_ptr(referrer_ptr) }; + let referrer: &str = referrer_c.to_str().unwrap(); + + debug!("module_resolve callback {} {}", specifier, referrer); + let isolate = unsafe { Isolate::from_raw_ptr(user_data) }; + + let out = isolate.state.dir.code_fetch(specifier, referrer).unwrap(); + debug!("module_resolve complete {}", out.filename); + + // TODO js_source is not null terminated, therefore the clone. + let js_source = CString::new(out.js_source().clone()).unwrap(); + let filename = out.filename.as_ptr() as *const i8; + let js_source_ptr = js_source.as_ptr() as *const i8; + + unsafe { + libdeno::deno_resolve_ok(isolate.libdeno_isolate, filename, js_source_ptr) + }; +} + // Dereferences the C pointer into the Rust Isolate object. extern "C" fn pre_dispatch( user_data: *mut c_void, @@ -553,4 +606,23 @@ mod tests { fn is_thread_safe<T: Sync + Send>() {} is_thread_safe::<IsolateState>(); } + + #[test] + fn execute_mod() { + let filename = std::env::current_dir() + .unwrap() + .join("tests/esm_imports_a.js"); + let filename = filename.to_str().unwrap(); + + let argv = vec![String::from("./deno"), String::from(filename)]; + let (flags, rest_argv, _) = flags::set_flags(argv).unwrap(); + + let state = Arc::new(IsolateState::new(flags, rest_argv)); + let snapshot = libdeno::deno_buf::empty(); + let isolate = Isolate::new(snapshot, state, dispatch_sync); + tokio_util::init(|| { + isolate.execute_mod(filename).expect("execute_mod error"); + isolate.event_loop().ok(); + }); + } } diff --git a/src/libdeno.rs b/src/libdeno.rs index 3dde4fd02..40a5a51d0 100644 --- a/src/libdeno.rs +++ b/src/libdeno.rs @@ -110,12 +110,20 @@ type deno_recv_cb = unsafe extern "C" fn( data_buf: deno_buf, ); +#[allow(non_camel_case_types)] +type deno_resolve_cb = unsafe extern "C" fn( + user_data: *mut c_void, + specifier: *const c_char, + referrer: *const c_char, +); + #[repr(C)] pub struct deno_config { pub will_snapshot: c_int, pub load_snapshot: deno_buf, pub shared: deno_buf, pub recv_cb: deno_recv_cb, + pub resolve_cb: deno_resolve_cb, } extern "C" { @@ -138,4 +146,15 @@ extern "C" { js_filename: *const c_char, js_source: *const c_char, ) -> c_int; + pub fn deno_execute_mod( + i: *const isolate, + user_data: *const c_void, + js_filename: *const c_char, + js_source: *const c_char, + ) -> c_int; + pub fn deno_resolve_ok( + i: *const isolate, + js_filename: *const c_char, + js_source: *const c_char, + ); } |