Skip to content

Commit

Permalink
Add rust binding and test for deno_execute_mod()
Browse files Browse the repository at this point in the history
  • Loading branch information
ry committed Jan 2, 2019
1 parent f557f17 commit edbc4f1
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/deno_dir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
72 changes: 72 additions & 0 deletions src/isolate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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();
});
}
}
19 changes: 19 additions & 0 deletions src/libdeno.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand All @@ -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 changes: 3 additions & 0 deletions tests/esm_imports_a.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { retb } from "./esm_imports_b.js";

if (retb() != "b") throw Error();
3 changes: 3 additions & 0 deletions tests/esm_imports_b.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function retb() {
return "b";
}

0 comments on commit edbc4f1

Please sign in to comment.