Skip to main content
Module

x/deno/src/compiler.rs

A modern runtime for JavaScript and TypeScript.
Go to Latest
File
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.use crate::isolate::Buf;use crate::isolate::IsolateState;use crate::msg;use crate::resources;use crate::resources::Resource;use crate::resources::ResourceId;use crate::workers;
use futures::Future;use serde_json;use std::sync::Arc;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 CodeFetchOutput { pub module_name: String, pub filename: String, pub media_type: msg::MediaType, pub source_code: String, pub maybe_output_code: Option<String>, pub maybe_source_map: Option<String>,}
impl CodeFetchOutput { pub fn js_source(&self) -> String { if self.media_type == msg::MediaType::Json { return format!("export default {};", self.source_code); } match self.maybe_output_code { None => self.source_code.clone(), Some(ref output_code) => output_code.clone(), } }}
impl CodeFetchOutput { // TODO Use serde_derive? Use flatbuffers? fn from_json(json_str: &str) -> Option<Self> { match serde_json::from_str::<serde_json::Value>(json_str) { Ok(serde_json::Value::Object(map)) => { let module_name = match map["moduleId"].as_str() { None => return None, Some(s) => s.to_string(), };
let filename = match map["fileName"].as_str() { None => return None, Some(s) => s.to_string(), };
let source_code = match map["sourceCode"].as_str() { None => return None, Some(s) => s.to_string(), };
let maybe_output_code = map["outputCode"].as_str().map(|s| s.to_string());
let maybe_source_map = map["sourceMap"].as_str().map(|s| s.to_string());
Some(CodeFetchOutput { module_name, filename, media_type: msg::MediaType::JavaScript, // TODO source_code, maybe_output_code, maybe_source_map, }) } _ => None, } }}
fn lazy_start(parent_state: &Arc<IsolateState>) -> Resource { let mut cell = C_RID.lock().unwrap(); let rid = cell.get_or_insert_with(|| { let resource = workers::spawn(parent_state.clone(), "compilerMain()".to_string()); 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: &Arc<IsolateState>, specifier: &str, referrer: &str,) -> Option<CodeFetchOutput> { 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 res_msg = recv_future.wait().unwrap().unwrap();
let res_json = std::str::from_utf8(&res_msg).unwrap(); CodeFetchOutput::from_json(res_json)}
#[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 cfo = compile_sync(&IsolateState::mock(), specifier, &referrer).unwrap(); let output_code = cfo.maybe_output_code.unwrap(); assert!(output_code.starts_with("console.log(\"Hello World\");")); }
#[test] fn code_fetch_output_from_json() { let json = r#"{ "moduleId":"/Users/rld/src/deno/tests/002_hello.ts", "fileName":"/Users/rld/src/deno/tests/002_hello.ts", "mediaType":1, "sourceCode":"console.log(\"Hello World\");\n", "outputCode":"yyy", "sourceMap":"xxx", "scriptVersion":"1" }"#; let actual = CodeFetchOutput::from_json(json).unwrap(); assert_eq!(actual.filename, "/Users/rld/src/deno/tests/002_hello.ts"); assert_eq!(actual.module_name, "/Users/rld/src/deno/tests/002_hello.ts"); assert_eq!(actual.source_code, "console.log(\"Hello World\");\n"); assert_eq!(actual.maybe_output_code, Some("yyy".to_string())); assert_eq!(actual.maybe_source_map, Some("xxx".to_string())); }}