diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2018-07-26 17:54:22 -0400 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2018-07-29 00:22:39 -0400 |
commit | 4d386e9e1c79d557cae6af58e6df85eb470c1e0c (patch) | |
tree | 2a5bda6620b2d68ea5f06e4c49c9b9a3ad4c76f2 /src/handlers.rs | |
parent | 1f093c12f84d269cb68370262d68ff6d515aef2e (diff) |
Implement CodeCache
Diffstat (limited to 'src/handlers.rs')
-rw-r--r-- | src/handlers.rs | 311 |
1 files changed, 64 insertions, 247 deletions
diff --git a/src/handlers.rs b/src/handlers.rs index 6dc08f919..4cb3afd5b 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -1,29 +1,18 @@ // Copyright 2018 the Deno authors. All rights reserved. MIT license. use binding::{deno_buf, deno_set_response, DenoC}; use flatbuffers; +use from_c; use libc::c_char; -use libc::uint32_t; use msg_generated::deno as msg; use std::ffi::CStr; -use std::fs::File; -use std::io::Read; -use std::path::Path; -use url; -use url::Url; -// TODO(ry) SRC_DIR is just a placeholder for future caching functionality. -static SRC_DIR: &str = "/Users/rld/.deno/src/"; -const ASSET_PREFIX: &str = "/$asset$/"; - -#[test] -fn test_url() { - let issue_list_url = Url::parse("https://github.com/rust-lang").unwrap(); - assert!(issue_list_url.scheme() == "https"); -} - -fn string_from_ptr(ptr: *const c_char) -> String { - let cstr = unsafe { CStr::from_ptr(ptr as *const i8) }; - String::from(cstr.to_str().unwrap()) +// 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() + }}; } /* @@ -35,182 +24,6 @@ pub fn deno_handle_msg_from_js(d: *const DenoC, buf: deno_buf) { } */ -// Prototype: https://github.com/ry/deno/blob/golang/os.go#L56-L68 -#[allow(dead_code)] -fn src_file_to_url<P: AsRef<Path>>(filename: P) -> String { - assert!(SRC_DIR.len() > 0, "SRC_DIR shouldn't be empty"); - - let filename = filename.as_ref().to_path_buf(); - let src = (SRC_DIR.as_ref() as &Path).to_path_buf(); - - if filename.starts_with(&src) { - let rest = filename.strip_prefix(&src).unwrap(); - "http://".to_string() + rest.to_str().unwrap() - } else { - String::from(filename.to_str().unwrap()) - } -} - -#[test] -fn test_src_file_to_url() { - assert_eq!("hello", src_file_to_url("hello")); - assert_eq!("/hello", src_file_to_url("/hello")); - let x = SRC_DIR.to_string() + "hello"; - assert_eq!("http://hello", src_file_to_url(&x)); - let x = SRC_DIR.to_string() + "/hello"; - assert_eq!("http://hello", src_file_to_url(&x)); -} - -// Prototype: https://github.com/ry/deno/blob/golang/os.go#L70-L98 -// Returns (module name, local filename) -fn resolve_module( - module_specifier: &String, - containing_file: &String, -) -> Result<(String, String), url::ParseError> { - debug!( - "resolve_module before module_specifier {} containing_file {}", - module_specifier, containing_file - ); - - //let module_specifier = src_file_to_url(module_specifier); - //let containing_file = src_file_to_url(containing_file); - //let base_url = Url::parse(&containing_file)?; - - let j: Url = - if containing_file == "." || Path::new(module_specifier).is_absolute() { - Url::from_file_path(module_specifier).unwrap() - } else if containing_file.as_str().ends_with("/") { - let base = Url::from_directory_path(&containing_file).unwrap(); - base.join(module_specifier)? - } else { - let base = Url::from_file_path(&containing_file).unwrap(); - base.join(module_specifier)? - }; - - let mut p = j.to_file_path() - .unwrap() - .into_os_string() - .into_string() - .unwrap(); - - if cfg!(target_os = "windows") { - // On windows, replace backward slashes to forward slashes. - // TODO(piscisaureus): This may not me be right, I just did it to make - // the tests pass. - p = p.replace("\\", "/"); - } - - let module_name = p.to_string(); - let filename = p.to_string(); - - Ok((module_name, filename)) -} - -// https://github.com/ry/deno/blob/golang/os_test.go#L16-L87 -#[test] -fn test_resolve_module() { - // The `add_root` macro prepends "C:" to a string if on windows; on posix - // systems it returns the input string untouched. This is necessary because - // `Url::from_file_path()` fails if the input path isn't an absolute path. - macro_rules! add_root { - ($path:expr) => { - if cfg!(target_os = "windows") { - concat!("C:", $path) - } else { - $path - } - }; - } - - let test_cases = [ - ( - "./subdir/print_hello.ts", - add_root!( - "/Users/rld/go/src/github.com/ry/deno/testdata/006_url_imports.ts" - ), - add_root!( - "/Users/rld/go/src/github.com/ry/deno/testdata/subdir/print_hello.ts" - ), - add_root!( - "/Users/rld/go/src/github.com/ry/deno/testdata/subdir/print_hello.ts" - ), - ), - ( - "testdata/001_hello.js", - add_root!("/Users/rld/go/src/github.com/ry/deno/"), - add_root!("/Users/rld/go/src/github.com/ry/deno/testdata/001_hello.js"), - add_root!("/Users/rld/go/src/github.com/ry/deno/testdata/001_hello.js"), - ), - ( - add_root!("/Users/rld/src/deno/hello.js"), - ".", - add_root!("/Users/rld/src/deno/hello.js"), - add_root!("/Users/rld/src/deno/hello.js"), - ), - ( - add_root!("/this/module/got/imported.js"), - add_root!("/that/module/did/it.js"), - add_root!("/this/module/got/imported.js"), - add_root!("/this/module/got/imported.js"), - ), - /* - ( - "http://localhost:4545/testdata/subdir/print_hello.ts", - add_root!("/Users/rld/go/src/github.com/ry/deno/testdata/006_url_imports.ts"), - "http://localhost:4545/testdata/subdir/print_hello.ts", - path.Join(SrcDir, "localhost:4545/testdata/subdir/print_hello.ts"), - ), - ( - path.Join(SrcDir, "unpkg.com/liltest@0.0.5/index.ts"), - ".", - "http://unpkg.com/liltest@0.0.5/index.ts", - path.Join(SrcDir, "unpkg.com/liltest@0.0.5/index.ts"), - ), - ( - "./util", - path.Join(SrcDir, "unpkg.com/liltest@0.0.5/index.ts"), - "http://unpkg.com/liltest@0.0.5/util", - path.Join(SrcDir, "unpkg.com/liltest@0.0.5/util"), - ), - */ - ]; - for &test in test_cases.iter() { - let module_specifier = String::from(test.0); - let containing_file = String::from(test.1); - let (module_name, filename) = - resolve_module(&module_specifier, &containing_file).unwrap(); - assert_eq!(module_name, test.2); - assert_eq!(filename, test.3); - } -} - -pub fn reply_code_fetch( - d: *const DenoC, - cmd_id: uint32_t, - module_name: &String, - filename: &String, - source_code: &String, - output_code: &String, -) { - let mut builder = flatbuffers::FlatBufferBuilder::new(); - let msg_args = msg::CodeFetchResArgs { - module_name: builder.create_string(module_name), - filename: builder.create_string(filename), - source_code: builder.create_string(source_code), - output_code: builder.create_string(output_code), - ..Default::default() - }; - let msg = msg::CreateCodeFetchRes(&mut builder, &msg_args); - builder.finish(msg); - let args = msg::BaseArgs { - cmdId: cmd_id, - msg: Some(msg.union()), - msg_type: msg::Any::CodeFetchRes, - ..Default::default() - }; - set_response_base(d, &mut builder, &args) -} - fn reply_error(d: *const DenoC, cmd_id: u32, msg: &String) { let mut builder = flatbuffers::FlatBufferBuilder::new(); // println!("reply_error{}", msg); @@ -254,63 +67,67 @@ pub extern "C" fn handle_code_fetch( module_specifier_: *const c_char, containing_file_: *const c_char, ) { - let module_specifier = string_from_ptr(module_specifier_); - let containing_file = string_from_ptr(containing_file_); - - let result = resolve_module(&module_specifier, &containing_file); - if result.is_err() { - let err = result.unwrap_err(); - let errmsg = format!("{} {} {}", err, module_specifier, containing_file); - reply_error(d, cmd_id, &errmsg); - return; - } - let (module_name, filename) = result.unwrap(); + let module_specifier = str_from_ptr!(module_specifier_); + let containing_file = str_from_ptr!(containing_file_); - let mut source_code = String::new(); + let deno = from_c(d); - debug!( - "code_fetch. module_name = {} module_specifier = {} containing_file = {} filename = {}", - module_name, module_specifier, containing_file, filename - ); + assert!(deno.dir.root.join("gen") == deno.dir.gen, "Sanity check"); - if is_remote(&module_name) { - unimplemented!(); - } else if module_name.starts_with(ASSET_PREFIX) { - assert!(false, "Asset resolution should be done in JS, not Rust."); - } else { - assert!( - module_name == filename, - "if a module isn't remote, it should have the same filename" - ); - let result = File::open(&filename); - if result.is_err() { - let err = result.unwrap_err(); - let errmsg = format!("{} {}", err, filename); - reply_error(d, cmd_id, &errmsg); - return; - } - let mut f = result.unwrap(); - let result = f.read_to_string(&mut source_code); - if result.is_err() { - let err = result.unwrap_err(); - let errmsg = format!("{} {}", err, filename); + let result = deno + .dir + .code_fetch(module_specifier, containing_file) + .map_err(|err| { + let errmsg = format!("{}", err); reply_error(d, cmd_id, &errmsg); - return; - } + }); + if result.is_err() { + return; } - - let output_code = String::new(); //load_output_code_cache(filename, source_code); - - reply_code_fetch( - d, - cmd_id, - &module_name, - &filename, - &source_code, - &output_code, - ) + let out = result.unwrap(); + // reply_code_fetch + let mut builder = flatbuffers::FlatBufferBuilder::new(); + let mut msg_args = msg::CodeFetchResArgs { + module_name: builder.create_string(&out.module_name), + filename: builder.create_string(&out.filename), + source_code: builder.create_string(&out.source_code), + ..Default::default() + }; + match out.maybe_output_code { + Some(ref output_code) => { + msg_args.output_code = builder.create_string(output_code); + } + _ => (), + }; + let msg = msg::CreateCodeFetchRes(&mut builder, &msg_args); + builder.finish(msg); + let args = msg::BaseArgs { + cmdId: cmd_id, + msg: Some(msg.union()), + msg_type: msg::Any::CodeFetchRes, + ..Default::default() + }; + set_response_base(d, &mut builder, &args) } -fn is_remote(_module_name: &String) -> bool { - false +// https://github.com/ry/deno/blob/golang/os.go#L156-L169 +#[no_mangle] +pub extern "C" fn handle_code_cache( + d: *const DenoC, + cmd_id: u32, + filename_: *const c_char, + source_code_: *const c_char, + output_code_: *const c_char, +) { + 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); + } + // null response indicates success. } |