1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-23 07:44:48 -05:00

Abide by the rules when passing Isolate between c and rust

Ensure that at most one mutable Isolate reference exists at a time.

`deno_execute()` and `deno_respond()` now borrow a reference to the rust-side
isolate from the caller. When we need a reference to the isolate while one of
these functions is on the stack, `deno_get_data()` can be used to borrow back
that reference.
This commit is contained in:
Bert Belder 2018-10-07 23:48:06 +02:00
parent d86e5d2605
commit e742af10aa
No known key found for this signature in database
GPG key ID: 7A77887B2E2ED461
8 changed files with 145 additions and 132 deletions

View file

@ -131,7 +131,7 @@ void deno_set_callback(Deno* deno, deno_sub_cb cb);
// Get error text with deno_last_exception(). // Get error text with deno_last_exception().
// 0 = success, non-zero = failure. // 0 = success, non-zero = failure.
// TODO(ry) Currently the return code has opposite semantics. // TODO(ry) Currently the return code has opposite semantics.
int deno_execute(Deno* d, const char* js_filename, const char* js_source); int deno_execute(Deno* d, void* user_data, const char* js_filename, const char* js_source);
// This call doesn't go into JS. This is thread-safe. // This call doesn't go into JS. This is thread-safe.
// TODO(ry) Currently this is called deno_pub. It should be renamed. // TODO(ry) Currently this is called deno_pub. It should be renamed.

View file

