summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2018-08-13 19:55:10 -0400
committerRyan Dahl <ry@tinyclouds.org>2018-08-16 08:40:11 -0400
commit36d82374cf54be5df23e570bd2c6865e223d5d76 (patch)
tree0885b628d43cd452981c278b9c02ee45042442e5
parentd770cc18f80257b520c2cf9cdc5ddea707b38680 (diff)
Implement deno_handle_msg_from_js in Rust
Fixes #419, #414.
-rw-r--r--BUILD.gn11
-rw-r--r--js/main.ts1
-rw-r--r--src/binding.cc12
-rw-r--r--src/binding.rs1
-rw-r--r--src/handlers.h19
-rw-r--r--src/handlers.rs154
-rw-r--r--src/internal.h4
-rw-r--r--src/main.rs13
-rw-r--r--src/msg.fbs2
-rw-r--r--src/reply.cc116
-rw-r--r--src/reply.h18
11 files changed, 108 insertions, 243 deletions
diff --git a/BUILD.gn b/BUILD.gn
index 20961b023..ef29899cd 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -156,14 +156,9 @@ v8_source_set("deno_flatbuffer_builder") {
}
v8_source_set("deno_bindings") {
- sources = [
- "src/reply.cc",
- "src/reply.h",
- ]
deps = [
":deno_base",
":deno_flatbuffer_builder",
- ":msg_cpp",
]
configs = [ ":deno_config" ]
}
@@ -178,12 +173,6 @@ executable("snapshot_creator") {
configs += [ ":deno_config" ]
}
-flatbuffer("msg_cpp") {
- sources = [
- "src/msg.fbs",
- ]
-}
-
# Generates type declarations for files that need to be included
# in the runtime bundle
run_node("gen_declarations") {
diff --git a/js/main.ts b/js/main.ts
index d652b18bc..667e115f5 100644
--- a/js/main.ts
+++ b/js/main.ts
@@ -56,7 +56,6 @@ export default function denoMain() {
// Deserialize res into startResMsg.
const bb = new flatbuffers.ByteBuffer(res);
const base = fbs.Base.getRootAsBase(bb);
- assert(base.cmdId() === cmdId);
assert(fbs.Any.StartRes === base.msgType());
const startResMsg = new fbs.StartRes();
assert(base.msg(startResMsg) != null);
diff --git a/src/binding.cc b/src/binding.cc
index 7015660e3..0a107c95f 100644
--- a/src/binding.cc
+++ b/src/binding.cc
@@ -357,20 +357,8 @@ void* deno_get_data(Deno* d) { return d->data; }
const char* deno_v8_version() { return v8::V8::GetVersion(); }
-// TODO(ry) Remove these when we call deno_reply_start from Rust.
-static char** global_argv;
-static int global_argc;
-char** deno_argv() { return global_argv; }
-int deno_argc() { return global_argc; }
-
void deno_set_flags(int* argc, char** argv) {
v8::V8::SetFlagsFromCommandLine(argc, argv, true);
- // TODO(ry) Remove these when we call deno_reply_start from Rust.
- global_argc = *argc;
- global_argv = reinterpret_cast<char**>(malloc(*argc * sizeof(char*)));
- for (int i = 0; i < *argc; i++) {
- global_argv[i] = strdup(argv[i]);
- }
}
const char* deno_last_exception(Deno* d) { return d->last_exception.c_str(); }
diff --git a/src/binding.rs b/src/binding.rs
index 2be5f7206..405f9d7f5 100644
--- a/src/binding.rs
+++ b/src/binding.rs
@@ -35,5 +35,4 @@ extern "C" {
js_filename: *const c_char,
js_source: *const c_char,
) -> c_int;
- pub fn deno_handle_msg_from_js(d: *const DenoC, buf: deno_buf);
}
diff --git a/src/handlers.h b/src/handlers.h
deleted file mode 100644
index 715db3483..000000000
--- a/src/handlers.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2018 the Deno authors. All rights reserved. MIT license.
-#ifndef HANDLERS_H_
-#define HANDLERS_H_
-
-#include <stdint.h>
-#include "deno.h"
-
-extern "C" {
-void handle_code_fetch(Deno* d, uint32_t cmd_id, const char* module_specifier,
- const char* containing_file);
-void handle_code_cache(Deno* d, uint32_t cmd_id, const char* filename,
- const char* source_code, const char* output_code);
-
-void handle_timer_start(Deno* d, uint32_t cmd_id, uint32_t timer_id,
- bool interval, uint32_t delay);
-void handle_timer_clear(Deno* d, uint32_t cmd_id, uint32_t timer_id);
-void handle_read_file_sync(Deno* d, uint32_t cmd_id, const char* filename);
-} // extern "C"
-#endif // HANDLERS_H_
diff --git a/src/handlers.rs b/src/handlers.rs
index 6f2bc8c8e..401c25144 100644
--- a/src/handlers.rs
+++ b/src/handlers.rs
@@ -6,28 +6,97 @@ use from_c;
use fs;
use futures;
use futures::sync::oneshot;
-use libc::c_char;
use msg_generated::deno as msg;
-use std::ffi::CStr;
+use std;
use std::path::Path;
-// Help. Is there a way to do this without macros?
-// Want: fn str_from_ptr(*const c_char) -> &str
-macro_rules! str_from_ptr {
- ($ptr:expr) => {{
- let cstr = unsafe { CStr::from_ptr($ptr as *const i8) };
- cstr.to_str().unwrap()
- }};
+pub extern "C" fn msg_from_js(d: *const DenoC, buf: deno_buf) {
+ let bytes = unsafe { std::slice::from_raw_parts(buf.data_ptr, buf.data_len) };
+ let base = msg::GetRootAsBase(bytes);
+ let msg_type = base.msg_type();
+ match msg_type {
+ msg::Any::Start => {
+ reply_start(d);
+ }
+ msg::Any::CodeFetch => {
+ // TODO base.msg_as_CodeFetch();
+ let msg = msg::CodeFetch::init_from_table(base.msg().unwrap());
+ let module_specifier = msg.module_specifier().unwrap();
+ let containing_file = msg.containing_file().unwrap();
+ handle_code_fetch(d, module_specifier, containing_file);
+ }
+ msg::Any::CodeCache => {
+ // TODO base.msg_as_CodeCache();
+ let msg = msg::CodeCache::init_from_table(base.msg().unwrap());
+ let filename = msg.filename().unwrap();
+ let source_code = msg.source_code().unwrap();
+ let output_code = msg.output_code().unwrap();
+ handle_code_cache(d, filename, source_code, output_code);
+ }
+ msg::Any::TimerStart => {
+ // TODO base.msg_as_TimerStart();
+ let msg = msg::TimerStart::init_from_table(base.msg().unwrap());
+ handle_timer_start(d, msg.id(), msg.interval(), msg.delay());
+ }
+ msg::Any::TimerClear => {
+ // TODO base.msg_as_TimerClear();
+ let msg = msg::TimerClear::init_from_table(base.msg().unwrap());
+ handle_timer_clear(d, msg.id());
+ }
+ msg::Any::Exit => {
+ // TODO base.msg_as_Exit();
+ let msg = msg::Exit::init_from_table(base.msg().unwrap());
+ std::process::exit(msg.code());
+ }
+ msg::Any::ReadFileSync => {
+ // TODO base.msg_as_ReadFileSync();
+ let msg = msg::ReadFileSync::init_from_table(base.msg().unwrap());
+ let filename = msg.filename().unwrap();
+ handle_read_file_sync(d, filename);
+ }
+ msg::Any::NONE => {
+ assert!(false, "Got message with msg_type == Any_NONE");
+ }
+ _ => {
+ assert!(
+ false,
+ format!("Unhandled message {}", msg::EnumNameAny(msg_type))
+ );
+ }
+ }
}
-/*
-// reply_start partially implemented here https://gist.github.com/ry/297c83e0ac8722c045db1b097cdb6afc
-pub fn deno_handle_msg_from_js(d: *const DenoC, buf: deno_buf) {
- let s = std::slice::from_raw_parts(buf.data_ptr, buf.data_len);
- buf.data_ptr
- get_root()
+fn reply_start(d: *const DenoC) {
+ let deno = from_c(d);
+
+ let mut builder = flatbuffers::FlatBufferBuilder::new();
+
+ let argv = deno.argv.iter().map(|s| s.as_str()).collect::<Vec<_>>();
+ let argv_off = builder.create_vector_of_strings(argv.as_slice());
+
+ let cwd_path = std::env::current_dir().unwrap();
+ let cwd_off = builder.create_string(cwd_path.to_str().unwrap());
+
+ let msg = msg::CreateStartRes(
+ &mut builder,
+ &msg::StartResArgs {
+ cwd: Some(cwd_off),
+ argv: Some(argv_off),
+ debug_flag: false,
+ ..Default::default()
+ },
+ );
+
+ set_response_base(
+ d,
+ &mut builder,
+ &msg::BaseArgs {
+ msg: Some(flatbuffers::Offset::new(msg.value())),
+ msg_type: msg::Any::StartRes,
+ ..Default::default()
+ },
+ )
}
-*/
// TODO(ry) Use Deno instead of DenoC as first arg.
fn reply_error(d: *const DenoC, cmd_id: u32, msg: &String) {
@@ -81,16 +150,11 @@ fn send_base(
}
// https://github.com/denoland/deno/blob/golang/os.go#L100-L154
-#[no_mangle]
-pub extern "C" fn handle_code_fetch(
+fn handle_code_fetch(
d: *const DenoC,
- cmd_id: u32,
- module_specifier_: *const c_char,
- containing_file_: *const c_char,
+ module_specifier: &str,
+ containing_file: &str,
) {
- let module_specifier = str_from_ptr!(module_specifier_);
- let containing_file = str_from_ptr!(containing_file_);
-
let deno = from_c(d);
assert!(deno.dir.root.join("gen") == deno.dir.gen, "Sanity check");
@@ -100,7 +164,7 @@ pub extern "C" fn handle_code_fetch(
.code_fetch(module_specifier, containing_file)
.map_err(|err| {
let errmsg = format!("{}", err);
- reply_error(d, cmd_id, &errmsg);
+ reply_error(d, 0, &errmsg);
});
if result.is_err() {
return;
@@ -122,7 +186,6 @@ pub extern "C" fn handle_code_fetch(
};
let msg = msg::CreateCodeFetchRes(&mut builder, &msg_args);
let args = msg::BaseArgs {
- cmdId: cmd_id,
msg: Some(flatbuffers::Offset::new(msg.value())),
msg_type: msg::Any::CodeFetchRes,
..Default::default()
@@ -131,23 +194,18 @@ pub extern "C" fn handle_code_fetch(
}
// https://github.com/denoland/deno/blob/golang/os.go#L156-L169
-#[no_mangle]
-pub extern "C" fn handle_code_cache(
+fn handle_code_cache(
d: *const DenoC,
- cmd_id: u32,
- filename_: *const c_char,
- source_code_: *const c_char,
- output_code_: *const c_char,
+ filename: &str,
+ source_code: &str,
+ output_code: &str,
) {
let deno = from_c(d);
- let filename = str_from_ptr!(filename_);
- let source_code = str_from_ptr!(source_code_);
- let output_code = str_from_ptr!(output_code_);
let result = deno.dir.code_cache(filename, source_code, output_code);
if result.is_err() {
let err = result.unwrap_err();
let errmsg = format!("{}", err);
- reply_error(d, cmd_id, &errmsg);
+ reply_error(d, 0, &errmsg);
}
// null response indicates success.
}
@@ -227,20 +285,13 @@ fn send_timer_ready(d: *const DenoC, timer_id: u32, done: bool) {
}
// Prototype https://github.com/denoland/deno/blob/golang/os.go#L171-L184
-#[no_mangle]
-pub extern "C" fn handle_read_file_sync(
- d: *const DenoC,
- cmd_id: u32,
- filename: *const c_char,
-) {
- let filename = str_from_ptr!(filename);
-
+fn handle_read_file_sync(d: *const DenoC, filename: &str) {
debug!("handle_read_file_sync {}", filename);
let result = fs::read_file_sync(Path::new(filename));
if result.is_err() {
let err = result.unwrap_err();
let errmsg = format!("{}", err);
- reply_error(d, cmd_id, &errmsg);
+ reply_error(d, 0, &errmsg);
return;
}
@@ -277,15 +328,12 @@ use std::time::{Duration, Instant};
use tokio::prelude::*;
use tokio::timer::{Delay, Interval};
// Prototype: https://github.com/ry/deno/blob/golang/timers.go#L25-L39
-#[no_mangle]
-pub extern "C" fn handle_timer_start(
+fn handle_timer_start(
d: *const DenoC,
- cmd_id: u32,
timer_id: u32,
interval: bool,
delay: u32,
) {
- assert!(cmd_id == 0);
debug!("handle_timer_start");
let deno = from_c(d);
@@ -314,13 +362,7 @@ pub extern "C" fn handle_timer_start(
}
// Prototype: https://github.com/ry/deno/blob/golang/timers.go#L40-L43
-#[no_mangle]
-pub extern "C" fn handle_timer_clear(
- d: *const DenoC,
- cmd_id: u32,
- timer_id: u32,
-) {
- assert!(cmd_id == 0);
+fn handle_timer_clear(d: *const DenoC, timer_id: u32) {
debug!("handle_timer_clear");
remove_timer(d, timer_id);
}
diff --git a/src/internal.h b/src/internal.h
index 0719bdc3e..c63ba532a 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -17,10 +17,6 @@ struct deno_s {
deno_recv_cb cb;
void* data;
};
-// TODO(ry) Remove these when we call deno_reply_start from Rust.
-char** deno_argv();
-int deno_argc();
-struct deno_s* deno_from_isolate(v8::Isolate* isolate);
}
namespace deno {
diff --git a/src/main.rs b/src/main.rs
index 49b7f0993..f03a680ba 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -97,12 +97,13 @@ pub struct Deno {
dir: deno_dir::DenoDir,
rt: tokio::runtime::current_thread::Runtime,
timers: HashMap<u32, futures::sync::oneshot::Sender<()>>,
+ argv: Vec<String>,
}
static DENO_INIT: std::sync::Once = std::sync::ONCE_INIT;
impl Deno {
- fn new() -> Box<Deno> {
+ fn new(argv: Vec<String>) -> Box<Deno> {
DENO_INIT.call_once(|| {
unsafe { binding::deno_init() };
});
@@ -112,12 +113,13 @@ impl Deno {
dir: deno_dir::DenoDir::new(None).unwrap(),
rt: tokio::runtime::current_thread::Runtime::new().unwrap(),
timers: HashMap::new(),
+ argv,
});
(*deno_box).ptr = unsafe {
binding::deno_new(
deno_box.as_ref() as *const _ as *const c_void,
- binding::deno_handle_msg_from_js,
+ handlers::msg_from_js,
)
};
@@ -171,7 +173,8 @@ pub fn from_c<'a>(d: *const binding::DenoC) -> &'a mut Deno {
#[test]
fn test_c_to_rust() {
- let d = Deno::new();
+ let argv = vec![String::from("./deno"), String::from("hello.js")];
+ let d = Deno::new(argv);
let d2 = from_c(d.ptr);
assert!(d.ptr == d2.ptr);
assert!(d.dir.root.join("gen") == d.dir.gen, "Sanity check");
@@ -198,7 +201,7 @@ fn main() {
log::set_logger(&LOGGER).unwrap();
log::set_max_level(log::LevelFilter::Info);
- let _js_args = set_flags(env::args().collect());
+ let js_args = set_flags(env::args().collect());
/*
let v = unsafe { deno_v8_version() };
@@ -207,7 +210,7 @@ fn main() {
println!("version: {}", version);
*/
- let mut d = Deno::new();
+ let mut d = Deno::new(js_args);
d.execute("deno_main.js", "denoMain();")
.unwrap_or_else(|err| {
diff --git a/src/msg.fbs b/src/msg.fbs
index 8126eb381..d9de54555 100644
--- a/src/msg.fbs
+++ b/src/msg.fbs
@@ -100,3 +100,5 @@ table WriteFileSync {
perm: uint;
// perm specified by https://godoc.org/os#FileMode
}
+
+root_type Base;
diff --git a/src/reply.cc b/src/reply.cc
deleted file mode 100644
index 62abe1364..000000000
--- a/src/reply.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2018 the Deno authors. All rights reserved. MIT license.
-
-// When Rust Flatbuffer support is complete this file should be ported
-// to Rust and removed: https://github.com/google/flatbuffers/pull/3894
-#include <vector>
-// getcwd
-#ifdef _WIN32
-#include <direct.h>
-#else
-#include <unistd.h>
-#endif
-
-#include "flatbuffers/flatbuffers.h"
-#include "src/deno.h"
-#include "src/flatbuffer_builder.h"
-#include "src/handlers.h"
-#include "src/internal.h"
-#include "src/msg_generated.h"
-#include "src/reply.h"
-#include "third_party/v8/src/base/logging.h"
-
-extern "C" {
-
-void deno_reply_start(Deno* d, uint32_t cmd_id, int argc, char* argv[],
- char* cwd) {
- deno::FlatBufferBuilder builder;
- auto start_cwd = builder.CreateString(cwd);
- std::vector<flatbuffers::Offset<flatbuffers::String>> args;
- for (int i = 0; i < argc; ++i) {
- args.push_back(builder.CreateString(argv[i]));
- }
- auto start_argv = builder.CreateVector(args);
- auto start_msg = deno::CreateStartRes(builder, start_cwd, start_argv);
- auto base = deno::CreateBase(builder, cmd_id, 0, deno::Any_StartRes,
- start_msg.Union());
- builder.Finish(base);
- deno_set_response(d, builder.ExportBuf());
-}
-
-void deno_handle_msg_from_js(Deno* d, deno_buf buf) {
- flatbuffers::Verifier verifier(buf.data_ptr, buf.data_len);
- DCHECK(verifier.VerifyBuffer<deno::Base>());
-
- auto base = flatbuffers::GetRoot<deno::Base>(buf.data_ptr);
- auto cmd_id = base->cmdId();
- auto msg_type = base->msg_type();
- const char* msg_type_name = deno::EnumNamesAny()[msg_type];
- switch (msg_type) {
- case deno::Any_Start: {
- char cwdbuf[1024];
- // TODO(piscisaureus): support unicode on windows.
- getcwd(cwdbuf, sizeof(cwdbuf));
- deno_reply_start(d, cmd_id, deno_argc(), deno_argv(), cwdbuf);
- break;
- }
-
- case deno::Any_CodeFetch: {
- auto msg = base->msg_as_CodeFetch();
- auto module_specifier = msg->module_specifier()->c_str();
- auto containing_file = msg->containing_file()->c_str();
- handle_code_fetch(d, cmd_id, module_specifier, containing_file);
- break;
- }
-
- case deno::Any_CodeCache: {
- auto msg = base->msg_as_CodeCache();
- auto filename = msg->filename()->c_str();
- auto source_code = msg->source_code()->c_str();
- auto output_code = msg->output_code()->c_str();
- handle_code_cache(d, cmd_id, filename, source_code, output_code);
- break;
- }
-
- case deno::Any_TimerStart: {
- auto msg = base->msg_as_TimerStart();
- handle_timer_start(d, cmd_id, msg->id(), msg->interval(), msg->delay());
- break;
- }
-
- case deno::Any_TimerReady: {
- CHECK(false && "Privileged side should not receive TimerReady message.");
- break;
- }
-
- case deno::Any_TimerClear: {
- auto msg = base->msg_as_TimerClear();
- handle_timer_clear(d, cmd_id, msg->id());
- break;
- }
-
- case deno::Any_Exit: {
- auto msg = base->msg_as_Exit();
- uint32_t code = msg->code();
- exit(code);
- break;
- }
-
- case deno::Any_ReadFileSync: {
- auto msg = base->msg_as_ReadFileSync();
- auto filename = msg->filename()->c_str();
- handle_read_file_sync(d, cmd_id, filename);
- break;
- }
-
- case deno::Any_NONE:
- CHECK(false && "Got message with msg_type == Any_NONE");
- break;
-
- default:
- printf("Unhandled message %s\n", msg_type_name);
- CHECK(false && "Unhandled message");
- break;
- }
-}
-
-} // extern "C"
diff --git a/src/reply.h b/src/reply.h
deleted file mode 100644
index 8815abd52..000000000
--- a/src/reply.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2018 the Deno authors. All rights reserved. MIT license.
-
-// TODO(ry) This library handles parsing and sending Flatbuffers. It's written
-// in C++ because flatbuffer support for Rust is not quite there. However, once
-// flatbuffers are supported in Rust, all of this code should be ported back to
-// Rust.
-
-#ifndef REPLY_H_
-#define REPLY_H_
-
-#include <stdint.h>
-#include "deno.h"
-
-extern "C" {
-// Parse incoming messages with C++ Flatbuffers, call into rust handlers.
-void deno_handle_msg_from_js(Deno* d, deno_buf buf);
-}
-#endif // REPLY_H_