diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2019-03-19 12:18:05 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-19 12:18:05 -0400 |
commit | fa3c35301aa44975776b96c85f200de8eb500c22 (patch) | |
tree | 76f8d5e6f42e1c306a40efd0b80dce18528952f4 /cli/compiler.rs | |
parent | c7d81fa9ff495986675c05e52e13acc9ffc85372 (diff) |
Rename //src/ to //cli/ (#1962)
To better distinguish the deno_core crate from the executable deno,
which will now be called "the cli" internally.
Diffstat (limited to 'cli/compiler.rs')
-rw-r--r-- | cli/compiler.rs | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/cli/compiler.rs b/cli/compiler.rs new file mode 100644 index 000000000..2d6e4a4b7 --- /dev/null +++ b/cli/compiler.rs @@ -0,0 +1,151 @@ +// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. +use crate::cli::Buf; +use crate::isolate_state::IsolateState; +use crate::msg; +use crate::permissions::{DenoPermissions, PermissionAccessor}; +use crate::resources; +use crate::resources::Resource; +use crate::resources::ResourceId; +use crate::startup_data; +use crate::workers; +use futures::Future; +use serde_json; +use std::str; +use std::sync::Mutex; + +lazy_static! { + static ref C_RID: Mutex<Option<ResourceId>> = Mutex::new(None); +} + +// This corresponds to JS ModuleMetaData. +// TODO Rename one or the other so they correspond. +#[derive(Debug)] +pub struct ModuleMetaData { + pub module_name: String, + pub filename: String, + pub media_type: msg::MediaType, + pub source_code: Vec<u8>, + pub maybe_output_code_filename: Option<String>, + pub maybe_output_code: Option<Vec<u8>>, + pub maybe_source_map_filename: Option<String>, + pub maybe_source_map: Option<Vec<u8>>, +} + +impl ModuleMetaData { + pub fn js_source(&self) -> String { + if self.media_type == msg::MediaType::Json { + return format!( + "export default {};", + str::from_utf8(&self.source_code).unwrap() + ); + } + match self.maybe_output_code { + None => str::from_utf8(&self.source_code).unwrap().to_string(), + Some(ref output_code) => str::from_utf8(output_code).unwrap().to_string(), + } + } +} + +fn lazy_start(parent_state: &IsolateState) -> Resource { + let mut cell = C_RID.lock().unwrap(); + let startup_data = startup_data::compiler_isolate_init(); + let permissions = DenoPermissions { + allow_read: PermissionAccessor::from(true), + allow_write: PermissionAccessor::from(true), + allow_net: PermissionAccessor::from(true), + ..Default::default() + }; + + let rid = cell.get_or_insert_with(|| { + let resource = workers::spawn( + Some(startup_data), + parent_state, + "compilerMain()".to_string(), + permissions, + ); + resource.rid + }); + Resource { rid: *rid } +} + +fn req(specifier: &str, referrer: &str) -> Buf { + json!({ + "specifier": specifier, + "referrer": referrer, + }).to_string() + .into_boxed_str() + .into_boxed_bytes() +} + +pub fn compile_sync( + parent_state: &IsolateState, + specifier: &str, + referrer: &str, + module_meta_data: &ModuleMetaData, +) -> ModuleMetaData { + let req_msg = req(specifier, referrer); + + let compiler = lazy_start(parent_state); + + let send_future = resources::worker_post_message(compiler.rid, req_msg); + send_future.wait().unwrap(); + + let recv_future = resources::worker_recv_message(compiler.rid); + let result = recv_future.wait().unwrap(); + assert!(result.is_some()); + let res_msg = result.unwrap(); + + let res_json = std::str::from_utf8(&res_msg).unwrap(); + match serde_json::from_str::<serde_json::Value>(res_json) { + Ok(serde_json::Value::Object(map)) => ModuleMetaData { + module_name: module_meta_data.module_name.clone(), + filename: module_meta_data.filename.clone(), + media_type: module_meta_data.media_type, + source_code: module_meta_data.source_code.clone(), + maybe_output_code: match map["outputCode"].as_str() { + Some(str) => Some(str.as_bytes().to_owned()), + _ => None, + }, + maybe_output_code_filename: None, + maybe_source_map: match map["sourceMap"].as_str() { + Some(str) => Some(str.as_bytes().to_owned()), + _ => None, + }, + maybe_source_map_filename: None, + }, + _ => panic!("error decoding compiler response"), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_compile_sync() { + let cwd = std::env::current_dir().unwrap(); + let cwd_string = cwd.to_str().unwrap().to_owned(); + + let specifier = "./tests/002_hello.ts"; + let referrer = cwd_string + "/"; + + let mut out = ModuleMetaData { + module_name: "xxx".to_owned(), + filename: "/tests/002_hello.ts".to_owned(), + media_type: msg::MediaType::TypeScript, + source_code: "console.log(\"Hello World\");".as_bytes().to_owned(), + maybe_output_code_filename: None, + maybe_output_code: None, + maybe_source_map_filename: None, + maybe_source_map: None, + }; + + out = compile_sync(&IsolateState::mock(), specifier, &referrer, &mut out); + assert!( + out + .maybe_output_code + .unwrap() + .starts_with("console.log(\"Hello World\");".as_bytes()) + ); + } +} |