diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2018-08-13 19:55:10 -0400 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2018-08-16 08:40:11 -0400 |
commit | 36d82374cf54be5df23e570bd2c6865e223d5d76 (patch) | |
tree | 0885b628d43cd452981c278b9c02ee45042442e5 | |
parent | d770cc18f80257b520c2cf9cdc5ddea707b38680 (diff) |
Implement deno_handle_msg_from_js in Rust
Fixes #419, #414.
-rw-r--r-- | BUILD.gn | 11 | ||||
-rw-r--r-- | js/main.ts | 1 | ||||
-rw-r--r-- | src/binding.cc | 12 | ||||
-rw-r--r-- | src/binding.rs | 1 | ||||
-rw-r--r-- | src/handlers.h | 19 | ||||
-rw-r--r-- | src/handlers.rs | 154 | ||||
-rw-r--r-- | src/internal.h | 4 | ||||
-rw-r--r-- | src/main.rs | 13 | ||||
-rw-r--r-- | src/msg.fbs | 2 | ||||
-rw-r--r-- | src/reply.cc | 116 | ||||
-rw-r--r-- | src/reply.h | 18 |
11 files changed, 108 insertions, 243 deletions
@@ -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_ |