Add rust binding and test for deno_execute_mod()

This commit is contained in:
Ryan Dahl 2019-01-01 06:24:05 -05:00
parent bba0ed3185
commit 7024d9f253
5 changed files with 106 additions and 0 deletions

View file

@ -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 {

View file

@ -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();
});
}
}

View file

@ -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,
);
}

3
tests/esm_imports_a.js Normal file
View file

@ -0,0 +1,3 @@
import { retb } from "./esm_imports_b.js";
if (retb() != "b") throw Error();

3
tests/esm_imports_b.js Normal file
View file

@ -0,0 +1,3 @@
export function retb() {
return "b";
}