2020-01-02 15:13:47 -05:00
|
|
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
2019-11-04 10:38:52 -05:00
|
|
|
use crate::compilers::CompiledModule;
|
|
|
|
use crate::compilers::JsCompiler;
|
2020-01-29 12:54:23 -05:00
|
|
|
use crate::compilers::TargetLib;
|
2019-11-04 10:38:52 -05:00
|
|
|
use crate::compilers::TsCompiler;
|
2019-11-14 08:31:39 -05:00
|
|
|
use crate::compilers::WasmCompiler;
|
2019-11-04 10:38:52 -05:00
|
|
|
use crate::deno_dir;
|
|
|
|
use crate::file_fetcher::SourceFileFetcher;
|
|
|
|
use crate::flags;
|
2020-02-19 08:17:13 -05:00
|
|
|
use crate::http_cache;
|
2019-11-04 10:38:52 -05:00
|
|
|
use crate::lockfile::Lockfile;
|
|
|
|
use crate::msg;
|
2020-05-04 14:10:59 -04:00
|
|
|
use crate::permissions::Permissions;
|
2020-01-05 11:56:18 -05:00
|
|
|
use deno_core::ErrBox;
|
|
|
|
use deno_core::ModuleSpecifier;
|
2019-11-04 10:38:52 -05:00
|
|
|
use std::env;
|
|
|
|
use std::ops::Deref;
|
2020-02-11 11:23:40 -05:00
|
|
|
use std::sync::atomic::AtomicUsize;
|
2019-11-04 10:38:52 -05:00
|
|
|
use std::sync::Arc;
|
|
|
|
use std::sync::Mutex;
|
2020-02-06 21:24:51 -05:00
|
|
|
use tokio::sync::Mutex as AsyncMutex;
|
2019-11-04 10:38:52 -05:00
|
|
|
|
|
|
|
/// Holds state of the program and can be accessed by V8 isolate.
|
2020-02-06 21:24:51 -05:00
|
|
|
#[derive(Clone)]
|
2020-02-06 23:05:02 -05:00
|
|
|
pub struct GlobalState(Arc<GlobalStateInner>);
|
2019-11-04 10:38:52 -05:00
|
|
|
|
|
|
|
/// This structure represents state of single "deno" program.
|
|
|
|
///
|
|
|
|
/// It is shared by all created workers (thus V8 isolates).
|
2020-02-06 23:05:02 -05:00
|
|
|
pub struct GlobalStateInner {
|
2019-11-04 10:38:52 -05:00
|
|
|
/// Flags parsed from `argv` contents.
|
2020-02-26 05:52:15 -05:00
|
|
|
pub flags: flags::Flags,
|
2019-11-04 10:38:52 -05:00
|
|
|
/// Permissions parsed from `flags`.
|
2020-05-04 14:10:59 -04:00
|
|
|
pub permissions: Permissions,
|
2019-11-04 10:38:52 -05:00
|
|
|
pub dir: deno_dir::DenoDir,
|
|
|
|
pub file_fetcher: SourceFileFetcher,
|
|
|
|
pub js_compiler: JsCompiler,
|
|
|
|
pub ts_compiler: TsCompiler,
|
2019-11-14 08:31:39 -05:00
|
|
|
pub wasm_compiler: WasmCompiler,
|
2019-11-04 10:38:52 -05:00
|
|
|
pub lockfile: Option<Mutex<Lockfile>>,
|
2020-02-11 11:23:40 -05:00
|
|
|
pub compiler_starts: AtomicUsize,
|
2020-02-06 21:24:51 -05:00
|
|
|
compile_lock: AsyncMutex<()>,
|
2019-11-04 10:38:52 -05:00
|
|
|
}
|
|
|
|
|
2020-02-06 23:05:02 -05:00
|
|
|
impl Deref for GlobalState {
|
|
|
|
type Target = GlobalStateInner;
|
2019-11-04 10:38:52 -05:00
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-06 23:05:02 -05:00
|
|
|
impl GlobalState {
|
2020-02-26 05:52:15 -05:00
|
|
|
pub fn new(flags: flags::Flags) -> Result<Self, ErrBox> {
|
2019-11-04 10:38:52 -05:00
|
|
|
let custom_root = env::var("DENO_DIR").map(String::into).ok();
|
|
|
|
let dir = deno_dir::DenoDir::new(custom_root)?;
|
2020-02-19 08:17:13 -05:00
|
|
|
let deps_cache_location = dir.root.join("deps");
|
|
|
|
let http_cache = http_cache::HttpCache::new(&deps_cache_location)?;
|
2019-11-04 10:38:52 -05:00
|
|
|
|
|
|
|
let file_fetcher = SourceFileFetcher::new(
|
2020-02-19 08:17:13 -05:00
|
|
|
http_cache,
|
2019-11-04 10:38:52 -05:00
|
|
|
!flags.reload,
|
|
|
|
flags.cache_blacklist.clone(),
|
2019-12-03 17:48:53 -05:00
|
|
|
flags.no_remote,
|
|
|
|
flags.cached_only,
|
2020-02-17 11:59:51 -05:00
|
|
|
flags.ca_file.clone(),
|
2019-11-04 10:38:52 -05:00
|
|
|
)?;
|
|
|
|
|
|
|
|
let ts_compiler = TsCompiler::new(
|
|
|
|
file_fetcher.clone(),
|
|
|
|
dir.gen_cache.clone(),
|
|
|
|
!flags.reload,
|
|
|
|
flags.config_path.clone(),
|
|
|
|
)?;
|
|
|
|
|
|
|
|
// Note: reads lazily from disk on first call to lockfile.check()
|
|
|
|
let lockfile = if let Some(filename) = &flags.lock {
|
|
|
|
Some(Mutex::new(Lockfile::new(filename.to_string())))
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
2020-02-06 23:05:02 -05:00
|
|
|
let inner = GlobalStateInner {
|
2019-11-04 10:38:52 -05:00
|
|
|
dir,
|
2020-05-04 14:10:59 -04:00
|
|
|
permissions: Permissions::from_flags(&flags),
|
2019-11-04 10:38:52 -05:00
|
|
|
flags,
|
|
|
|
file_fetcher,
|
|
|
|
ts_compiler,
|
|
|
|
js_compiler: JsCompiler {},
|
2019-11-14 08:31:39 -05:00
|
|
|
wasm_compiler: WasmCompiler::default(),
|
2019-11-04 10:38:52 -05:00
|
|
|
lockfile,
|
2020-02-11 11:23:40 -05:00
|
|
|
compiler_starts: AtomicUsize::new(0),
|
2020-02-06 21:24:51 -05:00
|
|
|
compile_lock: AsyncMutex::new(()),
|
2019-11-04 10:38:52 -05:00
|
|
|
};
|
|
|
|
|
2020-02-06 23:05:02 -05:00
|
|
|
Ok(GlobalState(Arc::new(inner)))
|
2019-11-04 10:38:52 -05:00
|
|
|
}
|
|
|
|
|
2020-02-03 18:08:44 -05:00
|
|
|
pub async fn fetch_compiled_module(
|
2019-12-14 17:12:34 -05:00
|
|
|
&self,
|
2020-02-03 18:08:44 -05:00
|
|
|
module_specifier: ModuleSpecifier,
|
2019-11-25 09:33:23 -05:00
|
|
|
maybe_referrer: Option<ModuleSpecifier>,
|
2020-01-29 12:54:23 -05:00
|
|
|
target_lib: TargetLib,
|
2020-02-03 18:08:44 -05:00
|
|
|
) -> Result<CompiledModule, ErrBox> {
|
2019-11-04 10:38:52 -05:00
|
|
|
let state1 = self.clone();
|
|
|
|
let state2 = self.clone();
|
2020-02-03 18:08:44 -05:00
|
|
|
let module_specifier = module_specifier.clone();
|
2019-11-04 10:38:52 -05:00
|
|
|
|
2020-02-03 18:08:44 -05:00
|
|
|
let out = self
|
2019-11-04 10:38:52 -05:00
|
|
|
.file_fetcher
|
2020-02-25 14:42:00 -05:00
|
|
|
.fetch_source_file(&module_specifier, maybe_referrer)
|
2020-02-03 18:08:44 -05:00
|
|
|
.await?;
|
2020-02-06 21:24:51 -05:00
|
|
|
|
|
|
|
// TODO(ry) Try to lift compile_lock as high up in the call stack for
|
|
|
|
// sanity.
|
|
|
|
let compile_lock = self.compile_lock.lock().await;
|
|
|
|
|
|
|
|
let compiled_module = match out.media_type {
|
2020-05-01 18:32:05 -04:00
|
|
|
msg::MediaType::Json | msg::MediaType::Unknown => {
|
|
|
|
state1.js_compiler.compile(out).await
|
|
|
|
}
|
2020-02-03 18:08:44 -05:00
|
|
|
msg::MediaType::Wasm => {
|
2020-02-25 14:42:00 -05:00
|
|
|
state1.wasm_compiler.compile(state1.clone(), &out).await
|
2020-02-03 18:08:44 -05:00
|
|
|
}
|
|
|
|
msg::MediaType::TypeScript
|
|
|
|
| msg::MediaType::TSX
|
|
|
|
| msg::MediaType::JSX => {
|
|
|
|
state1
|
|
|
|
.ts_compiler
|
2020-02-25 14:42:00 -05:00
|
|
|
.compile(state1.clone(), &out, target_lib)
|
2020-02-06 21:24:51 -05:00
|
|
|
.await
|
2020-02-03 18:08:44 -05:00
|
|
|
}
|
|
|
|
msg::MediaType::JavaScript => {
|
|
|
|
if state1.ts_compiler.compile_js {
|
2020-02-06 21:24:51 -05:00
|
|
|
state2
|
2020-01-29 12:54:23 -05:00
|
|
|
.ts_compiler
|
2020-02-25 14:42:00 -05:00
|
|
|
.compile(state1.clone(), &out, target_lib)
|
2020-02-06 21:24:51 -05:00
|
|
|
.await
|
2020-02-03 18:08:44 -05:00
|
|
|
} else {
|
2020-04-06 16:52:25 -04:00
|
|
|
if let Some(types_url) = out.types_url.clone() {
|
|
|
|
let types_specifier = ModuleSpecifier::from(types_url);
|
|
|
|
state1
|
|
|
|
.file_fetcher
|
|
|
|
.fetch_source_file(
|
|
|
|
&types_specifier,
|
|
|
|
Some(module_specifier.clone()),
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.ok();
|
|
|
|
};
|
|
|
|
|
2020-02-25 14:42:00 -05:00
|
|
|
state1.js_compiler.compile(out).await
|
2019-11-04 10:38:52 -05:00
|
|
|
}
|
2019-12-14 17:12:34 -05:00
|
|
|
}
|
2020-02-06 21:24:51 -05:00
|
|
|
}?;
|
|
|
|
drop(compile_lock);
|
2020-02-03 18:08:44 -05:00
|
|
|
|
|
|
|
if let Some(ref lockfile) = state2.lockfile {
|
|
|
|
let mut g = lockfile.lock().unwrap();
|
|
|
|
if state2.flags.lock_write {
|
|
|
|
g.insert(&compiled_module);
|
|
|
|
} else {
|
|
|
|
let check = match g.check(&compiled_module) {
|
|
|
|
Err(e) => return Err(ErrBox::from(e)),
|
|
|
|
Ok(v) => v,
|
|
|
|
};
|
|
|
|
if !check {
|
|
|
|
eprintln!(
|
|
|
|
"Subresource integrity check failed --lock={}\n{}",
|
|
|
|
g.filename, compiled_module.name
|
|
|
|
);
|
|
|
|
std::process::exit(10);
|
2019-11-04 10:38:52 -05:00
|
|
|
}
|
2019-12-14 17:12:34 -05:00
|
|
|
}
|
|
|
|
}
|
2020-02-03 18:08:44 -05:00
|
|
|
Ok(compiled_module)
|
2019-11-04 10:38:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
2020-02-06 23:05:02 -05:00
|
|
|
pub fn mock(argv: Vec<String>) -> GlobalState {
|
2020-02-26 05:52:15 -05:00
|
|
|
GlobalState::new(flags::Flags {
|
2020-02-06 23:05:02 -05:00
|
|
|
argv,
|
2020-02-26 05:52:15 -05:00
|
|
|
..flags::Flags::default()
|
2020-02-06 23:05:02 -05:00
|
|
|
})
|
2019-11-04 10:38:52 -05:00
|
|
|
.unwrap()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn thread_safe() {
|
|
|
|
fn f<S: Send + Sync>(_: S) {}
|
2020-02-25 14:42:00 -05:00
|
|
|
f(GlobalState::mock(vec![]));
|
2019-11-04 10:38:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn import_map_given_for_repl() {
|
2020-02-26 05:52:15 -05:00
|
|
|
let _result = GlobalState::new(flags::Flags {
|
2020-02-06 23:05:02 -05:00
|
|
|
import_map_path: Some("import_map.json".to_string()),
|
2020-02-26 05:52:15 -05:00
|
|
|
..flags::Flags::default()
|
2020-02-06 23:05:02 -05:00
|
|
|
});
|
2019-11-04 10:38:52 -05:00
|
|
|
}
|