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:
parent
d86e5d2605
commit
e742af10aa
8 changed files with 145 additions and 132 deletions
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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")];
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue