refactor: cleanup compiler pipeline (#2686)

* remove fetch_source_file_and_maybe_compile_async and 
  replace it with State.fetch_compiled_module

* remove SourceFile.js_source()

* introduce CompiledModule which is basically the same as
  deno::SourceInfo and represents arbitrary file that has been 
  compiled to JS module

* introduce //cli/compilers module containing all compilers

* introduce JsCompiler which is a no-op compiler
  - output is the same as input, no compilation takes place
  - it is used for MediaType::JavaScript and MediaType::Unknown

* introduce JsonCompiler that wraps JSON in default export

* support JS-to-JS compilation using checkJs
This commit is contained in:
Bartek Iwańczuk 2019-07-31 19:16:03 +02:00 committed by Ryan Dahl
parent e7cee29c84
commit 2e1ab82321
14 changed files with 353 additions and 199 deletions

View file

@ -1,11 +1,14 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
use crate::compiler::TsCompiler;
use crate::compilers::CompiledModule;
use crate::compilers::JsCompiler;
use crate::compilers::JsonCompiler;
use crate::compilers::TsCompiler;
use crate::deno_dir;
use crate::file_fetcher::SourceFile;
use crate::file_fetcher::SourceFileFetcher;
use crate::flags;
use crate::global_timer::GlobalTimer;
use crate::import_map::ImportMap;
use crate::msg;
use crate::ops;
use crate::permissions::DenoPermissions;
use crate::progress::Progress;
@ -26,6 +29,7 @@ use std;
use std::collections::HashMap;
use std::env;
use std::ops::Deref;
use std::str;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use std::sync::Mutex;
@ -77,6 +81,8 @@ pub struct State {
pub seeded_rng: Option<Mutex<StdRng>>,
pub file_fetcher: SourceFileFetcher,
pub js_compiler: JsCompiler,
pub json_compiler: JsonCompiler,
pub ts_compiler: TsCompiler,
}
@ -103,28 +109,6 @@ impl ThreadSafeState {
}
}
pub fn fetch_source_file_and_maybe_compile_async(
state: &ThreadSafeState,
module_specifier: &ModuleSpecifier,
) -> impl Future<Item = SourceFile, Error = ErrBox> {
let state_ = state.clone();
state_
.file_fetcher
.fetch_source_file_async(&module_specifier)
.and_then(move |out| {
state_
.clone()
.ts_compiler
.compile_async(state_.clone(), &out)
.map_err(|e| {
debug!("compiler error exiting!");
eprintln!("\n{}", e.to_string());
std::process::exit(1);
})
})
}
impl Loader for ThreadSafeState {
fn resolve(
&self,
@ -150,16 +134,14 @@ impl Loader for ThreadSafeState {
module_specifier: &ModuleSpecifier,
) -> Box<deno::SourceCodeInfoFuture> {
self.metrics.resolve_count.fetch_add(1, Ordering::SeqCst);
Box::new(
fetch_source_file_and_maybe_compile_async(self, module_specifier).map(
|source_file| deno::SourceCodeInfo {
// Real module name, might be different from initial specifier
// due to redirections.
code: source_file.js_source(),
module_name: source_file.url.to_string(),
},
),
)
Box::new(self.fetch_compiled_module(module_specifier).map(
|compiled_module| deno::SourceCodeInfo {
// Real module name, might be different from initial specifier
// due to redirections.
code: compiled_module.code,
module_name: compiled_module.name,
},
))
}
}
@ -192,36 +174,26 @@ impl ThreadSafeState {
dir.gen_cache.clone(),
!flags.reload,
flags.config_path.clone(),
);
)?;
let main_module: Option<ModuleSpecifier> = if argv_rest.len() <= 1 {
None
} else {
let root_specifier = argv_rest[1].clone();
match ModuleSpecifier::resolve_url_or_path(&root_specifier) {
Ok(specifier) => Some(specifier),
Err(e) => {
// TODO: handle unresolvable specifier
panic!("Unable to resolve root specifier: {:?}", e);
}
}
Some(ModuleSpecifier::resolve_url_or_path(&root_specifier)?)
};
let mut import_map = None;
if let Some(file_name) = &flags.import_map_path {
let base_url = match &main_module {
Some(module_specifier) => module_specifier.clone(),
None => unreachable!(),
};
match ImportMap::load(&base_url.to_string(), file_name) {
Ok(map) => import_map = Some(map),
Err(err) => {
println!("{:?}", err);
panic!("Error parsing import map");
}
let import_map: Option<ImportMap> = match &flags.import_map_path {
None => None,
Some(file_name) => {
let base_url = match &main_module {
Some(module_specifier) => module_specifier.clone(),
None => unreachable!(),
};
let import_map = ImportMap::load(&base_url.to_string(), file_name)?;
Some(import_map)
}
}
};
let mut seeded_rng = None;
if let Some(seed) = flags.seed {
@ -249,11 +221,42 @@ impl ThreadSafeState {
seeded_rng,
file_fetcher,
ts_compiler,
js_compiler: JsCompiler {},
json_compiler: JsonCompiler {},
};
Ok(ThreadSafeState(Arc::new(state)))
}
pub fn fetch_compiled_module(
self: &Self,
module_specifier: &ModuleSpecifier,
) -> impl Future<Item = CompiledModule, Error = ErrBox> {
let state_ = self.clone();
self
.file_fetcher
.fetch_source_file_async(&module_specifier)
.and_then(move |out| match out.media_type {
msg::MediaType::Unknown => {
state_.js_compiler.compile_async(state_.clone(), &out)
}
msg::MediaType::Json => {
state_.json_compiler.compile_async(state_.clone(), &out)
}
msg::MediaType::TypeScript => {
state_.ts_compiler.compile_async(state_.clone(), &out)
}
msg::MediaType::JavaScript => {
if state_.ts_compiler.compile_js {
state_.ts_compiler.compile_async(state_.clone(), &out)
} else {
state_.js_compiler.compile_async(state_.clone(), &out)
}
}
})
}
/// Read main module from argv
pub fn main_module(&self) -> Option<ModuleSpecifier> {
match &self.main_module {