@ -401,6 +401,24 @@ void AddIsolate(Deno* d, v8::Isolate* isolate) {
d->isolate->SetData(0, d); d->isolate->SetData(0, d);
} }
class UserDataScope {
Deno* deno;
void* prev_data;
void* data; // Not necessary; only for sanity checking.
public:
UserDataScope(Deno* deno_, void* data_) : deno(deno_), data(data_) {
CHECK(deno->user_data == nullptr || deno->user_data == data_);
prev_data = deno->user_data;
deno->user_data = data;
}
~UserDataScope() {
CHECK(deno->user_data == data);
deno->user_data = prev_data;
}
};
} // namespace deno } // namespace deno
extern "C" { extern "C" {
@ -413,7 +431,10 @@ void deno_init() {
v8::V8::Initialize(); v8::V8::Initialize();
} }
void* deno_get_data(Deno* d) { return d->user_data; } void* deno_get_data(const Deno* d) {
CHECK(d->user_data != nullptr);
return d->user_data;
}
const char* deno_v8_version() { return v8::V8::GetVersion(); } const char* deno_v8_version() { return v8::V8::GetVersion(); }
@ -423,7 +444,9 @@ void deno_set_v8_flags(int* argc, char** argv) {
const char* deno_last_exception(Deno* d) { return d->last_exception.c_str(); } const char* deno_last_exception(Deno* d) { return d->last_exception.c_str(); }
int deno_execute(Deno* d, const char* js_filename, const char* js_source) { int deno_execute(Deno* d, void* user_data, const char* js_filename,
const char* js_source) {
deno::UserDataScope user_data_scope(d, user_data);
auto* isolate = d->isolate; auto* isolate = d->isolate;
v8::Locker locker(isolate); v8::Locker locker(isolate);
v8::Isolate::Scope isolate_scope(isolate); v8::Isolate::Scope isolate_scope(isolate);
@ -432,7 +455,7 @@ int deno_execute(Deno* d, const char* js_filename, const char* js_source) {
return deno::Execute(context, js_filename, js_source) ? 1 : 0; return deno::Execute(context, js_filename, js_source) ? 1 : 0;
} }
int deno_respond(Deno* d, int32_t req_id, deno_buf buf) { int deno_respond(Deno* d, void* user_data, int32_t req_id, deno_buf buf) {
if (d->currentArgs != nullptr) { if (d->currentArgs != nullptr) {
// Synchronous response. // Synchronous response.
auto ab = deno::ImportBuf(d->isolate, buf); auto ab = deno::ImportBuf(d->isolate, buf);
@ -442,7 +465,7 @@ int deno_respond(Deno* d, int32_t req_id, deno_buf buf) {
} }
// Asynchronous response. // Asynchronous response.
deno::UserDataScope user_data_scope(d, user_data);
v8::Locker locker(d->isolate); v8::Locker locker(d->isolate);
v8::Isolate::Scope isolate_scope(d->isolate); v8::Isolate::Scope isolate_scope(d->isolate);
v8::HandleScope handle_scope(d->isolate); v8::HandleScope handle_scope(d->isolate);

View file

@ -30,7 +30,7 @@ void deno_init();
const char* deno_v8_version(); const char* deno_v8_version();
void deno_set_v8_flags(int* argc, char** argv); void deno_set_v8_flags(int* argc, char** argv);
Deno* deno_new(void* user_data, deno_recv_cb cb); Deno* deno_new(deno_recv_cb cb);
void deno_delete(Deno* d); void deno_delete(Deno* d);
// Returns the void* user_data provided in deno_new. // Returns the void* user_data provided in deno_new.
@ -39,7 +39,8 @@ void* deno_get_data(Deno*);
// Returns false on error. // Returns false on error.
// Get error text with deno_last_exception(). // Get error text with deno_last_exception().
// 0 = fail, 1 = success // 0 = fail, 1 = success
int deno_execute(Deno* d, const char* js_filename, const char* js_source); int deno_execute(Deno* d, void* user_data, const char* js_filename,
const char* js_source);
// deno_respond sends up to one message back for every deno_recv_cb made. // deno_respond sends up to one message back for every deno_recv_cb made.
// //
@ -59,7 +60,7 @@ int deno_execute(Deno* d, const char* js_filename, const char* js_source);
// //
// A non-zero return value, means a JS exception was encountered during the // A non-zero return value, means a JS exception was encountered during the
// libdeno.recv() callback. Check deno_last_exception() for exception text. // libdeno.recv() callback. Check deno_last_exception() for exception text.
int deno_respond(Deno* d, int32_t req_id, deno_buf buf); int deno_respond(Deno* d, void* user_data, int32_t req_id, deno_buf buf);
const char* deno_last_exception(Deno* d); const char* deno_last_exception(Deno* d);

View file

@ -14,7 +14,7 @@
namespace deno { namespace deno {
Deno* NewFromFileSystem(void* user_data, deno_recv_cb cb) { Deno* NewFromFileSystem(deno_recv_cb cb) {
std::string exe_path; std::string exe_path;
CHECK(deno::ExePath(&exe_path)); CHECK(deno::ExePath(&exe_path));
std::string exe_dir = deno::Dirname(exe_path); // Always ends with a slash. std::string exe_dir = deno::Dirname(exe_path); // Always ends with a slash.
@ -30,7 +30,7 @@ Deno* NewFromFileSystem(void* user_data, deno_recv_cb cb) {
Deno* d = new Deno; Deno* d = new Deno;
d->currentArgs = nullptr; d->currentArgs = nullptr;
d->cb = cb; d->cb = cb;
d->user_data = user_data; d->user_data = nullptr;
v8::Isolate::CreateParams params; v8::Isolate::CreateParams params;
params.array_buffer_allocator = params.array_buffer_allocator =
v8::ArrayBuffer::Allocator::NewDefaultAllocator(); v8::ArrayBuffer::Allocator::NewDefaultAllocator();
@ -55,7 +55,5 @@ Deno* NewFromFileSystem(void* user_data, deno_recv_cb cb) {
} // namespace deno } // namespace deno
extern "C" { extern "C" {
Deno* deno_new(void* user_data, deno_recv_cb cb) { Deno* deno_new(deno_recv_cb cb) { return deno::NewFromFileSystem(cb); }
return deno::NewFromFileSystem(user_data, cb);
}
} }

View file

@ -43,11 +43,11 @@ void DeserializeInternalFields(v8::Local<v8::Object> holder, int index,
deserialized_data.push_back(embedder_field); deserialized_data.push_back(embedder_field);
} }
Deno* NewFromSnapshot(void* user_data, deno_recv_cb cb) { Deno* NewFromSnapshot(deno_recv_cb cb) {
Deno* d = new Deno; Deno* d = new Deno;
d->currentArgs = nullptr; d->currentArgs = nullptr;
d->cb = cb; d->cb = cb;
d->user_data = user_data; d->user_data = nullptr;
v8::Isolate::CreateParams params; v8::Isolate::CreateParams params;
params.array_buffer_allocator = params.array_buffer_allocator =
v8::ArrayBuffer::Allocator::NewDefaultAllocator(); v8::ArrayBuffer::Allocator::NewDefaultAllocator();
@ -80,7 +80,5 @@ Deno* NewFromSnapshot(void* user_data, deno_recv_cb cb) {
} // namespace deno } // namespace deno
extern "C" { extern "C" {
Deno* deno_new(void* user_data, deno_recv_cb cb) { Deno* deno_new(deno_recv_cb cb) { return deno::NewFromSnapshot(cb); }
return deno::NewFromSnapshot(user_data, cb);
}
} }

View file

@ -4,21 +4,21 @@
#include "deno.h" #include "deno.h"
TEST(LibDenoTest, InitializesCorrectly) { TEST(LibDenoTest, InitializesCorrectly) {
Deno* d = deno_new(nullptr, nullptr); Deno* d = deno_new(nullptr);
EXPECT_TRUE(deno_execute(d, "a.js", "1 + 2")); EXPECT_TRUE(deno_execute(d, nullptr, "a.js", "1 + 2"));
deno_delete(d); deno_delete(d);
} }
TEST(LibDenoTest, CanCallFunction) { TEST(LibDenoTest, CanCallFunction) {
Deno* d = deno_new(nullptr, nullptr); Deno* d = deno_new(nullptr);
EXPECT_TRUE(deno_execute(d, "a.js", EXPECT_TRUE(deno_execute(d, nullptr, "a.js",
"if (CanCallFunction() != 'foo') throw Error();")); "if (CanCallFunction() != 'foo') throw Error();"));
deno_delete(d); deno_delete(d);
} }
TEST(LibDenoTest, ErrorsCorrectly) { TEST(LibDenoTest, ErrorsCorrectly) {
Deno* d = deno_new(nullptr, nullptr); Deno* d = deno_new(nullptr);
EXPECT_FALSE(deno_execute(d, "a.js", "throw Error()")); EXPECT_FALSE(deno_execute(d, nullptr, "a.js", "throw Error()"));
deno_delete(d); deno_delete(d);
} }
@ -54,7 +54,7 @@ void assert_null(deno_buf b) {
TEST(LibDenoTest, RecvReturnEmpty) { TEST(LibDenoTest, RecvReturnEmpty) {
static int count = 0; static int count = 0;
Deno* d = deno_new(nullptr, [](auto _, int req_id, auto buf, auto data_buf) { Deno* d = deno_new([](auto _, int req_id, auto buf, auto data_buf) {
assert_null(data_buf); assert_null(data_buf);
count++; count++;
EXPECT_EQ(static_cast<size_t>(3), buf.data_len); EXPECT_EQ(static_cast<size_t>(3), buf.data_len);
@ -62,38 +62,36 @@ TEST(LibDenoTest, RecvReturnEmpty) {
EXPECT_EQ(buf.data_ptr[1], 'b'); EXPECT_EQ(buf.data_ptr[1], 'b');
EXPECT_EQ(buf.data_ptr[2], 'c'); EXPECT_EQ(buf.data_ptr[2], 'c');
}); });
EXPECT_TRUE(deno_execute(d, "a.js", "RecvReturnEmpty()")); EXPECT_TRUE(deno_execute(d, nullptr, "a.js", "RecvReturnEmpty()"));
EXPECT_EQ(count, 2); EXPECT_EQ(count, 2);
deno_delete(d); deno_delete(d);
} }
TEST(LibDenoTest, RecvReturnBar) { TEST(LibDenoTest, RecvReturnBar) {
static int count = 0; static int count = 0;
Deno* d = Deno* d = deno_new([](auto deno, int req_id, auto buf, auto data_buf) {
deno_new(nullptr, [](auto deno, int req_id, auto buf, auto data_buf) {
assert_null(data_buf); assert_null(data_buf);
count++; count++;
EXPECT_EQ(static_cast<size_t>(3), buf.data_len); EXPECT_EQ(static_cast<size_t>(3), buf.data_len);
EXPECT_EQ(buf.data_ptr[0], 'a'); EXPECT_EQ(buf.data_ptr[0], 'a');
EXPECT_EQ(buf.data_ptr[1], 'b'); EXPECT_EQ(buf.data_ptr[1], 'b');
EXPECT_EQ(buf.data_ptr[2], 'c'); EXPECT_EQ(buf.data_ptr[2], 'c');
deno_respond(deno, req_id, strbuf("bar")); deno_respond(deno, nullptr, req_id, strbuf("bar"));
}); });
EXPECT_TRUE(deno_execute(d, "a.js", "RecvReturnBar()")); EXPECT_TRUE(deno_execute(d, nullptr, "a.js", "RecvReturnBar()"));
EXPECT_EQ(count, 1); EXPECT_EQ(count, 1);
deno_delete(d); deno_delete(d);
} }
TEST(LibDenoTest, DoubleRecvFails) { TEST(LibDenoTest, DoubleRecvFails) {
Deno* d = deno_new(nullptr, nullptr); Deno* d = deno_new(nullptr);
EXPECT_FALSE(deno_execute(d, "a.js", "DoubleRecvFails()")); EXPECT_FALSE(deno_execute(d, nullptr, "a.js", "DoubleRecvFails()"));
deno_delete(d); deno_delete(d);
} }
TEST(LibDenoTest, SendRecvSlice) { TEST(LibDenoTest, SendRecvSlice) {
static int count = 0; static int count = 0;
Deno* d = Deno* d = deno_new([](auto deno, int req_id, auto buf, auto data_buf) {
deno_new(nullptr, [](auto deno, int req_id, auto buf, auto data_buf) {
assert_null(data_buf); assert_null(data_buf);
static const size_t alloc_len = 1024; static const size_t alloc_len = 1024;
size_t i = count++; size_t i = count++;
@ -117,16 +115,16 @@ TEST(LibDenoTest, SendRecvSlice) {
buf2.data_ptr[0] = 200 + i; buf2.data_ptr[0] = 200 + i;
buf2.data_ptr[buf2.data_len - 1] = 200 - i; buf2.data_ptr[buf2.data_len - 1] = 200 - i;
// Send back. // Send back.
deno_respond(deno, req_id, buf2); deno_respond(deno, nullptr, req_id, buf2);
}); });
EXPECT_TRUE(deno_execute(d, "a.js", "SendRecvSlice()")); EXPECT_TRUE(deno_execute(d, nullptr, "a.js", "SendRecvSlice()"));
EXPECT_EQ(count, 5); EXPECT_EQ(count, 5);
deno_delete(d); deno_delete(d);
} }
TEST(LibDenoTest, JSSendArrayBufferViewTypes) { TEST(LibDenoTest, JSSendArrayBufferViewTypes) {
static int count = 0; static int count = 0;
Deno* d = deno_new(nullptr, [](auto _, int req_id, auto buf, auto data_buf) { Deno* d = deno_new([](auto _, int req_id, auto buf, auto data_buf) {
assert_null(data_buf); assert_null(data_buf);
count++; count++;
size_t data_offset = buf.data_ptr - buf.alloc_ptr; size_t data_offset = buf.data_ptr - buf.alloc_ptr;
@ -135,47 +133,47 @@ TEST(LibDenoTest, JSSendArrayBufferViewTypes) {
EXPECT_EQ(buf.alloc_len, 4321u); EXPECT_EQ(buf.alloc_len, 4321u);
EXPECT_EQ(buf.data_ptr[0], count); EXPECT_EQ(buf.data_ptr[0], count);
}); });
EXPECT_TRUE(deno_execute(d, "a.js", "JSSendArrayBufferViewTypes()")); EXPECT_TRUE(deno_execute(d, nullptr, "a.js", "JSSendArrayBufferViewTypes()"));
EXPECT_EQ(count, 3); EXPECT_EQ(count, 3);
deno_delete(d); deno_delete(d);
} }
TEST(LibDenoTest, TypedArraySnapshots) { TEST(LibDenoTest, TypedArraySnapshots) {
Deno* d = deno_new(nullptr, nullptr); Deno* d = deno_new(nullptr);
EXPECT_TRUE(deno_execute(d, "a.js", "TypedArraySnapshots()")); EXPECT_TRUE(deno_execute(d, nullptr, "a.js", "TypedArraySnapshots()"));
deno_delete(d); deno_delete(d);
} }
TEST(LibDenoTest, SnapshotBug) { TEST(LibDenoTest, SnapshotBug) {
Deno* d = deno_new(nullptr, nullptr); Deno* d = deno_new(nullptr);
EXPECT_TRUE(deno_execute(d, "a.js", "SnapshotBug()")); EXPECT_TRUE(deno_execute(d, nullptr, "a.js", "SnapshotBug()"));
deno_delete(d); deno_delete(d);
} }
TEST(LibDenoTest, GlobalErrorHandling) { TEST(LibDenoTest, GlobalErrorHandling) {
static int count = 0; static int count = 0;
Deno* d = deno_new(nullptr, [](auto _, int req_id, auto buf, auto data_buf) { Deno* d = deno_new([](auto _, int req_id, auto buf, auto data_buf) {
assert_null(data_buf); assert_null(data_buf);
count++; count++;
EXPECT_EQ(static_cast<size_t>(1), buf.data_len); EXPECT_EQ(static_cast<size_t>(1), buf.data_len);
EXPECT_EQ(buf.data_ptr[0], 42); EXPECT_EQ(buf.data_ptr[0], 42);
}); });
EXPECT_FALSE(deno_execute(d, "a.js", "GlobalErrorHandling()")); EXPECT_FALSE(deno_execute(d, nullptr, "a.js", "GlobalErrorHandling()"));
EXPECT_EQ(count, 1); EXPECT_EQ(count, 1);
deno_delete(d); deno_delete(d);
} }
TEST(LibDenoTest, DoubleGlobalErrorHandlingFails) { TEST(LibDenoTest, DoubleGlobalErrorHandlingFails) {
Deno* d = deno_new(nullptr, nullptr); Deno* d = deno_new(nullptr);
EXPECT_FALSE(deno_execute(d, "a.js", "DoubleGlobalErrorHandlingFails()")); EXPECT_FALSE(
deno_execute(d, nullptr, "a.js", "DoubleGlobalErrorHandlingFails()"));
deno_delete(d); deno_delete(d);
} }
TEST(LibDenoTest, DataBuf) { TEST(LibDenoTest, DataBuf) {
static int count = 0; static int count = 0;
static deno_buf data_buf_copy; static deno_buf data_buf_copy;
Deno* d = deno_new(nullptr, Deno* d = deno_new([](auto _, int req_id, deno_buf buf, deno_buf data_buf) {
[](auto _, int req_id, deno_buf buf, deno_buf data_buf) {
count++; count++;
data_buf.data_ptr[0] = 4; data_buf.data_ptr[0] = 4;
data_buf.data_ptr[1] = 2; data_buf.data_ptr[1] = 2;
@ -185,7 +183,7 @@ TEST(LibDenoTest, DataBuf) {
EXPECT_EQ(buf.data_ptr[0], 1); EXPECT_EQ(buf.data_ptr[0], 1);
EXPECT_EQ(buf.data_ptr[1], 2); EXPECT_EQ(buf.data_ptr[1], 2);
}); });
EXPECT_TRUE(deno_execute(d, "a.js", "DataBuf()")); EXPECT_TRUE(deno_execute(d, nullptr, "a.js", "DataBuf()"));
EXPECT_EQ(count, 1); EXPECT_EQ(count, 1);
// data_buf was subsequently changed in JS, let's check that our copy reflects // data_buf was subsequently changed in JS, let's check that our copy reflects
// that. // that.

View file

@ -14,7 +14,6 @@ use libc::c_void;
use std; use std;
use std::ffi::CStr; use std::ffi::CStr;
use std::ffi::CString; use std::ffi::CString;
use std::sync::atomic;
use std::sync::mpsc; use std::sync::mpsc;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;
@ -72,18 +71,18 @@ impl IsolateState {
static DENO_INIT: std::sync::Once = std::sync::ONCE_INIT; static DENO_INIT: std::sync::Once = std::sync::ONCE_INIT;
impl Isolate { impl Isolate {
pub fn new(argv: Vec<String>, dispatch: Dispatch) -> Box<Isolate> { pub fn new(argv: Vec<String>, dispatch: Dispatch) -> Isolate {
DENO_INIT.call_once(|| { DENO_INIT.call_once(|| {
unsafe { libdeno::deno_init() }; unsafe { libdeno::deno_init() };
}); });
let (flags, argv_rest) = flags::set_flags(argv); let (flags, argv_rest) = flags::set_flags(argv);
let libdeno_isolate = unsafe { libdeno::deno_new(pre_dispatch) };
// This channel handles sending async messages back to the runtime. // This channel handles sending async messages back to the runtime.
let (tx, rx) = mpsc::channel::<(i32, Buf)>(); let (tx, rx) = mpsc::channel::<(i32, Buf)>();
let mut isolate = Box::new(Isolate { Isolate {
libdeno_isolate: 0 as *const libdeno::isolate, libdeno_isolate,
dispatch, dispatch,
rx, rx,
ntasks: 0, ntasks: 0,
@ -94,24 +93,20 @@ impl Isolate {
flags, flags,
tx: Mutex::new(Some(tx)), tx: Mutex::new(Some(tx)),
}), }),
}); }
}
(*isolate).libdeno_isolate = unsafe { pub fn as_void_ptr(&mut self) -> *mut c_void {
libdeno::deno_new(isolate.as_mut() as *mut _ as *mut c_void, pre_dispatch) self as *mut _ as *mut c_void
};
isolate
} }
pub fn from_c<'a>(d: *const libdeno::isolate) -> &'a mut Isolate { pub fn from_c<'a>(d: *const libdeno::isolate) -> &'a mut Isolate {
let ptr = unsafe { libdeno::deno_get_data(d) }; let ptr = unsafe { libdeno::deno_get_data(d) } as *mut _;
let ptr = ptr as *mut Isolate; unsafe { &mut *ptr }
let isolate_box = unsafe { Box::from_raw(ptr) };
Box::leak(isolate_box)
} }
pub fn execute( pub fn execute(
&self, &mut self,
js_filename: &str, js_filename: &str,
js_source: &str, js_source: &str,
) -> Result<(), DenoException> { ) -> Result<(), DenoException> {
@ -120,6 +115,7 @@ impl Isolate {
let r = unsafe { let r = unsafe {
libdeno::deno_execute( libdeno::deno_execute(
self.libdeno_isolate, self.libdeno_isolate,
self.as_void_ptr(),
filename.as_ptr(), filename.as_ptr(),
source.as_ptr(), source.as_ptr(),
) )
@ -132,10 +128,17 @@ impl Isolate {
Ok(()) Ok(())
} }
pub fn respond(&self, req_id: i32, buf: Buf) { pub fn respond(&mut self, req_id: i32, buf: Buf) {
// TODO(zero-copy) Use Buf::leak(buf) to leak the heap allocated buf. And // TODO(zero-copy) Use Buf::leak(buf) to leak the heap allocated buf. And
// don't do the memcpy in ImportBuf() (in libdeno/binding.cc) // don't do the memcpy in ImportBuf() (in libdeno/binding.cc)
unsafe { libdeno::deno_respond(self.libdeno_isolate, req_id, buf.into()) } unsafe {
libdeno::deno_respond(
self.libdeno_isolate,
self.as_void_ptr(),
req_id,
buf.into(),
)
}
} }
fn complete_op(&mut self, req_id: i32, buf: Buf) { fn complete_op(&mut self, req_id: i32, buf: Buf) {
@ -146,14 +149,21 @@ impl Isolate {
self.respond(req_id, buf); self.respond(req_id, buf);
} }
fn timeout(&self) { fn timeout(&mut self) {
let dummy_buf = libdeno::deno_buf { let dummy_buf = libdeno::deno_buf {
alloc_ptr: 0 as *mut u8, alloc_ptr: 0 as *mut u8,
alloc_len: 0, alloc_len: 0,
data_ptr: 0 as *mut u8, data_ptr: 0 as *mut u8,
data_len: 0, data_len: 0,
}; };
unsafe { libdeno::deno_respond(self.libdeno_isolate, -1, dummy_buf) } unsafe {
libdeno::deno_respond(
self.libdeno_isolate,
self.as_void_ptr(),
-1,
dummy_buf,
)
}
} }
// TODO Use Park abstraction? Note at time of writing Tokio default runtime // TODO Use Park abstraction? Note at time of writing Tokio default runtime
@ -280,27 +290,6 @@ mod tests {
use super::*; use super::*;
use futures; use futures;
#[test]
fn test_c_to_rust() {
let argv = vec![String::from("./deno"), String::from("hello.js")];
let isolate = Isolate::new(argv, unreachable_dispatch);
let isolate2 = Isolate::from_c(isolate.libdeno_isolate);
assert_eq!(isolate.libdeno_isolate, isolate2.libdeno_isolate);
assert_eq!(
isolate.state.dir.root.join("gen"),
isolate.state.dir.gen,
"Sanity check"
);
}
fn unreachable_dispatch(
_isolate: &mut Isolate,
_control: &[u8],
_data: &'static mut [u8],
) -> (bool, Box<Op>) {
unreachable!();
}
#[test] #[test]
fn test_dispatch_sync() { fn test_dispatch_sync() {
let argv = vec![String::from("./deno"), String::from("hello.js")]; let argv = vec![String::from("./deno"), String::from("hello.js")];

View file

@ -30,13 +30,19 @@ extern "C" {
pub fn deno_init(); pub fn deno_init();
pub fn deno_v8_version() -> *const c_char; pub fn deno_v8_version() -> *const c_char;
pub fn deno_set_v8_flags(argc: *mut c_int, argv: *mut *mut c_char); pub fn deno_set_v8_flags(argc: *mut c_int, argv: *mut *mut c_char);
pub fn deno_new(user_data: *mut c_void, cb: DenoRecvCb) -> *const isolate; pub fn deno_new(cb: DenoRecvCb) -> *const isolate;
pub fn deno_delete(i: *const isolate); pub fn deno_delete(i: *const isolate);
pub fn deno_last_exception(i: *const isolate) -> *const c_char; pub fn deno_last_exception(i: *const isolate) -> *const c_char;
pub fn deno_get_data(i: *const isolate) -> *mut c_void; pub fn deno_get_data(i: *const isolate) -> *mut c_void;
pub fn deno_respond(i: *const isolate, req_id: i32, buf: deno_buf); pub fn deno_respond(
i: *const isolate,
user_data: *mut c_void,
req_id: i32,
buf: deno_buf,
);
pub fn deno_execute( pub fn deno_execute(
i: *const isolate, i: *const isolate,
user_data: *mut c_void,
js_filename: *const c_char, js_filename: *const c_char,
js_source: *const c_char, js_source: *const c_char,
) -> c_int; ) -> c_int;