mirror of
https://github.com/denoland/deno.git
synced 2025-01-11 08:33:43 -05:00
Add rust binding and test for deno_execute_mod()
This commit is contained in:
parent
bba0ed3185
commit
7024d9f253
5 changed files with 106 additions and 0 deletions
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
3
tests/esm_imports_a.js
Normal 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
3
tests/esm_imports_b.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
export function retb() {
|
||||
return "b";
|
||||
}
|
Loading…
Reference in a new issue