mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
refactor: add RootConfig
(#14985)
This commit is contained in:
parent
3236340ac8
commit
7768eccf97
21 changed files with 917 additions and 819 deletions
|
@ -11,7 +11,6 @@ use deno_core::anyhow::bail;
|
|||
use deno_core::anyhow::Context;
|
||||
use deno_core::error::custom_error;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::normalize_path;
|
||||
use deno_core::serde::Deserialize;
|
||||
use deno_core::serde::Serialize;
|
||||
use deno_core::serde::Serializer;
|
||||
|
@ -161,66 +160,6 @@ pub const IGNORED_RUNTIME_COMPILER_OPTIONS: &[&str] = &[
|
|||
"watch",
|
||||
];
|
||||
|
||||
/// Filenames that Deno will recognize when discovering config.
|
||||
const CONFIG_FILE_NAMES: [&str; 2] = ["deno.json", "deno.jsonc"];
|
||||
|
||||
pub fn discover(flags: &Flags) -> Result<Option<ConfigFile>, AnyError> {
|
||||
match &flags.config_flag {
|
||||
ConfigFlag::Disabled => Ok(None),
|
||||
ConfigFlag::Path(config_path) => Ok(Some(ConfigFile::read(config_path)?)),
|
||||
ConfigFlag::Discover => {
|
||||
if let Some(config_path_args) = flags.config_path_args() {
|
||||
let mut checked = HashSet::new();
|
||||
for f in config_path_args {
|
||||
if let Some(cf) = discover_from(&f, &mut checked)? {
|
||||
return Ok(Some(cf));
|
||||
}
|
||||
}
|
||||
// From CWD walk up to root looking for deno.json or deno.jsonc
|
||||
let cwd = std::env::current_dir()?;
|
||||
discover_from(&cwd, &mut checked)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn discover_from(
|
||||
start: &Path,
|
||||
checked: &mut HashSet<PathBuf>,
|
||||
) -> Result<Option<ConfigFile>, AnyError> {
|
||||
for ancestor in start.ancestors() {
|
||||
if checked.insert(ancestor.to_path_buf()) {
|
||||
for config_filename in CONFIG_FILE_NAMES {
|
||||
let f = ancestor.join(config_filename);
|
||||
match ConfigFile::read(f) {
|
||||
Ok(cf) => {
|
||||
return Ok(Some(cf));
|
||||
}
|
||||
Err(e) => {
|
||||
if let Some(ioerr) = e.downcast_ref::<std::io::Error>() {
|
||||
use std::io::ErrorKind::*;
|
||||
match ioerr.kind() {
|
||||
InvalidInput | PermissionDenied | NotFound => {
|
||||
// ok keep going
|
||||
}
|
||||
_ => {
|
||||
return Err(e); // Unknown error. Stop.
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(e); // Parse error or something else. Stop.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// No config file found.
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// A function that works like JavaScript's `Object.assign()`.
|
||||
pub fn json_merge(a: &mut Value, b: &Value) {
|
||||
match (a, b) {
|
||||
|
@ -235,56 +174,6 @@ pub fn json_merge(a: &mut Value, b: &Value) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Based on an optional command line import map path and an optional
|
||||
/// configuration file, return a resolved module specifier to an import map.
|
||||
pub fn resolve_import_map_specifier(
|
||||
maybe_import_map_path: Option<&str>,
|
||||
maybe_config_file: Option<&ConfigFile>,
|
||||
) -> Result<Option<ModuleSpecifier>, AnyError> {
|
||||
if let Some(import_map_path) = maybe_import_map_path {
|
||||
if let Some(config_file) = &maybe_config_file {
|
||||
if config_file.to_import_map_path().is_some() {
|
||||
log::warn!("{} the configuration file \"{}\" contains an entry for \"importMap\" that is being ignored.", crate::colors::yellow("Warning"), config_file.specifier);
|
||||
}
|
||||
}
|
||||
let specifier = deno_core::resolve_url_or_path(import_map_path)
|
||||
.context(format!("Bad URL (\"{}\") for import map.", import_map_path))?;
|
||||
return Ok(Some(specifier));
|
||||
} else if let Some(config_file) = &maybe_config_file {
|
||||
// when the import map is specifier in a config file, it needs to be
|
||||
// resolved relative to the config file, versus the CWD like with the flag
|
||||
// and with config files, we support both local and remote config files,
|
||||
// so we have treat them differently.
|
||||
if let Some(import_map_path) = config_file.to_import_map_path() {
|
||||
let specifier =
|
||||
// with local config files, it might be common to specify an import
|
||||
// map like `"importMap": "import-map.json"`, which is resolvable if
|
||||
// the file is resolved like a file path, so we will coerce the config
|
||||
// file into a file path if possible and join the import map path to
|
||||
// the file path.
|
||||
if let Ok(config_file_path) = config_file.specifier.to_file_path() {
|
||||
let import_map_file_path = normalize_path(config_file_path
|
||||
.parent()
|
||||
.ok_or_else(|| {
|
||||
anyhow!("Bad config file specifier: {}", config_file.specifier)
|
||||
})?
|
||||
.join(&import_map_path));
|
||||
ModuleSpecifier::from_file_path(import_map_file_path).unwrap()
|
||||
// otherwise if the config file is remote, we have no choice but to
|
||||
// use "import resolution" with the config file as the base.
|
||||
} else {
|
||||
deno_core::resolve_import(&import_map_path, config_file.specifier.as_str())
|
||||
.context(format!(
|
||||
"Bad URL (\"{}\") for import map.",
|
||||
import_map_path
|
||||
))?
|
||||
};
|
||||
return Ok(Some(specifier));
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn parse_compiler_options(
|
||||
compiler_options: &HashMap<String, Value>,
|
||||
maybe_specifier: Option<ModuleSpecifier>,
|
||||
|
@ -547,6 +436,66 @@ pub struct ConfigFile {
|
|||
}
|
||||
|
||||
impl ConfigFile {
|
||||
pub fn discover(flags: &Flags) -> Result<Option<ConfigFile>, AnyError> {
|
||||
match &flags.config_flag {
|
||||
ConfigFlag::Disabled => Ok(None),
|
||||
ConfigFlag::Path(config_path) => Ok(Some(ConfigFile::read(config_path)?)),
|
||||
ConfigFlag::Discover => {
|
||||
if let Some(config_path_args) = flags.config_path_args() {
|
||||
let mut checked = HashSet::new();
|
||||
for f in config_path_args {
|
||||
if let Some(cf) = Self::discover_from(&f, &mut checked)? {
|
||||
return Ok(Some(cf));
|
||||
}
|
||||
}
|
||||
// From CWD walk up to root looking for deno.json or deno.jsonc
|
||||
let cwd = std::env::current_dir()?;
|
||||
Self::discover_from(&cwd, &mut checked)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn discover_from(
|
||||
start: &Path,
|
||||
checked: &mut HashSet<PathBuf>,
|
||||
) -> Result<Option<ConfigFile>, AnyError> {
|
||||
/// Filenames that Deno will recognize when discovering config.
|
||||
const CONFIG_FILE_NAMES: [&str; 2] = ["deno.json", "deno.jsonc"];
|
||||
|
||||
for ancestor in start.ancestors() {
|
||||
if checked.insert(ancestor.to_path_buf()) {
|
||||
for config_filename in CONFIG_FILE_NAMES {
|
||||
let f = ancestor.join(config_filename);
|
||||
match ConfigFile::read(f) {
|
||||
Ok(cf) => {
|
||||
return Ok(Some(cf));
|
||||
}
|
||||
Err(e) => {
|
||||
if let Some(ioerr) = e.downcast_ref::<std::io::Error>() {
|
||||
use std::io::ErrorKind::*;
|
||||
match ioerr.kind() {
|
||||
InvalidInput | PermissionDenied | NotFound => {
|
||||
// ok keep going
|
||||
}
|
||||
_ => {
|
||||
return Err(e); // Unknown error. Stop.
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(e); // Parse error or something else. Stop.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// No config file found.
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub fn read(path_ref: impl AsRef<Path>) -> Result<Self, AnyError> {
|
||||
let path = Path::new(path_ref.as_ref());
|
||||
let config_file = if path.is_absolute() {
|
||||
|
@ -744,12 +693,36 @@ impl ConfigFile {
|
|||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_tasks_config(
|
||||
&self,
|
||||
) -> Result<BTreeMap<String, String>, AnyError> {
|
||||
let maybe_tasks_config = self.to_tasks_config()?;
|
||||
if let Some(tasks_config) = maybe_tasks_config {
|
||||
for key in tasks_config.keys() {
|
||||
if key.is_empty() {
|
||||
bail!("Configuration file task names cannot be empty");
|
||||
} else if !key
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_alphanumeric() || matches!(c, '_' | '-' | ':'))
|
||||
{
|
||||
bail!("Configuration file task names must only contain alpha-numeric characters, colons (:), underscores (_), or dashes (-). Task: {}", key);
|
||||
} else if !key.chars().next().unwrap().is_ascii_alphabetic() {
|
||||
bail!("Configuration file task names must start with an alphabetic character. Task: {}", key);
|
||||
}
|
||||
}
|
||||
Ok(tasks_config)
|
||||
} else {
|
||||
bail!("No tasks found in configuration file")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use deno_core::serde_json::json;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn read_config_file_relative() {
|
||||
|
@ -996,7 +969,9 @@ mod tests {
|
|||
let testdata = test_util::testdata_path();
|
||||
let c_md = testdata.join("fmt/with_config/subdir/c.md");
|
||||
let mut checked = HashSet::new();
|
||||
let config_file = discover_from(&c_md, &mut checked).unwrap().unwrap();
|
||||
let config_file = ConfigFile::discover_from(&c_md, &mut checked)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
assert!(checked.contains(c_md.parent().unwrap()));
|
||||
assert!(!checked.contains(&testdata));
|
||||
let fmt_config = config_file.to_fmt_config().unwrap().unwrap();
|
||||
|
@ -1012,7 +987,9 @@ mod tests {
|
|||
}
|
||||
|
||||
// If we call discover_from again starting at testdata, we ought to get None.
|
||||
assert!(discover_from(&testdata, &mut checked).unwrap().is_none());
|
||||
assert!(ConfigFile::discover_from(&testdata, &mut checked)
|
||||
.unwrap()
|
||||
.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1020,83 +997,71 @@ mod tests {
|
|||
let testdata = test_util::testdata_path();
|
||||
let d = testdata.join("malformed_config/");
|
||||
let mut checked = HashSet::new();
|
||||
let err = discover_from(&d, &mut checked).unwrap_err();
|
||||
let err = ConfigFile::discover_from(&d, &mut checked).unwrap_err();
|
||||
assert!(err.to_string().contains("Unable to parse config file"));
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[test]
|
||||
fn resolve_import_map_config_file() {
|
||||
let config_text = r#"{
|
||||
"importMap": "import_map.json"
|
||||
}"#;
|
||||
let config_specifier =
|
||||
ModuleSpecifier::parse("file:///deno/deno.jsonc").unwrap();
|
||||
let config_file = ConfigFile::new(config_text, &config_specifier).unwrap();
|
||||
let actual = resolve_import_map_specifier(None, Some(&config_file));
|
||||
assert!(actual.is_ok());
|
||||
let actual = actual.unwrap();
|
||||
assert_eq!(
|
||||
actual,
|
||||
Some(ModuleSpecifier::parse("file:///deno/import_map.json").unwrap())
|
||||
fn tasks_no_tasks() {
|
||||
run_task_error_test(r#"{}"#, "No tasks found in configuration file");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn task_name_invalid_chars() {
|
||||
run_task_error_test(
|
||||
r#"{
|
||||
"tasks": {
|
||||
"build": "deno test",
|
||||
"some%test": "deno bundle mod.ts"
|
||||
}
|
||||
}"#,
|
||||
concat!(
|
||||
"Configuration file task names must only contain alpha-numeric ",
|
||||
"characters, colons (:), underscores (_), or dashes (-). Task: some%test",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolve_import_map_config_file_remote() {
|
||||
let config_text = r#"{
|
||||
"importMap": "./import_map.json"
|
||||
}"#;
|
||||
let config_specifier =
|
||||
ModuleSpecifier::parse("https://example.com/deno.jsonc").unwrap();
|
||||
let config_file = ConfigFile::new(config_text, &config_specifier).unwrap();
|
||||
let actual = resolve_import_map_specifier(None, Some(&config_file));
|
||||
assert!(actual.is_ok());
|
||||
let actual = actual.unwrap();
|
||||
assert_eq!(
|
||||
actual,
|
||||
Some(
|
||||
ModuleSpecifier::parse("https://example.com/import_map.json").unwrap()
|
||||
)
|
||||
fn task_name_non_alpha_starting_char() {
|
||||
run_task_error_test(
|
||||
r#"{
|
||||
"tasks": {
|
||||
"build": "deno test",
|
||||
"1test": "deno bundle mod.ts"
|
||||
}
|
||||
}"#,
|
||||
concat!(
|
||||
"Configuration file task names must start with an ",
|
||||
"alphabetic character. Task: 1test",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolve_import_map_flags_take_precedence() {
|
||||
let config_text = r#"{
|
||||
"importMap": "import_map.json"
|
||||
}"#;
|
||||
let config_specifier =
|
||||
ModuleSpecifier::parse("file:///deno/deno.jsonc").unwrap();
|
||||
let config_file = ConfigFile::new(config_text, &config_specifier).unwrap();
|
||||
let actual =
|
||||
resolve_import_map_specifier(Some("import-map.json"), Some(&config_file));
|
||||
let import_map_path =
|
||||
std::env::current_dir().unwrap().join("import-map.json");
|
||||
let expected_specifier =
|
||||
ModuleSpecifier::from_file_path(&import_map_path).unwrap();
|
||||
assert!(actual.is_ok());
|
||||
let actual = actual.unwrap();
|
||||
assert_eq!(actual, Some(expected_specifier));
|
||||
fn task_name_empty() {
|
||||
run_task_error_test(
|
||||
r#"{
|
||||
"tasks": {
|
||||
"build": "deno test",
|
||||
"": "deno bundle mod.ts"
|
||||
}
|
||||
}"#,
|
||||
"Configuration file task names cannot be empty",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolve_import_map_none() {
|
||||
let config_text = r#"{}"#;
|
||||
let config_specifier =
|
||||
ModuleSpecifier::parse("file:///deno/deno.jsonc").unwrap();
|
||||
fn run_task_error_test(config_text: &str, expected_error: &str) {
|
||||
let config_dir = ModuleSpecifier::parse("file:///deno/").unwrap();
|
||||
let config_specifier = config_dir.join("tsconfig.json").unwrap();
|
||||
let config_file = ConfigFile::new(config_text, &config_specifier).unwrap();
|
||||
let actual = resolve_import_map_specifier(None, Some(&config_file));
|
||||
assert!(actual.is_ok());
|
||||
let actual = actual.unwrap();
|
||||
assert_eq!(actual, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolve_import_map_no_config() {
|
||||
let actual = resolve_import_map_specifier(None, None);
|
||||
assert!(actual.is_ok());
|
||||
let actual = actual.unwrap();
|
||||
assert_eq!(actual, None);
|
||||
assert_eq!(
|
||||
config_file
|
||||
.resolve_tasks_config()
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
expected_error,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -234,7 +234,7 @@ impl Default for DenoSubcommand {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum TypeCheckMode {
|
||||
/// Type-check all modules.
|
||||
All,
|
||||
|
@ -305,7 +305,6 @@ pub struct Flags {
|
|||
pub compat: bool,
|
||||
pub no_prompt: bool,
|
||||
pub reload: bool,
|
||||
pub repl: bool,
|
||||
pub seed: Option<u64>,
|
||||
pub unstable: bool,
|
||||
pub unsafely_ignore_certificate_errors: Option<Vec<String>>,
|
||||
|
@ -571,7 +570,6 @@ pub fn flags_from_vec(args: Vec<String>) -> clap::Result<Flags> {
|
|||
}
|
||||
|
||||
fn handle_repl_flags(flags: &mut Flags, repl_flags: ReplFlags) {
|
||||
flags.repl = true;
|
||||
flags.subcommand = DenoSubcommand::Repl(repl_flags);
|
||||
flags.allow_net = Some(vec![]);
|
||||
flags.allow_env = Some(vec![]);
|
||||
|
@ -4022,7 +4020,6 @@ mod tests {
|
|||
assert_eq!(
|
||||
r.unwrap(),
|
||||
Flags {
|
||||
repl: true,
|
||||
subcommand: DenoSubcommand::Repl(ReplFlags {
|
||||
eval_files: None,
|
||||
eval: None
|
||||
|
@ -4047,7 +4044,6 @@ mod tests {
|
|||
assert_eq!(
|
||||
r.unwrap(),
|
||||
Flags {
|
||||
repl: true,
|
||||
subcommand: DenoSubcommand::Repl(ReplFlags {
|
||||
eval_files: None,
|
||||
eval: None
|
||||
|
@ -4085,7 +4081,6 @@ mod tests {
|
|||
assert_eq!(
|
||||
r.unwrap(),
|
||||
Flags {
|
||||
repl: true,
|
||||
subcommand: DenoSubcommand::Repl(ReplFlags {
|
||||
eval_files: None,
|
||||
eval: Some("console.log('hello');".to_string()),
|
||||
|
@ -4110,7 +4105,6 @@ mod tests {
|
|||
assert_eq!(
|
||||
r.unwrap(),
|
||||
Flags {
|
||||
repl: true,
|
||||
subcommand: DenoSubcommand::Repl(ReplFlags {
|
||||
eval_files: Some(vec![
|
||||
"./a.js".to_string(),
|
||||
|
@ -4770,7 +4764,6 @@ mod tests {
|
|||
assert_eq!(
|
||||
r.unwrap(),
|
||||
Flags {
|
||||
repl: true,
|
||||
subcommand: DenoSubcommand::Repl(ReplFlags {
|
||||
eval_files: None,
|
||||
eval: Some("console.log('hello');".to_string()),
|
||||
|
@ -4845,7 +4838,6 @@ mod tests {
|
|||
assert_eq!(
|
||||
r.unwrap(),
|
||||
Flags {
|
||||
repl: true,
|
||||
subcommand: DenoSubcommand::Repl(ReplFlags {
|
||||
eval_files: None,
|
||||
eval: None
|
||||
|
|
438
cli/args/mod.rs
438
cli/args/mod.rs
|
@ -5,5 +5,441 @@ pub mod flags;
|
|||
|
||||
mod flags_allow_net;
|
||||
|
||||
pub use config_file::*;
|
||||
pub use config_file::CompilerOptions;
|
||||
pub use config_file::ConfigFile;
|
||||
pub use config_file::EmitConfigOptions;
|
||||
pub use config_file::FmtConfig;
|
||||
pub use config_file::FmtOptionsConfig;
|
||||
pub use config_file::LintConfig;
|
||||
pub use config_file::LintRulesConfig;
|
||||
pub use config_file::MaybeImportsResult;
|
||||
pub use config_file::ProseWrap;
|
||||
pub use config_file::TsConfig;
|
||||
pub use flags::*;
|
||||
|
||||
use deno_ast::ModuleSpecifier;
|
||||
use deno_core::anyhow::anyhow;
|
||||
use deno_core::anyhow::bail;
|
||||
use deno_core::anyhow::Context;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::normalize_path;
|
||||
use deno_core::url::Url;
|
||||
use deno_runtime::colors;
|
||||
use deno_runtime::deno_tls::rustls::RootCertStore;
|
||||
use deno_runtime::inspector_server::InspectorServer;
|
||||
use deno_runtime::permissions::PermissionsOptions;
|
||||
use std::collections::BTreeMap;
|
||||
use std::env;
|
||||
use std::net::SocketAddr;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::compat;
|
||||
use crate::deno_dir::DenoDir;
|
||||
use crate::emit::get_ts_config_for_emit;
|
||||
use crate::emit::TsConfigType;
|
||||
use crate::emit::TsConfigWithIgnoredOptions;
|
||||
use crate::emit::TsTypeLib;
|
||||
use crate::file_fetcher::get_root_cert_store;
|
||||
use crate::file_fetcher::CacheSetting;
|
||||
use crate::lockfile::Lockfile;
|
||||
use crate::version;
|
||||
|
||||
/// Holds the common configuration used by many sub commands
|
||||
/// and provides some helper function for creating common objects.
|
||||
pub struct RootConfig {
|
||||
// the source of the configuration is a detail the rest of the
|
||||
// application need not concern itself with, so keep these private
|
||||
flags: Flags,
|
||||
maybe_config_file: Option<ConfigFile>,
|
||||
}
|
||||
|
||||
impl RootConfig {
|
||||
pub fn from_flags(flags: Flags) -> Result<Self, AnyError> {
|
||||
if let Some(insecure_allowlist) =
|
||||
flags.unsafely_ignore_certificate_errors.as_ref()
|
||||
{
|
||||
let domains = if insecure_allowlist.is_empty() {
|
||||
"for all hostnames".to_string()
|
||||
} else {
|
||||
format!("for: {}", insecure_allowlist.join(", "))
|
||||
};
|
||||
let msg =
|
||||
format!("DANGER: TLS certificate validation is disabled {}", domains);
|
||||
eprintln!("{}", colors::yellow(msg));
|
||||
}
|
||||
|
||||
let maybe_config_file = ConfigFile::discover(&flags)?;
|
||||
Ok(Self {
|
||||
maybe_config_file,
|
||||
flags,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn maybe_config_file_specifier(&self) -> Option<ModuleSpecifier> {
|
||||
self.maybe_config_file.as_ref().map(|f| f.specifier.clone())
|
||||
}
|
||||
|
||||
pub fn ts_type_lib_window(&self) -> TsTypeLib {
|
||||
if self.flags.unstable {
|
||||
TsTypeLib::UnstableDenoWindow
|
||||
} else {
|
||||
TsTypeLib::DenoWindow
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ts_type_lib_worker(&self) -> TsTypeLib {
|
||||
if self.flags.unstable {
|
||||
TsTypeLib::UnstableDenoWorker
|
||||
} else {
|
||||
TsTypeLib::DenoWorker
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cache_setting(&self) -> CacheSetting {
|
||||
if self.flags.cached_only {
|
||||
CacheSetting::Only
|
||||
} else if !self.flags.cache_blocklist.is_empty() {
|
||||
CacheSetting::ReloadSome(self.flags.cache_blocklist.clone())
|
||||
} else if self.flags.reload {
|
||||
CacheSetting::ReloadAll
|
||||
} else {
|
||||
CacheSetting::Use
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_deno_dir(&self) -> Result<DenoDir, AnyError> {
|
||||
Ok(DenoDir::new(self.maybe_custom_root())?)
|
||||
}
|
||||
|
||||
/// Based on an optional command line import map path and an optional
|
||||
/// configuration file, return a resolved module specifier to an import map.
|
||||
pub fn resolve_import_map_path(
|
||||
&self,
|
||||
) -> Result<Option<ModuleSpecifier>, AnyError> {
|
||||
resolve_import_map_specifier(
|
||||
self.flags.import_map_path.as_deref(),
|
||||
self.maybe_config_file.as_ref(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn resolve_root_cert_store(&self) -> Result<RootCertStore, AnyError> {
|
||||
get_root_cert_store(
|
||||
None,
|
||||
self.flags.ca_stores.clone(),
|
||||
self.flags.ca_file.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn resolve_ts_config_for_emit(
|
||||
&self,
|
||||
config_type: TsConfigType,
|
||||
) -> Result<TsConfigWithIgnoredOptions, AnyError> {
|
||||
get_ts_config_for_emit(config_type, self.maybe_config_file.as_ref())
|
||||
}
|
||||
|
||||
/// Resolves the storage key to use based on the current flags, config, or main module.
|
||||
pub fn resolve_storage_key(
|
||||
&self,
|
||||
main_module: &ModuleSpecifier,
|
||||
) -> Option<String> {
|
||||
if let Some(location) = &self.flags.location {
|
||||
// if a location is set, then the ascii serialization of the location is
|
||||
// used, unless the origin is opaque, and then no storage origin is set, as
|
||||
// we can't expect the origin to be reproducible
|
||||
let storage_origin = location.origin().ascii_serialization();
|
||||
if storage_origin == "null" {
|
||||
None
|
||||
} else {
|
||||
Some(storage_origin)
|
||||
}
|
||||
} else if let Some(config_file) = &self.maybe_config_file {
|
||||
// otherwise we will use the path to the config file
|
||||
Some(config_file.specifier.to_string())
|
||||
} else {
|
||||
// otherwise we will use the path to the main module
|
||||
Some(main_module.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_inspector_server(&self) -> Option<InspectorServer> {
|
||||
let maybe_inspect_host = self.flags.inspect.or(self.flags.inspect_brk);
|
||||
maybe_inspect_host
|
||||
.map(|host| InspectorServer::new(host, version::get_user_agent()))
|
||||
}
|
||||
|
||||
pub fn resolve_lock_file(&self) -> Result<Option<Lockfile>, AnyError> {
|
||||
if let Some(filename) = &self.flags.lock {
|
||||
let lockfile = Lockfile::new(filename.clone(), self.flags.lock_write)?;
|
||||
Ok(Some(lockfile))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_tasks_config(
|
||||
&self,
|
||||
) -> Result<BTreeMap<String, String>, AnyError> {
|
||||
if let Some(config_file) = &self.maybe_config_file {
|
||||
config_file.resolve_tasks_config()
|
||||
} else {
|
||||
bail!("No config file found")
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the implied JSX import source module.
|
||||
pub fn to_maybe_jsx_import_source_module(&self) -> Option<String> {
|
||||
self
|
||||
.maybe_config_file
|
||||
.as_ref()
|
||||
.and_then(|c| c.to_maybe_jsx_import_source_module())
|
||||
}
|
||||
|
||||
/// Return any imports that should be brought into the scope of the module
|
||||
/// graph.
|
||||
pub fn to_maybe_imports(&self) -> MaybeImportsResult {
|
||||
let mut imports = Vec::new();
|
||||
if let Some(config_file) = &self.maybe_config_file {
|
||||
if let Some(config_imports) = config_file.to_maybe_imports()? {
|
||||
imports.extend(config_imports);
|
||||
}
|
||||
}
|
||||
if self.flags.compat {
|
||||
imports.extend(compat::get_node_imports());
|
||||
}
|
||||
if imports.is_empty() {
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(imports))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_lint_config(&self) -> Result<Option<LintConfig>, AnyError> {
|
||||
if let Some(config_file) = &self.maybe_config_file {
|
||||
config_file.to_lint_config()
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_fmt_config(&self) -> Result<Option<FmtConfig>, AnyError> {
|
||||
if let Some(config) = &self.maybe_config_file {
|
||||
config.to_fmt_config()
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
/// Vector of user script CLI arguments.
|
||||
pub fn argv(&self) -> &Vec<String> {
|
||||
&self.flags.argv
|
||||
}
|
||||
|
||||
pub fn check_js(&self) -> bool {
|
||||
self
|
||||
.maybe_config_file
|
||||
.as_ref()
|
||||
.map(|cf| cf.get_check_js())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn compat(&self) -> bool {
|
||||
self.flags.compat
|
||||
}
|
||||
|
||||
pub fn coverage_dir(&self) -> Option<&String> {
|
||||
self.flags.coverage_dir.as_ref()
|
||||
}
|
||||
|
||||
pub fn enable_testing_features(&self) -> bool {
|
||||
self.flags.enable_testing_features
|
||||
}
|
||||
|
||||
pub fn inspect_brk(&self) -> Option<SocketAddr> {
|
||||
self.flags.inspect_brk
|
||||
}
|
||||
|
||||
pub fn log_level(&self) -> Option<log::Level> {
|
||||
self.flags.log_level
|
||||
}
|
||||
|
||||
pub fn location_flag(&self) -> Option<&Url> {
|
||||
self.flags.location.as_ref()
|
||||
}
|
||||
|
||||
pub fn maybe_custom_root(&self) -> Option<PathBuf> {
|
||||
self
|
||||
.flags
|
||||
.cache_path
|
||||
.clone()
|
||||
.or_else(|| env::var("DENO_DIR").map(String::into).ok())
|
||||
}
|
||||
|
||||
pub fn no_clear_screen(&self) -> bool {
|
||||
self.flags.no_clear_screen
|
||||
}
|
||||
|
||||
pub fn no_remote(&self) -> bool {
|
||||
self.flags.no_remote
|
||||
}
|
||||
|
||||
pub fn permissions_options(&self) -> PermissionsOptions {
|
||||
self.flags.permissions_options()
|
||||
}
|
||||
|
||||
pub fn reload_flag(&self) -> bool {
|
||||
self.flags.reload
|
||||
}
|
||||
|
||||
pub fn seed(&self) -> Option<u64> {
|
||||
self.flags.seed
|
||||
}
|
||||
|
||||
pub fn sub_command(&self) -> &DenoSubcommand {
|
||||
&self.flags.subcommand
|
||||
}
|
||||
|
||||
pub fn type_check_mode(&self) -> TypeCheckMode {
|
||||
self.flags.type_check_mode
|
||||
}
|
||||
|
||||
pub fn unsafely_ignore_certificate_errors(&self) -> Option<&Vec<String>> {
|
||||
self.flags.unsafely_ignore_certificate_errors.as_ref()
|
||||
}
|
||||
|
||||
pub fn unstable(&self) -> bool {
|
||||
self.flags.unstable
|
||||
}
|
||||
|
||||
pub fn watch_paths(&self) -> Option<&Vec<PathBuf>> {
|
||||
self.flags.watch.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_import_map_specifier(
|
||||
maybe_import_map_path: Option<&str>,
|
||||
maybe_config_file: Option<&ConfigFile>,
|
||||
) -> Result<Option<ModuleSpecifier>, AnyError> {
|
||||
if let Some(import_map_path) = maybe_import_map_path {
|
||||
if let Some(config_file) = &maybe_config_file {
|
||||
if config_file.to_import_map_path().is_some() {
|
||||
log::warn!("{} the configuration file \"{}\" contains an entry for \"importMap\" that is being ignored.", crate::colors::yellow("Warning"), config_file.specifier);
|
||||
}
|
||||
}
|
||||
let specifier = deno_core::resolve_url_or_path(import_map_path)
|
||||
.context(format!("Bad URL (\"{}\") for import map.", import_map_path))?;
|
||||
return Ok(Some(specifier));
|
||||
} else if let Some(config_file) = &maybe_config_file {
|
||||
// when the import map is specifier in a config file, it needs to be
|
||||
// resolved relative to the config file, versus the CWD like with the flag
|
||||
// and with config files, we support both local and remote config files,
|
||||
// so we have treat them differently.
|
||||
if let Some(import_map_path) = config_file.to_import_map_path() {
|
||||
let specifier =
|
||||
// with local config files, it might be common to specify an import
|
||||
// map like `"importMap": "import-map.json"`, which is resolvable if
|
||||
// the file is resolved like a file path, so we will coerce the config
|
||||
// file into a file path if possible and join the import map path to
|
||||
// the file path.
|
||||
if let Ok(config_file_path) = config_file.specifier.to_file_path() {
|
||||
let import_map_file_path = normalize_path(config_file_path
|
||||
.parent()
|
||||
.ok_or_else(|| {
|
||||
anyhow!("Bad config file specifier: {}", config_file.specifier)
|
||||
})?
|
||||
.join(&import_map_path));
|
||||
ModuleSpecifier::from_file_path(import_map_file_path).unwrap()
|
||||
// otherwise if the config file is remote, we have no choice but to
|
||||
// use "import resolution" with the config file as the base.
|
||||
} else {
|
||||
deno_core::resolve_import(&import_map_path, config_file.specifier.as_str())
|
||||
.context(format!(
|
||||
"Bad URL (\"{}\") for import map.",
|
||||
import_map_path
|
||||
))?
|
||||
};
|
||||
return Ok(Some(specifier));
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[test]
|
||||
fn resolve_import_map_config_file() {
|
||||
let config_text = r#"{
|
||||
"importMap": "import_map.json"
|
||||
}"#;
|
||||
let config_specifier =
|
||||
ModuleSpecifier::parse("file:///deno/deno.jsonc").unwrap();
|
||||
let config_file = ConfigFile::new(config_text, &config_specifier).unwrap();
|
||||
let actual = resolve_import_map_specifier(None, Some(&config_file));
|
||||
assert!(actual.is_ok());
|
||||
let actual = actual.unwrap();
|
||||
assert_eq!(
|
||||
actual,
|
||||
Some(ModuleSpecifier::parse("file:///deno/import_map.json").unwrap())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolve_import_map_config_file_remote() {
|
||||
let config_text = r#"{
|
||||
"importMap": "./import_map.json"
|
||||
}"#;
|
||||
let config_specifier =
|
||||
ModuleSpecifier::parse("https://example.com/deno.jsonc").unwrap();
|
||||
let config_file = ConfigFile::new(config_text, &config_specifier).unwrap();
|
||||
let actual = resolve_import_map_specifier(None, Some(&config_file));
|
||||
assert!(actual.is_ok());
|
||||
let actual = actual.unwrap();
|
||||
assert_eq!(
|
||||
actual,
|
||||
Some(
|
||||
ModuleSpecifier::parse("https://example.com/import_map.json").unwrap()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolve_import_map_flags_take_precedence() {
|
||||
let config_text = r#"{
|
||||
"importMap": "import_map.json"
|
||||
}"#;
|
||||
let config_specifier =
|
||||
ModuleSpecifier::parse("file:///deno/deno.jsonc").unwrap();
|
||||
let config_file = ConfigFile::new(config_text, &config_specifier).unwrap();
|
||||
let actual =
|
||||
resolve_import_map_specifier(Some("import-map.json"), Some(&config_file));
|
||||
let import_map_path =
|
||||
std::env::current_dir().unwrap().join("import-map.json");
|
||||
let expected_specifier =
|
||||
ModuleSpecifier::from_file_path(&import_map_path).unwrap();
|
||||
assert!(actual.is_ok());
|
||||
let actual = actual.unwrap();
|
||||
assert_eq!(actual, Some(expected_specifier));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolve_import_map_none() {
|
||||
let config_text = r#"{}"#;
|
||||
let config_specifier =
|
||||
ModuleSpecifier::parse("file:///deno/deno.jsonc").unwrap();
|
||||
let config_file = ConfigFile::new(config_text, &config_specifier).unwrap();
|
||||
let actual = resolve_import_map_specifier(None, Some(&config_file));
|
||||
assert!(actual.is_ok());
|
||||
let actual = actual.unwrap();
|
||||
assert_eq!(actual, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolve_import_map_no_config() {
|
||||
let actual = resolve_import_map_specifier(None, None);
|
||||
assert!(actual.is_ok());
|
||||
let actual = actual.unwrap();
|
||||
assert_eq!(actual, None);
|
||||
}
|
||||
}
|
||||
|
|
115
cli/emit.rs
115
cli/emit.rs
|
@ -4,9 +4,9 @@
|
|||
//! populate a cache, emit files, and transform a graph into the structures for
|
||||
//! loading into an isolate.
|
||||
|
||||
use crate::args::config_file::IgnoredCompilerOptions;
|
||||
use crate::args::ConfigFile;
|
||||
use crate::args::EmitConfigOptions;
|
||||
use crate::args::IgnoredCompilerOptions;
|
||||
use crate::args::TsConfig;
|
||||
use crate::args::TypeCheckMode;
|
||||
use crate::cache::CacheType;
|
||||
|
@ -29,7 +29,6 @@ use deno_core::serde::Serialize;
|
|||
use deno_core::serde::Serializer;
|
||||
use deno_core::serde_json;
|
||||
use deno_core::serde_json::json;
|
||||
use deno_core::serde_json::Value;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use deno_graph::MediaType;
|
||||
use deno_graph::ModuleGraph;
|
||||
|
@ -127,42 +126,6 @@ impl<T: Cacher> EmitCache for T {
|
|||
}
|
||||
}
|
||||
|
||||
/// Represents the "default" type library that should be used when type
|
||||
/// checking the code in the module graph. Note that a user provided config
|
||||
/// of `"lib"` would override this value.
|
||||
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
|
||||
pub enum TypeLib {
|
||||
DenoWindow,
|
||||
DenoWorker,
|
||||
UnstableDenoWindow,
|
||||
UnstableDenoWorker,
|
||||
}
|
||||
|
||||
impl Default for TypeLib {
|
||||
fn default() -> Self {
|
||||
Self::DenoWindow
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for TypeLib {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let value = match self {
|
||||
Self::DenoWindow => vec!["deno.window".to_string()],
|
||||
Self::DenoWorker => vec!["deno.worker".to_string()],
|
||||
Self::UnstableDenoWindow => {
|
||||
vec!["deno.window".to_string(), "deno.unstable".to_string()]
|
||||
}
|
||||
Self::UnstableDenoWorker => {
|
||||
vec!["deno.worker".to_string(), "deno.unstable".to_string()]
|
||||
}
|
||||
};
|
||||
Serialize::serialize(&value, serializer)
|
||||
}
|
||||
}
|
||||
|
||||
/// A structure representing stats from an emit operation for a graph.
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct Stats(pub Vec<(String, u32)>);
|
||||
|
@ -197,28 +160,68 @@ impl fmt::Display for Stats {
|
|||
}
|
||||
}
|
||||
|
||||
/// Represents the "default" type library that should be used when type
|
||||
/// checking the code in the module graph. Note that a user provided config
|
||||
/// of `"lib"` would override this value.
|
||||
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
|
||||
pub enum TsTypeLib {
|
||||
DenoWindow,
|
||||
DenoWorker,
|
||||
UnstableDenoWindow,
|
||||
UnstableDenoWorker,
|
||||
}
|
||||
|
||||
impl Default for TsTypeLib {
|
||||
fn default() -> Self {
|
||||
Self::DenoWindow
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for TsTypeLib {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let value = match self {
|
||||
Self::DenoWindow => vec!["deno.window".to_string()],
|
||||
Self::DenoWorker => vec!["deno.worker".to_string()],
|
||||
Self::UnstableDenoWindow => {
|
||||
vec!["deno.window".to_string(), "deno.unstable".to_string()]
|
||||
}
|
||||
Self::UnstableDenoWorker => {
|
||||
vec!["deno.worker".to_string(), "deno.unstable".to_string()]
|
||||
}
|
||||
};
|
||||
Serialize::serialize(&value, serializer)
|
||||
}
|
||||
}
|
||||
|
||||
/// An enum that represents the base tsc configuration to return.
|
||||
pub enum ConfigType {
|
||||
pub enum TsConfigType {
|
||||
/// Return a configuration for bundling, using swc to emit the bundle. This is
|
||||
/// independent of type checking.
|
||||
Bundle,
|
||||
/// Return a configuration to use tsc to type check and optionally emit. This
|
||||
/// is independent of either bundling or just emitting via swc
|
||||
Check { lib: TypeLib, tsc_emit: bool },
|
||||
Check { lib: TsTypeLib, tsc_emit: bool },
|
||||
/// Return a configuration to use swc to emit single module files.
|
||||
Emit,
|
||||
}
|
||||
|
||||
/// For a given configuration type and optionally a configuration file, return a
|
||||
/// tuple of the resulting `TsConfig` struct and optionally any user
|
||||
/// configuration options that were ignored.
|
||||
pub fn get_ts_config(
|
||||
config_type: ConfigType,
|
||||
pub struct TsConfigWithIgnoredOptions {
|
||||
pub ts_config: TsConfig,
|
||||
pub maybe_ignored_options: Option<IgnoredCompilerOptions>,
|
||||
}
|
||||
|
||||
/// For a given configuration type and optionally a configuration file,
|
||||
/// return a `TsConfig` struct and optionally any user configuration
|
||||
/// options that were ignored.
|
||||
pub fn get_ts_config_for_emit(
|
||||
config_type: TsConfigType,
|
||||
maybe_config_file: Option<&ConfigFile>,
|
||||
maybe_user_config: Option<&HashMap<String, Value>>,
|
||||
) -> Result<(TsConfig, Option<IgnoredCompilerOptions>), AnyError> {
|
||||
) -> Result<TsConfigWithIgnoredOptions, AnyError> {
|
||||
let mut ts_config = match config_type {
|
||||
ConfigType::Bundle => TsConfig::new(json!({
|
||||
TsConfigType::Bundle => TsConfig::new(json!({
|
||||
"checkJs": false,
|
||||
"emitDecoratorMetadata": false,
|
||||
"importsNotUsedAsValues": "remove",
|
||||
|
@ -229,7 +232,7 @@ pub fn get_ts_config(
|
|||
"jsxFactory": "React.createElement",
|
||||
"jsxFragmentFactory": "React.Fragment",
|
||||
})),
|
||||
ConfigType::Check { tsc_emit, lib } => {
|
||||
TsConfigType::Check { tsc_emit, lib } => {
|
||||
let mut ts_config = TsConfig::new(json!({
|
||||
"allowJs": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
|
@ -263,7 +266,7 @@ pub fn get_ts_config(
|
|||
}
|
||||
ts_config
|
||||
}
|
||||
ConfigType::Emit => TsConfig::new(json!({
|
||||
TsConfigType::Emit => TsConfig::new(json!({
|
||||
"checkJs": false,
|
||||
"emitDecoratorMetadata": false,
|
||||
"importsNotUsedAsValues": "remove",
|
||||
|
@ -276,15 +279,15 @@ pub fn get_ts_config(
|
|||
"resolveJsonModule": true,
|
||||
})),
|
||||
};
|
||||
let maybe_ignored_options = if let Some(user_options) = maybe_user_config {
|
||||
ts_config.merge_user_config(user_options)?
|
||||
} else {
|
||||
ts_config.merge_tsconfig_from_config_file(maybe_config_file)?
|
||||
};
|
||||
let maybe_ignored_options =
|
||||
ts_config.merge_tsconfig_from_config_file(maybe_config_file)?;
|
||||
ts_config.merge(&json!({
|
||||
"moduleDetection": "force",
|
||||
}));
|
||||
Ok((ts_config, maybe_ignored_options))
|
||||
Ok(TsConfigWithIgnoredOptions {
|
||||
ts_config,
|
||||
maybe_ignored_options,
|
||||
})
|
||||
}
|
||||
|
||||
/// Transform the graph into root specifiers that we can feed `tsc`. We have to
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::colors;
|
||||
use crate::emit::TypeLib;
|
||||
use crate::emit::TsTypeLib;
|
||||
use crate::errors::get_error_class_name;
|
||||
|
||||
use deno_core::error::custom_error;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::ModuleSpecifier;
|
||||
|
@ -43,7 +44,7 @@ pub enum ModuleEntry {
|
|||
ts_check: bool,
|
||||
/// A set of type libs that the module has passed a type check with this
|
||||
/// session. This would consist of window, worker or both.
|
||||
checked_libs: HashSet<TypeLib>,
|
||||
checked_libs: HashSet<TsTypeLib>,
|
||||
maybe_types: Option<Resolved>,
|
||||
},
|
||||
Configuration {
|
||||
|
@ -385,7 +386,7 @@ impl GraphData {
|
|||
pub fn set_type_checked(
|
||||
&mut self,
|
||||
roots: &[(ModuleSpecifier, ModuleKind)],
|
||||
lib: &TypeLib,
|
||||
lib: TsTypeLib,
|
||||
) {
|
||||
let specifiers: Vec<ModuleSpecifier> =
|
||||
match self.walk(roots, true, true, true) {
|
||||
|
@ -396,7 +397,7 @@ impl GraphData {
|
|||
if let ModuleEntry::Module { checked_libs, .. } =
|
||||
self.modules.get_mut(&specifier).unwrap()
|
||||
{
|
||||
checked_libs.insert(lib.clone());
|
||||
checked_libs.insert(lib);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -405,7 +406,7 @@ impl GraphData {
|
|||
pub fn is_type_checked(
|
||||
&self,
|
||||
roots: &[(ModuleSpecifier, ModuleKind)],
|
||||
lib: &TypeLib,
|
||||
lib: &TsTypeLib,
|
||||
) -> bool {
|
||||
roots.iter().all(|(r, _)| {
|
||||
let found = self.follow_redirect(r);
|
||||
|
|
|
@ -49,13 +49,13 @@ impl CacheServer {
|
|||
let _join_handle = thread::spawn(move || {
|
||||
let runtime = create_basic_runtime();
|
||||
runtime.block_on(async {
|
||||
let ps = ProcState::build(Arc::new(Flags {
|
||||
let ps = ProcState::build(Flags {
|
||||
cache_path: maybe_cache_path,
|
||||
ca_stores: maybe_ca_stores,
|
||||
ca_file: maybe_ca_file,
|
||||
unsafely_ignore_certificate_errors,
|
||||
..Default::default()
|
||||
}))
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
let maybe_import_map_resolver =
|
||||
|
|
|
@ -364,7 +364,7 @@ impl Inner {
|
|||
if let Some(root_uri) = &self.config.root_uri {
|
||||
let root_path = fs_util::specifier_to_file_path(root_uri)?;
|
||||
let mut checked = std::collections::HashSet::new();
|
||||
let maybe_config = crate::args::discover_from(&root_path, &mut checked)?;
|
||||
let maybe_config = ConfigFile::discover_from(&root_path, &mut checked)?;
|
||||
Ok(maybe_config.map(|c| {
|
||||
lsp_log!(" Auto-resolved configuration file: \"{}\"", c.specifier);
|
||||
c
|
||||
|
|
|
@ -8,7 +8,6 @@ use crate::args::flags_from_vec;
|
|||
use crate::args::DenoSubcommand;
|
||||
use crate::checksum;
|
||||
use crate::create_main_worker;
|
||||
use crate::emit;
|
||||
use crate::located_script_name;
|
||||
use crate::lsp::client::Client;
|
||||
use crate::lsp::client::TestingNotification;
|
||||
|
@ -308,9 +307,9 @@ impl TestRun {
|
|||
let args = self.get_args();
|
||||
lsp_log!("Executing test run with arguments: {}", args.join(" "));
|
||||
let flags = flags_from_vec(args.into_iter().map(String::from).collect())?;
|
||||
let ps = proc_state::ProcState::build(Arc::new(flags)).await?;
|
||||
let ps = proc_state::ProcState::build(flags).await?;
|
||||
let permissions =
|
||||
Permissions::from_options(&ps.flags.permissions_options());
|
||||
Permissions::from_options(&ps.config.permissions_options());
|
||||
test::check_specifiers(
|
||||
&ps,
|
||||
permissions.clone(),
|
||||
|
@ -319,7 +318,6 @@ impl TestRun {
|
|||
.iter()
|
||||
.map(|s| (s.clone(), test::TestMode::Executable))
|
||||
.collect(),
|
||||
emit::TypeLib::DenoWindow,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
@ -327,7 +325,7 @@ impl TestRun {
|
|||
let sender = TestEventSender::new(sender);
|
||||
|
||||
let (concurrent_jobs, fail_fast) =
|
||||
if let DenoSubcommand::Test(test_flags) = &ps.flags.subcommand {
|
||||
if let DenoSubcommand::Test(test_flags) = ps.config.sub_command() {
|
||||
(
|
||||
test_flags.concurrent_jobs.into(),
|
||||
test_flags.fail_fast.map(|count| count.into()),
|
||||
|
|
223
cli/main.rs
223
cli/main.rs
|
@ -36,7 +36,6 @@ mod version;
|
|||
mod windows_util;
|
||||
|
||||
use crate::args::flags_from_vec;
|
||||
use crate::args::resolve_import_map_specifier;
|
||||
use crate::args::BenchFlags;
|
||||
use crate::args::BundleFlags;
|
||||
use crate::args::CacheFlags;
|
||||
|
@ -60,6 +59,7 @@ use crate::args::TypeCheckMode;
|
|||
use crate::args::UninstallFlags;
|
||||
use crate::args::UpgradeFlags;
|
||||
use crate::args::VendorFlags;
|
||||
use crate::emit::TsConfigType;
|
||||
use crate::file_fetcher::File;
|
||||
use crate::file_watcher::ResolutionResult;
|
||||
use crate::fmt_errors::format_js_error;
|
||||
|
@ -70,6 +70,7 @@ use crate::proc_state::ProcState;
|
|||
use crate::resolver::ImportMapResolver;
|
||||
use crate::resolver::JsxResolver;
|
||||
|
||||
use args::RootConfig;
|
||||
use deno_ast::MediaType;
|
||||
use deno_core::error::generic_error;
|
||||
use deno_core::error::AnyError;
|
||||
|
@ -108,7 +109,7 @@ use std::sync::Arc;
|
|||
fn create_web_worker_preload_module_callback(
|
||||
ps: ProcState,
|
||||
) -> Arc<PreloadModuleCb> {
|
||||
let compat = ps.flags.compat;
|
||||
let compat = ps.config.compat();
|
||||
|
||||
Arc::new(move |mut worker| {
|
||||
let fut = async move {
|
||||
|
@ -143,30 +144,30 @@ fn create_web_worker_callback(
|
|||
|
||||
let options = WebWorkerOptions {
|
||||
bootstrap: BootstrapOptions {
|
||||
args: ps.flags.argv.clone(),
|
||||
args: ps.config.argv().clone(),
|
||||
cpu_count: std::thread::available_parallelism()
|
||||
.map(|p| p.get())
|
||||
.unwrap_or(1),
|
||||
debug_flag: ps
|
||||
.flags
|
||||
.log_level
|
||||
.config
|
||||
.log_level()
|
||||
.map_or(false, |l| l == log::Level::Debug),
|
||||
enable_testing_features: ps.flags.enable_testing_features,
|
||||
enable_testing_features: ps.config.enable_testing_features(),
|
||||
location: Some(args.main_module.clone()),
|
||||
no_color: !colors::use_color(),
|
||||
is_tty: colors::is_tty(),
|
||||
runtime_version: version::deno(),
|
||||
ts_version: version::TYPESCRIPT.to_string(),
|
||||
unstable: ps.flags.unstable,
|
||||
unstable: ps.config.unstable(),
|
||||
user_agent: version::get_user_agent(),
|
||||
},
|
||||
extensions,
|
||||
unsafely_ignore_certificate_errors: ps
|
||||
.flags
|
||||
.unsafely_ignore_certificate_errors
|
||||
.clone(),
|
||||
root_cert_store: ps.root_cert_store.clone(),
|
||||
seed: ps.flags.seed,
|
||||
.config
|
||||
.unsafely_ignore_certificate_errors()
|
||||
.map(ToOwned::to_owned),
|
||||
root_cert_store: Some(ps.root_cert_store.clone()),
|
||||
seed: ps.config.seed(),
|
||||
module_loader,
|
||||
create_web_worker_cb,
|
||||
preload_module_cb,
|
||||
|
@ -203,31 +204,14 @@ pub fn create_main_worker(
|
|||
let module_loader = CliModuleLoader::new(ps.clone());
|
||||
|
||||
let maybe_inspector_server = ps.maybe_inspector_server.clone();
|
||||
let should_break_on_first_statement = ps.flags.inspect_brk.is_some();
|
||||
let should_break_on_first_statement = ps.config.inspect_brk().is_some();
|
||||
|
||||
let create_web_worker_cb =
|
||||
create_web_worker_callback(ps.clone(), stdio.clone());
|
||||
let web_worker_preload_module_cb =
|
||||
create_web_worker_preload_module_callback(ps.clone());
|
||||
|
||||
let maybe_storage_key = if let Some(location) = &ps.flags.location {
|
||||
// if a location is set, then the ascii serialization of the location is
|
||||
// used, unless the origin is opaque, and then no storage origin is set, as
|
||||
// we can't expect the origin to be reproducible
|
||||
let storage_origin = location.origin().ascii_serialization();
|
||||
if storage_origin == "null" {
|
||||
None
|
||||
} else {
|
||||
Some(storage_origin)
|
||||
}
|
||||
} else if let Some(config_file) = &ps.maybe_config_file {
|
||||
// otherwise we will use the path to the config file
|
||||
Some(config_file.specifier.to_string())
|
||||
} else {
|
||||
// otherwise we will use the path to the main module
|
||||
Some(main_module.to_string())
|
||||
};
|
||||
|
||||
let maybe_storage_key = ps.config.resolve_storage_key(&main_module);
|
||||
let origin_storage_dir = maybe_storage_key.map(|key| {
|
||||
ps.dir
|
||||
.root
|
||||
|
@ -241,27 +225,30 @@ pub fn create_main_worker(
|
|||
|
||||
let options = WorkerOptions {
|
||||
bootstrap: BootstrapOptions {
|
||||
args: ps.flags.argv.clone(),
|
||||
args: ps.config.argv().clone(),
|
||||
cpu_count: std::thread::available_parallelism()
|
||||
.map(|p| p.get())
|
||||
.unwrap_or(1),
|
||||
debug_flag: ps.flags.log_level.map_or(false, |l| l == log::Level::Debug),
|
||||
enable_testing_features: ps.flags.enable_testing_features,
|
||||
location: ps.flags.location.clone(),
|
||||
debug_flag: ps
|
||||
.config
|
||||
.log_level()
|
||||
.map_or(false, |l| l == log::Level::Debug),
|
||||
enable_testing_features: ps.config.enable_testing_features(),
|
||||
location: ps.config.location_flag().map(ToOwned::to_owned),
|
||||
no_color: !colors::use_color(),
|
||||
is_tty: colors::is_tty(),
|
||||
runtime_version: version::deno(),
|
||||
ts_version: version::TYPESCRIPT.to_string(),
|
||||
unstable: ps.flags.unstable,
|
||||
unstable: ps.config.unstable(),
|
||||
user_agent: version::get_user_agent(),
|
||||
},
|
||||
extensions,
|
||||
unsafely_ignore_certificate_errors: ps
|
||||
.flags
|
||||
.unsafely_ignore_certificate_errors
|
||||
.clone(),
|
||||
root_cert_store: ps.root_cert_store.clone(),
|
||||
seed: ps.flags.seed,
|
||||
.config
|
||||
.unsafely_ignore_certificate_errors()
|
||||
.map(ToOwned::to_owned),
|
||||
root_cert_store: Some(ps.root_cert_store.clone()),
|
||||
seed: ps.config.seed(),
|
||||
source_map_getter: Some(Box::new(ps.clone())),
|
||||
format_js_error_fn: Some(Arc::new(format_js_error)),
|
||||
create_web_worker_cb,
|
||||
|
@ -412,7 +399,7 @@ async fn compile_command(
|
|||
)?;
|
||||
|
||||
let module_specifier = resolve_url_or_path(&compile_flags.source_file)?;
|
||||
let ps = ProcState::build(Arc::new(flags)).await?;
|
||||
let ps = ProcState::build(flags).await?;
|
||||
let deno_dir = &ps.dir;
|
||||
|
||||
let output_path =
|
||||
|
@ -460,7 +447,7 @@ async fn info_command(
|
|||
flags: Flags,
|
||||
info_flags: InfoFlags,
|
||||
) -> Result<i32, AnyError> {
|
||||
let ps = ProcState::build(Arc::new(flags)).await?;
|
||||
let ps = ProcState::build(flags).await?;
|
||||
if let Some(specifier) = info_flags.file {
|
||||
let specifier = resolve_url_or_path(&specifier)?;
|
||||
let mut cache = cache::FetchCacher::new(
|
||||
|
@ -472,10 +459,10 @@ async fn info_command(
|
|||
let maybe_locker = lockfile::as_maybe_locker(ps.lockfile.clone());
|
||||
let maybe_import_map_resolver =
|
||||
ps.maybe_import_map.clone().map(ImportMapResolver::new);
|
||||
let maybe_jsx_resolver = ps.maybe_config_file.as_ref().and_then(|cf| {
|
||||
cf.to_maybe_jsx_import_source_module()
|
||||
.map(|im| JsxResolver::new(im, maybe_import_map_resolver.clone()))
|
||||
});
|
||||
let maybe_jsx_resolver = ps
|
||||
.config
|
||||
.to_maybe_jsx_import_source_module()
|
||||
.map(|im| JsxResolver::new(im, maybe_import_map_resolver.clone()));
|
||||
let maybe_resolver = if maybe_jsx_resolver.is_some() {
|
||||
maybe_jsx_resolver.as_ref().map(|jr| jr.as_resolver())
|
||||
} else {
|
||||
|
@ -502,7 +489,7 @@ async fn info_command(
|
|||
}
|
||||
} else {
|
||||
// If it was just "deno info" print location of caches and exit
|
||||
print_cache_info(&ps, info_flags.json, ps.flags.location.as_ref())?;
|
||||
print_cache_info(&ps, info_flags.json, ps.config.location_flag())?;
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
|
@ -516,7 +503,7 @@ async fn install_command(
|
|||
preload_flags.inspect_brk = None;
|
||||
let permissions =
|
||||
Permissions::from_options(&preload_flags.permissions_options());
|
||||
let ps = ProcState::build(Arc::new(preload_flags)).await?;
|
||||
let ps = ProcState::build(preload_flags).await?;
|
||||
let main_module = resolve_url_or_path(&install_flags.module_url)?;
|
||||
let mut worker = create_main_worker(
|
||||
&ps,
|
||||
|
@ -560,19 +547,15 @@ async fn cache_command(
|
|||
flags: Flags,
|
||||
cache_flags: CacheFlags,
|
||||
) -> Result<i32, AnyError> {
|
||||
let lib = if flags.unstable {
|
||||
emit::TypeLib::UnstableDenoWindow
|
||||
} else {
|
||||
emit::TypeLib::DenoWindow
|
||||
};
|
||||
let ps = ProcState::build(Arc::new(flags)).await?;
|
||||
let ps = ProcState::build(flags).await?;
|
||||
let lib = ps.config.ts_type_lib_window();
|
||||
|
||||
for file in cache_flags.files {
|
||||
let specifier = resolve_url_or_path(&file)?;
|
||||
ps.prepare_module_load(
|
||||
vec![specifier],
|
||||
false,
|
||||
lib.clone(),
|
||||
lib,
|
||||
Permissions::allow_all(),
|
||||
Permissions::allow_all(),
|
||||
false,
|
||||
|
@ -605,7 +588,7 @@ async fn eval_command(
|
|||
let main_module =
|
||||
resolve_url_or_path(&format!("./$deno$eval.{}", eval_flags.ext))?;
|
||||
let permissions = Permissions::from_options(&flags.permissions_options());
|
||||
let ps = ProcState::build(Arc::new(flags)).await?;
|
||||
let ps = ProcState::build(flags).await?;
|
||||
let mut worker = create_main_worker(
|
||||
&ps,
|
||||
main_module.clone(),
|
||||
|
@ -634,7 +617,7 @@ async fn eval_command(
|
|||
// to allow module access by TS compiler.
|
||||
ps.file_fetcher.insert_cached(file);
|
||||
debug!("main_module {}", &main_module);
|
||||
if ps.flags.compat {
|
||||
if ps.config.compat() {
|
||||
worker.execute_side_module(&compat::GLOBAL_URL).await?;
|
||||
}
|
||||
worker.execute_main_module(&main_module).await?;
|
||||
|
@ -656,17 +639,13 @@ async fn create_graph_and_maybe_check(
|
|||
Permissions::allow_all(),
|
||||
);
|
||||
let maybe_locker = lockfile::as_maybe_locker(ps.lockfile.clone());
|
||||
let maybe_imports = if let Some(config_file) = &ps.maybe_config_file {
|
||||
config_file.to_maybe_imports()?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let maybe_imports = ps.config.to_maybe_imports()?;
|
||||
let maybe_import_map_resolver =
|
||||
ps.maybe_import_map.clone().map(ImportMapResolver::new);
|
||||
let maybe_jsx_resolver = ps.maybe_config_file.as_ref().and_then(|cf| {
|
||||
cf.to_maybe_jsx_import_source_module()
|
||||
.map(|im| JsxResolver::new(im, maybe_import_map_resolver.clone()))
|
||||
});
|
||||
let maybe_jsx_resolver = ps
|
||||
.config
|
||||
.to_maybe_jsx_import_source_module()
|
||||
.map(|im| JsxResolver::new(im, maybe_import_map_resolver.clone()));
|
||||
let maybe_resolver = if maybe_jsx_resolver.is_some() {
|
||||
maybe_jsx_resolver.as_ref().map(|jr| jr.as_resolver())
|
||||
} else {
|
||||
|
@ -688,49 +667,36 @@ async fn create_graph_and_maybe_check(
|
|||
.await,
|
||||
);
|
||||
|
||||
let check_js = ps
|
||||
.maybe_config_file
|
||||
.as_ref()
|
||||
.map(|cf| cf.get_check_js())
|
||||
.unwrap_or(false);
|
||||
let check_js = ps.config.check_js();
|
||||
graph_valid(
|
||||
&graph,
|
||||
ps.flags.type_check_mode != TypeCheckMode::None,
|
||||
ps.config.type_check_mode() != TypeCheckMode::None,
|
||||
check_js,
|
||||
)?;
|
||||
graph_lock_or_exit(&graph);
|
||||
|
||||
if ps.flags.type_check_mode != TypeCheckMode::None {
|
||||
let lib = if ps.flags.unstable {
|
||||
emit::TypeLib::UnstableDenoWindow
|
||||
} else {
|
||||
emit::TypeLib::DenoWindow
|
||||
};
|
||||
let (ts_config, maybe_ignored_options) = emit::get_ts_config(
|
||||
emit::ConfigType::Check {
|
||||
if ps.config.type_check_mode() != TypeCheckMode::None {
|
||||
let ts_config_result =
|
||||
ps.config.resolve_ts_config_for_emit(TsConfigType::Check {
|
||||
tsc_emit: false,
|
||||
lib,
|
||||
},
|
||||
ps.maybe_config_file.as_ref(),
|
||||
None,
|
||||
)?;
|
||||
if let Some(ignored_options) = maybe_ignored_options {
|
||||
lib: ps.config.ts_type_lib_window(),
|
||||
})?;
|
||||
if let Some(ignored_options) = ts_config_result.maybe_ignored_options {
|
||||
eprintln!("{}", ignored_options);
|
||||
}
|
||||
let maybe_config_specifier =
|
||||
ps.maybe_config_file.as_ref().map(|cf| cf.specifier.clone());
|
||||
let maybe_config_specifier = ps.config.maybe_config_file_specifier();
|
||||
let check_result = emit::check_and_maybe_emit(
|
||||
&graph.roots,
|
||||
Arc::new(RwLock::new(graph.as_ref().into())),
|
||||
&ps.dir.gen_cache,
|
||||
emit::CheckOptions {
|
||||
type_check_mode: ps.flags.type_check_mode.clone(),
|
||||
type_check_mode: ps.config.type_check_mode(),
|
||||
debug,
|
||||
emit_with_diagnostics: false,
|
||||
maybe_config_specifier,
|
||||
ts_config,
|
||||
ts_config: ts_config_result.ts_config,
|
||||
log_checks: true,
|
||||
reload: ps.flags.reload,
|
||||
reload: ps.config.reload_flag(),
|
||||
reload_exclusions: Default::default(),
|
||||
},
|
||||
)?;
|
||||
|
@ -746,17 +712,13 @@ async fn create_graph_and_maybe_check(
|
|||
fn bundle_module_graph(
|
||||
graph: &deno_graph::ModuleGraph,
|
||||
ps: &ProcState,
|
||||
flags: &Flags,
|
||||
) -> Result<deno_emit::BundleEmit, AnyError> {
|
||||
info!("{} {}", colors::green("Bundle"), graph.roots[0].0);
|
||||
|
||||
let (ts_config, maybe_ignored_options) = emit::get_ts_config(
|
||||
emit::ConfigType::Bundle,
|
||||
ps.maybe_config_file.as_ref(),
|
||||
None,
|
||||
)?;
|
||||
if flags.type_check_mode == TypeCheckMode::None {
|
||||
if let Some(ignored_options) = maybe_ignored_options {
|
||||
let ts_config_result =
|
||||
ps.config.resolve_ts_config_for_emit(TsConfigType::Bundle)?;
|
||||
if ps.config.type_check_mode() == TypeCheckMode::None {
|
||||
if let Some(ignored_options) = ts_config_result.maybe_ignored_options {
|
||||
eprintln!("{}", ignored_options);
|
||||
}
|
||||
}
|
||||
|
@ -765,7 +727,7 @@ fn bundle_module_graph(
|
|||
graph,
|
||||
deno_emit::BundleOptions {
|
||||
bundle_type: deno_emit::BundleType::Module,
|
||||
emit_options: ts_config.into(),
|
||||
emit_options: ts_config_result.ts_config.into(),
|
||||
emit_ignore_directives: true,
|
||||
},
|
||||
)
|
||||
|
@ -776,16 +738,16 @@ async fn bundle_command(
|
|||
bundle_flags: BundleFlags,
|
||||
) -> Result<i32, AnyError> {
|
||||
let debug = flags.log_level == Some(log::Level::Debug);
|
||||
let flags = Arc::new(flags);
|
||||
let root_config = Arc::new(RootConfig::from_flags(flags)?);
|
||||
let resolver = |_| {
|
||||
let flags = flags.clone();
|
||||
let root_config = root_config.clone();
|
||||
let source_file1 = bundle_flags.source_file.clone();
|
||||
let source_file2 = bundle_flags.source_file.clone();
|
||||
async move {
|
||||
let module_specifier = resolve_url_or_path(&source_file1)?;
|
||||
|
||||
debug!(">>>>> bundle START");
|
||||
let ps = ProcState::build(flags).await?;
|
||||
let ps = ProcState::from_root_config(root_config).await?;
|
||||
|
||||
let graph =
|
||||
create_graph_and_maybe_check(module_specifier, &ps, debug).await?;
|
||||
|
@ -798,11 +760,10 @@ async fn bundle_command(
|
|||
})
|
||||
.collect();
|
||||
|
||||
if let Ok(Some(import_map_path)) = resolve_import_map_specifier(
|
||||
ps.flags.import_map_path.as_deref(),
|
||||
ps.maybe_config_file.as_ref(),
|
||||
)
|
||||
.map(|ms| ms.and_then(|ref s| s.to_file_path().ok()))
|
||||
if let Ok(Some(import_map_path)) = ps
|
||||
.config
|
||||
.resolve_import_map_path()
|
||||
.map(|ms| ms.and_then(|ref s| s.to_file_path().ok()))
|
||||
{
|
||||
paths_to_watch.push(import_map_path);
|
||||
}
|
||||
|
@ -824,7 +785,7 @@ async fn bundle_command(
|
|||
let operation = |(ps, graph): (ProcState, Arc<deno_graph::ModuleGraph>)| {
|
||||
let out_file = bundle_flags.out_file.clone();
|
||||
async move {
|
||||
let bundle_output = bundle_module_graph(graph.as_ref(), &ps, &ps.flags)?;
|
||||
let bundle_output = bundle_module_graph(graph.as_ref(), &ps)?;
|
||||
debug!(">>>>> bundle END");
|
||||
|
||||
if let Some(out_file) = out_file.as_ref() {
|
||||
|
@ -862,13 +823,13 @@ async fn bundle_command(
|
|||
}
|
||||
};
|
||||
|
||||
if flags.watch.is_some() {
|
||||
if root_config.watch_paths().is_some() {
|
||||
file_watcher::watch_func(
|
||||
resolver,
|
||||
operation,
|
||||
file_watcher::PrintConfig {
|
||||
job_name: "Bundle".to_string(),
|
||||
clear_screen: !flags.no_clear_screen,
|
||||
clear_screen: !root_config.no_clear_screen(),
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
@ -897,14 +858,10 @@ async fn format_command(
|
|||
flags: Flags,
|
||||
fmt_flags: FmtFlags,
|
||||
) -> Result<i32, AnyError> {
|
||||
let ps = ProcState::build(Arc::new(flags)).await?;
|
||||
let maybe_fmt_config = if let Some(config_file) = &ps.maybe_config_file {
|
||||
config_file.to_fmt_config()?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let config = RootConfig::from_flags(flags)?;
|
||||
|
||||
if fmt_flags.files.len() == 1 && fmt_flags.files[0].to_string_lossy() == "-" {
|
||||
let maybe_fmt_config = config.to_fmt_config()?;
|
||||
tools::fmt::format_stdin(
|
||||
fmt_flags,
|
||||
maybe_fmt_config.map(|c| c.options).unwrap_or_default(),
|
||||
|
@ -912,8 +869,7 @@ async fn format_command(
|
|||
return Ok(0);
|
||||
}
|
||||
|
||||
tools::fmt::format(ps.flags.as_ref(), fmt_flags, maybe_fmt_config, &ps.dir)
|
||||
.await?;
|
||||
tools::fmt::format(&config, fmt_flags).await?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
|
@ -922,16 +878,15 @@ async fn repl_command(
|
|||
repl_flags: ReplFlags,
|
||||
) -> Result<i32, AnyError> {
|
||||
let main_module = resolve_url_or_path("./$deno$repl.ts").unwrap();
|
||||
let permissions = Permissions::from_options(&flags.permissions_options());
|
||||
let ps = ProcState::build(Arc::new(flags)).await?;
|
||||
let ps = ProcState::build(flags).await?;
|
||||
let mut worker = create_main_worker(
|
||||
&ps,
|
||||
main_module.clone(),
|
||||
permissions,
|
||||
Permissions::from_options(&ps.config.permissions_options()),
|
||||
vec![],
|
||||
Default::default(),
|
||||
);
|
||||
if ps.flags.compat {
|
||||
if ps.config.compat() {
|
||||
worker.execute_side_module(&compat::GLOBAL_URL).await?;
|
||||
compat::add_global_require(&mut worker.js_runtime, main_module.as_str())?;
|
||||
worker.run_event_loop(false).await?;
|
||||
|
@ -943,13 +898,12 @@ async fn repl_command(
|
|||
}
|
||||
|
||||
async fn run_from_stdin(flags: Flags) -> Result<i32, AnyError> {
|
||||
let ps = ProcState::build(Arc::new(flags)).await?;
|
||||
let permissions = Permissions::from_options(&ps.flags.permissions_options());
|
||||
let ps = ProcState::build(flags).await?;
|
||||
let main_module = resolve_url_or_path("./$deno$stdin.ts").unwrap();
|
||||
let mut worker = create_main_worker(
|
||||
&ps.clone(),
|
||||
main_module.clone(),
|
||||
permissions,
|
||||
Permissions::from_options(&ps.config.permissions_options()),
|
||||
vec![],
|
||||
Default::default(),
|
||||
);
|
||||
|
@ -970,7 +924,7 @@ async fn run_from_stdin(flags: Flags) -> Result<i32, AnyError> {
|
|||
ps.file_fetcher.insert_cached(source_file);
|
||||
|
||||
debug!("main_module {}", main_module);
|
||||
if ps.flags.compat {
|
||||
if ps.config.compat() {
|
||||
worker.execute_side_module(&compat::GLOBAL_URL).await?;
|
||||
}
|
||||
worker.execute_main_module(&main_module).await?;
|
||||
|
@ -1049,8 +1003,9 @@ async fn run_with_watch(flags: Flags, script: String) -> Result<i32, AnyError> {
|
|||
let flags = flags.clone();
|
||||
let permissions = Permissions::from_options(&flags.permissions_options());
|
||||
async move {
|
||||
let ps = ProcState::build_for_file_watcher(flags.clone(), sender.clone())
|
||||
.await?;
|
||||
let ps =
|
||||
ProcState::build_for_file_watcher((*flags).clone(), sender.clone())
|
||||
.await?;
|
||||
// We make use an module executor guard to ensure that unload is always fired when an
|
||||
// operation is called.
|
||||
let mut executor = FileWatcherModuleExecutor::new(
|
||||
|
@ -1103,8 +1058,8 @@ async fn run_command(
|
|||
// map specified and bare specifier is used on the command line - this should
|
||||
// probably call `ProcState::resolve` instead
|
||||
let main_module = resolve_url_or_path(&run_flags.script)?;
|
||||
let ps = ProcState::build(Arc::new(flags)).await?;
|
||||
let permissions = Permissions::from_options(&ps.flags.permissions_options());
|
||||
let ps = ProcState::build(flags).await?;
|
||||
let permissions = Permissions::from_options(&ps.config.permissions_options());
|
||||
let mut worker = create_main_worker(
|
||||
&ps,
|
||||
main_module.clone(),
|
||||
|
@ -1130,7 +1085,7 @@ async fn run_command(
|
|||
|
||||
debug!("main_module {}", main_module);
|
||||
|
||||
if ps.flags.compat {
|
||||
if ps.config.compat() {
|
||||
// TODO(bartlomieju): fix me
|
||||
assert_eq!(main_module.scheme(), "file");
|
||||
|
||||
|
@ -1254,7 +1209,7 @@ async fn vendor_command(
|
|||
flags: Flags,
|
||||
vendor_flags: VendorFlags,
|
||||
) -> Result<i32, AnyError> {
|
||||
let ps = ProcState::build(Arc::new(flags)).await?;
|
||||
let ps = ProcState::build(flags).await?;
|
||||
tools::vendor::vendor(ps, vendor_flags).await?;
|
||||
Ok(0)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::emit::TypeLib;
|
||||
use crate::emit::TsTypeLib;
|
||||
use crate::proc_state::ProcState;
|
||||
|
||||
use deno_core::error::AnyError;
|
||||
|
@ -16,7 +16,7 @@ use std::rc::Rc;
|
|||
use std::str;
|
||||
|
||||
pub struct CliModuleLoader {
|
||||
pub lib: TypeLib,
|
||||
pub lib: TsTypeLib,
|
||||
/// The initial set of permissions used to resolve the static imports in the
|
||||
/// worker. They are decoupled from the worker (dynamic) permissions since
|
||||
/// read access errors must be raised based on the parent thread permissions.
|
||||
|
@ -26,28 +26,16 @@ pub struct CliModuleLoader {
|
|||
|
||||
impl CliModuleLoader {
|
||||
pub fn new(ps: ProcState) -> Rc<Self> {
|
||||
let lib = if ps.flags.unstable {
|
||||
TypeLib::UnstableDenoWindow
|
||||
} else {
|
||||
TypeLib::DenoWindow
|
||||
};
|
||||
|
||||
Rc::new(CliModuleLoader {
|
||||
lib,
|
||||
lib: ps.config.ts_type_lib_window(),
|
||||
root_permissions: Permissions::allow_all(),
|
||||
ps,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_for_worker(ps: ProcState, permissions: Permissions) -> Rc<Self> {
|
||||
let lib = if ps.flags.unstable {
|
||||
TypeLib::UnstableDenoWorker
|
||||
} else {
|
||||
TypeLib::DenoWorker
|
||||
};
|
||||
|
||||
Rc::new(CliModuleLoader {
|
||||
lib,
|
||||
lib: ps.config.ts_type_lib_worker(),
|
||||
root_permissions: permissions,
|
||||
ps,
|
||||
})
|
||||
|
@ -97,13 +85,8 @@ impl ModuleLoader for CliModuleLoader {
|
|||
} else {
|
||||
self.root_permissions.clone()
|
||||
};
|
||||
let lib = self.lib;
|
||||
|
||||
let lib = match self.lib {
|
||||
TypeLib::DenoWindow => crate::emit::TypeLib::DenoWindow,
|
||||
TypeLib::DenoWorker => crate::emit::TypeLib::DenoWorker,
|
||||
TypeLib::UnstableDenoWindow => crate::emit::TypeLib::UnstableDenoWindow,
|
||||
TypeLib::UnstableDenoWorker => crate::emit::TypeLib::UnstableDenoWorker,
|
||||
};
|
||||
drop(state);
|
||||
|
||||
async move {
|
||||
|
|
|
@ -1,19 +1,17 @@
|
|||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::args::resolve_import_map_specifier;
|
||||
use crate::args::ConfigFile;
|
||||
use crate::args::DenoSubcommand;
|
||||
use crate::args::Flags;
|
||||
use crate::args::MaybeImportsResult;
|
||||
use crate::args::RootConfig;
|
||||
use crate::args::TypeCheckMode;
|
||||
use crate::cache;
|
||||
use crate::colors;
|
||||
use crate::compat;
|
||||
use crate::compat::NodeEsmResolver;
|
||||
use crate::deno_dir;
|
||||
use crate::emit;
|
||||
use crate::emit::EmitCache;
|
||||
use crate::file_fetcher::get_root_cert_store;
|
||||
use crate::file_fetcher::CacheSetting;
|
||||
use crate::emit::TsConfigType;
|
||||
use crate::emit::TsTypeLib;
|
||||
use crate::file_fetcher::FileFetcher;
|
||||
use crate::graph_util::graph_lock_or_exit;
|
||||
use crate::graph_util::GraphData;
|
||||
|
@ -23,7 +21,6 @@ use crate::lockfile::as_maybe_locker;
|
|||
use crate::lockfile::Lockfile;
|
||||
use crate::resolver::ImportMapResolver;
|
||||
use crate::resolver::JsxResolver;
|
||||
use crate::version;
|
||||
|
||||
use deno_ast::MediaType;
|
||||
use deno_core::anyhow::anyhow;
|
||||
|
@ -68,17 +65,15 @@ use std::sync::Arc;
|
|||
pub struct ProcState(Arc<Inner>);
|
||||
|
||||
pub struct Inner {
|
||||
/// Flags parsed from `argv` contents.
|
||||
pub flags: Arc<Flags>,
|
||||
pub dir: deno_dir::DenoDir,
|
||||
pub coverage_dir: Option<String>,
|
||||
pub file_fetcher: FileFetcher,
|
||||
pub config: Arc<RootConfig>,
|
||||
graph_data: Arc<RwLock<GraphData>>,
|
||||
pub lockfile: Option<Arc<Mutex<Lockfile>>>,
|
||||
pub maybe_config_file: Option<ConfigFile>,
|
||||
pub maybe_import_map: Option<Arc<ImportMap>>,
|
||||
pub maybe_inspector_server: Option<Arc<InspectorServer>>,
|
||||
pub root_cert_store: Option<RootCertStore>,
|
||||
pub root_cert_store: RootCertStore,
|
||||
pub blob_store: BlobStore,
|
||||
pub broadcast_channel: InMemoryBroadcastChannel,
|
||||
pub shared_array_buffer_store: SharedArrayBufferStore,
|
||||
|
@ -95,30 +90,35 @@ impl Deref for ProcState {
|
|||
}
|
||||
|
||||
impl ProcState {
|
||||
pub async fn build(flags: Arc<Flags>) -> Result<Self, AnyError> {
|
||||
Self::build_with_sender(flags, None).await
|
||||
pub async fn build(flags: Flags) -> Result<Self, AnyError> {
|
||||
Self::from_root_config(Arc::new(RootConfig::from_flags(flags)?)).await
|
||||
}
|
||||
|
||||
pub async fn from_root_config(
|
||||
root_config: Arc<RootConfig>,
|
||||
) -> Result<Self, AnyError> {
|
||||
Self::build_with_sender(root_config, None).await
|
||||
}
|
||||
|
||||
pub async fn build_for_file_watcher(
|
||||
flags: Arc<Flags>,
|
||||
flags: Flags,
|
||||
files_to_watch_sender: tokio::sync::mpsc::UnboundedSender<Vec<PathBuf>>,
|
||||
) -> Result<Self, AnyError> {
|
||||
let ps = Self::build_with_sender(
|
||||
flags.clone(),
|
||||
Some(files_to_watch_sender.clone()),
|
||||
)
|
||||
.await?;
|
||||
// resolve the config each time
|
||||
let root_config = Arc::new(RootConfig::from_flags(flags)?);
|
||||
let ps =
|
||||
Self::build_with_sender(root_config, Some(files_to_watch_sender.clone()))
|
||||
.await?;
|
||||
|
||||
// Add the extra files listed in the watch flag
|
||||
if let Some(watch_paths) = &flags.watch {
|
||||
if let Some(watch_paths) = ps.config.watch_paths() {
|
||||
files_to_watch_sender.send(watch_paths.clone()).unwrap();
|
||||
}
|
||||
|
||||
if let Ok(Some(import_map_path)) = resolve_import_map_specifier(
|
||||
ps.flags.import_map_path.as_deref(),
|
||||
ps.maybe_config_file.as_ref(),
|
||||
)
|
||||
.map(|ms| ms.and_then(|ref s| s.to_file_path().ok()))
|
||||
if let Ok(Some(import_map_path)) = ps
|
||||
.config
|
||||
.resolve_import_map_path()
|
||||
.map(|ms| ms.and_then(|ref s| s.to_file_path().ok()))
|
||||
{
|
||||
files_to_watch_sender.send(vec![import_map_path]).unwrap();
|
||||
}
|
||||
|
@ -127,73 +127,33 @@ impl ProcState {
|
|||
}
|
||||
|
||||
async fn build_with_sender(
|
||||
flags: Arc<Flags>,
|
||||
root_config: Arc<RootConfig>,
|
||||
maybe_sender: Option<tokio::sync::mpsc::UnboundedSender<Vec<PathBuf>>>,
|
||||
) -> Result<Self, AnyError> {
|
||||
let maybe_custom_root = flags
|
||||
.cache_path
|
||||
.clone()
|
||||
.or_else(|| env::var("DENO_DIR").map(String::into).ok());
|
||||
let dir = deno_dir::DenoDir::new(maybe_custom_root)?;
|
||||
let deps_cache_location = dir.root.join("deps");
|
||||
let http_cache = http_cache::HttpCache::new(&deps_cache_location);
|
||||
|
||||
let root_cert_store = get_root_cert_store(
|
||||
None,
|
||||
flags.ca_stores.clone(),
|
||||
flags.ca_file.clone(),
|
||||
)?;
|
||||
|
||||
if let Some(insecure_allowlist) =
|
||||
flags.unsafely_ignore_certificate_errors.as_ref()
|
||||
{
|
||||
let domains = if insecure_allowlist.is_empty() {
|
||||
"for all hostnames".to_string()
|
||||
} else {
|
||||
format!("for: {}", insecure_allowlist.join(", "))
|
||||
};
|
||||
let msg =
|
||||
format!("DANGER: TLS certificate validation is disabled {}", domains);
|
||||
eprintln!("{}", colors::yellow(msg));
|
||||
}
|
||||
|
||||
let cache_usage = if flags.cached_only {
|
||||
CacheSetting::Only
|
||||
} else if !flags.cache_blocklist.is_empty() {
|
||||
CacheSetting::ReloadSome(flags.cache_blocklist.clone())
|
||||
} else if flags.reload {
|
||||
CacheSetting::ReloadAll
|
||||
} else {
|
||||
CacheSetting::Use
|
||||
};
|
||||
|
||||
let blob_store = BlobStore::default();
|
||||
let broadcast_channel = InMemoryBroadcastChannel::default();
|
||||
let shared_array_buffer_store = SharedArrayBufferStore::default();
|
||||
let compiled_wasm_module_store = CompiledWasmModuleStore::default();
|
||||
|
||||
let dir = root_config.resolve_deno_dir()?;
|
||||
let deps_cache_location = dir.root.join("deps");
|
||||
let http_cache = http_cache::HttpCache::new(&deps_cache_location);
|
||||
let root_cert_store = root_config.resolve_root_cert_store()?;
|
||||
let cache_usage = root_config.cache_setting();
|
||||
let file_fetcher = FileFetcher::new(
|
||||
http_cache,
|
||||
cache_usage,
|
||||
!flags.no_remote,
|
||||
!root_config.no_remote(),
|
||||
Some(root_cert_store.clone()),
|
||||
blob_store.clone(),
|
||||
flags.unsafely_ignore_certificate_errors.clone(),
|
||||
root_config
|
||||
.unsafely_ignore_certificate_errors()
|
||||
.map(ToOwned::to_owned),
|
||||
)?;
|
||||
|
||||
let lockfile = if let Some(filename) = &flags.lock {
|
||||
let lockfile = Lockfile::new(filename.clone(), flags.lock_write)?;
|
||||
Some(Arc::new(Mutex::new(lockfile)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let maybe_config_file = crate::args::discover(&flags)?;
|
||||
|
||||
let maybe_import_map_specifier = crate::args::resolve_import_map_specifier(
|
||||
flags.import_map_path.as_deref(),
|
||||
maybe_config_file.as_ref(),
|
||||
)?;
|
||||
let lockfile = root_config
|
||||
.resolve_lock_file()?
|
||||
.map(|f| Arc::new(Mutex::new(f)));
|
||||
let maybe_import_map_specifier = root_config.resolve_import_map_path()?;
|
||||
|
||||
let maybe_import_map =
|
||||
if let Some(import_map_specifier) = maybe_import_map_specifier {
|
||||
|
@ -211,14 +171,12 @@ impl ProcState {
|
|||
None
|
||||
};
|
||||
|
||||
let maybe_inspect_host = flags.inspect.or(flags.inspect_brk);
|
||||
let maybe_inspector_server = maybe_inspect_host.map(|host| {
|
||||
Arc::new(InspectorServer::new(host, version::get_user_agent()))
|
||||
});
|
||||
let maybe_inspector_server =
|
||||
root_config.resolve_inspector_server().map(Arc::new);
|
||||
|
||||
let coverage_dir = flags
|
||||
.coverage_dir
|
||||
.clone()
|
||||
let coverage_dir = root_config
|
||||
.coverage_dir()
|
||||
.map(ToOwned::to_owned)
|
||||
.or_else(|| env::var("DENO_UNSTABLE_COVERAGE_DIR").ok());
|
||||
|
||||
// FIXME(bartlomieju): `NodeEsmResolver` is not aware of JSX resolver
|
||||
|
@ -228,13 +186,12 @@ impl ProcState {
|
|||
);
|
||||
let maybe_import_map_resolver =
|
||||
maybe_import_map.clone().map(ImportMapResolver::new);
|
||||
let maybe_jsx_resolver = maybe_config_file.as_ref().and_then(|cf| {
|
||||
cf.to_maybe_jsx_import_source_module()
|
||||
.map(|im| JsxResolver::new(im, maybe_import_map_resolver.clone()))
|
||||
});
|
||||
let maybe_jsx_resolver = root_config
|
||||
.to_maybe_jsx_import_source_module()
|
||||
.map(|im| JsxResolver::new(im, maybe_import_map_resolver.clone()));
|
||||
let maybe_resolver: Option<
|
||||
Arc<dyn deno_graph::source::Resolver + Send + Sync>,
|
||||
> = if flags.compat {
|
||||
> = if root_config.compat() {
|
||||
Some(Arc::new(node_resolver))
|
||||
} else if let Some(jsx_resolver) = maybe_jsx_resolver {
|
||||
// the JSX resolver offloads to the import map if present, otherwise uses
|
||||
|
@ -255,14 +212,13 @@ impl ProcState {
|
|||
Ok(ProcState(Arc::new(Inner {
|
||||
dir,
|
||||
coverage_dir,
|
||||
flags,
|
||||
config: root_config,
|
||||
file_fetcher,
|
||||
graph_data: Default::default(),
|
||||
lockfile,
|
||||
maybe_config_file,
|
||||
maybe_import_map,
|
||||
maybe_inspector_server,
|
||||
root_cert_store: Some(root_cert_store.clone()),
|
||||
root_cert_store,
|
||||
blob_store,
|
||||
broadcast_channel,
|
||||
shared_array_buffer_store,
|
||||
|
@ -272,25 +228,6 @@ impl ProcState {
|
|||
})))
|
||||
}
|
||||
|
||||
/// Return any imports that should be brought into the scope of the module
|
||||
/// graph.
|
||||
fn get_maybe_imports(&self) -> MaybeImportsResult {
|
||||
let mut imports = Vec::new();
|
||||
if let Some(config_file) = &self.maybe_config_file {
|
||||
if let Some(config_imports) = config_file.to_maybe_imports()? {
|
||||
imports.extend(config_imports);
|
||||
}
|
||||
}
|
||||
if self.flags.compat {
|
||||
imports.extend(compat::get_node_imports());
|
||||
}
|
||||
if imports.is_empty() {
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(imports))
|
||||
}
|
||||
}
|
||||
|
||||
/// This method must be called for a module or a static importer of that
|
||||
/// module before attempting to `load()` it from a `JsRuntime`. It will
|
||||
/// populate `self.graph_data` in memory with the necessary source code, write
|
||||
|
@ -299,7 +236,7 @@ impl ProcState {
|
|||
&self,
|
||||
roots: Vec<ModuleSpecifier>,
|
||||
is_dynamic: bool,
|
||||
lib: emit::TypeLib,
|
||||
lib: TsTypeLib,
|
||||
root_permissions: Permissions,
|
||||
dynamic_permissions: Permissions,
|
||||
reload_on_watch: bool,
|
||||
|
@ -339,7 +276,7 @@ impl ProcState {
|
|||
|
||||
// TODO(bartlomieju): this is very make-shift, is there an existing API
|
||||
// that we could include it like with "maybe_imports"?
|
||||
let roots = if self.flags.compat {
|
||||
let roots = if self.config.compat() {
|
||||
let mut r = vec![(compat::GLOBAL_URL.clone(), ModuleKind::Esm)];
|
||||
r.extend(roots);
|
||||
r
|
||||
|
@ -348,12 +285,12 @@ impl ProcState {
|
|||
};
|
||||
if !reload_on_watch {
|
||||
let graph_data = self.graph_data.read();
|
||||
if self.flags.type_check_mode == TypeCheckMode::None
|
||||
if self.config.type_check_mode() == TypeCheckMode::None
|
||||
|| graph_data.is_type_checked(&roots, &lib)
|
||||
{
|
||||
if let Some(result) = graph_data.check(
|
||||
&roots,
|
||||
self.flags.type_check_mode != TypeCheckMode::None,
|
||||
self.config.type_check_mode() != TypeCheckMode::None,
|
||||
false,
|
||||
) {
|
||||
return result;
|
||||
|
@ -367,7 +304,7 @@ impl ProcState {
|
|||
dynamic_permissions.clone(),
|
||||
);
|
||||
let maybe_locker = as_maybe_locker(self.lockfile.clone());
|
||||
let maybe_imports = self.get_maybe_imports()?;
|
||||
let maybe_imports = self.config.to_maybe_imports()?;
|
||||
|
||||
struct ProcStateLoader<'a> {
|
||||
inner: &'a mut cache::FetchCacher,
|
||||
|
@ -462,57 +399,50 @@ impl ProcState {
|
|||
{
|
||||
let mut graph_data = self.graph_data.write();
|
||||
graph_data.add_graph(&graph, reload_on_watch);
|
||||
let check_js = self
|
||||
.maybe_config_file
|
||||
.as_ref()
|
||||
.map(|cf| cf.get_check_js())
|
||||
.unwrap_or(false);
|
||||
let check_js = self.config.check_js();
|
||||
graph_data
|
||||
.check(
|
||||
&roots,
|
||||
self.flags.type_check_mode != TypeCheckMode::None,
|
||||
self.config.type_check_mode() != TypeCheckMode::None,
|
||||
check_js,
|
||||
)
|
||||
.unwrap()?;
|
||||
}
|
||||
|
||||
let config_type = if self.flags.type_check_mode == TypeCheckMode::None {
|
||||
emit::ConfigType::Emit
|
||||
let config_type = if self.config.type_check_mode() == TypeCheckMode::None {
|
||||
TsConfigType::Emit
|
||||
} else {
|
||||
emit::ConfigType::Check {
|
||||
TsConfigType::Check {
|
||||
tsc_emit: true,
|
||||
lib: lib.clone(),
|
||||
lib,
|
||||
}
|
||||
};
|
||||
|
||||
let (ts_config, maybe_ignored_options) =
|
||||
emit::get_ts_config(config_type, self.maybe_config_file.as_ref(), None)?;
|
||||
let ts_config_result =
|
||||
self.config.resolve_ts_config_for_emit(config_type)?;
|
||||
|
||||
if let Some(ignored_options) = maybe_ignored_options {
|
||||
if let Some(ignored_options) = ts_config_result.maybe_ignored_options {
|
||||
log::warn!("{}", ignored_options);
|
||||
}
|
||||
|
||||
if self.flags.type_check_mode == TypeCheckMode::None {
|
||||
if self.config.type_check_mode() == TypeCheckMode::None {
|
||||
let options = emit::EmitOptions {
|
||||
ts_config,
|
||||
reload: self.flags.reload,
|
||||
ts_config: ts_config_result.ts_config,
|
||||
reload: self.config.reload_flag(),
|
||||
reload_exclusions,
|
||||
};
|
||||
let emit_result = emit::emit(&graph, &self.dir.gen_cache, options)?;
|
||||
log::debug!("{}", emit_result.stats);
|
||||
} else {
|
||||
let maybe_config_specifier = self
|
||||
.maybe_config_file
|
||||
.as_ref()
|
||||
.map(|cf| cf.specifier.clone());
|
||||
let maybe_config_specifier = self.config.maybe_config_file_specifier();
|
||||
let options = emit::CheckOptions {
|
||||
type_check_mode: self.flags.type_check_mode.clone(),
|
||||
debug: self.flags.log_level == Some(log::Level::Debug),
|
||||
type_check_mode: self.config.type_check_mode(),
|
||||
debug: self.config.log_level() == Some(log::Level::Debug),
|
||||
emit_with_diagnostics: false,
|
||||
maybe_config_specifier,
|
||||
ts_config,
|
||||
ts_config: ts_config_result.ts_config,
|
||||
log_checks: true,
|
||||
reload: self.flags.reload,
|
||||
reload: self.config.reload_flag(),
|
||||
reload_exclusions,
|
||||
};
|
||||
let emit_result = emit::check_and_maybe_emit(
|
||||
|
@ -527,9 +457,9 @@ impl ProcState {
|
|||
log::debug!("{}", emit_result.stats);
|
||||
}
|
||||
|
||||
if self.flags.type_check_mode != TypeCheckMode::None {
|
||||
if self.config.type_check_mode() != TypeCheckMode::None {
|
||||
let mut graph_data = self.graph_data.write();
|
||||
graph_data.set_type_checked(&roots, &lib);
|
||||
graph_data.set_type_checked(&roots, lib);
|
||||
}
|
||||
|
||||
// any updates to the lockfile should be updated now
|
||||
|
@ -571,7 +501,9 @@ impl ProcState {
|
|||
// FIXME(bartlomieju): this is a hacky way to provide compatibility with REPL
|
||||
// and `Deno.core.evalContext` API. Ideally we should always have a referrer filled
|
||||
// but sadly that's not the case due to missing APIs in V8.
|
||||
let referrer = if referrer.is_empty() && self.flags.repl {
|
||||
let referrer = if referrer.is_empty()
|
||||
&& matches!(self.config.sub_command(), DenoSubcommand::Repl(_))
|
||||
{
|
||||
deno_core::resolve_url_or_path("./$deno$repl.ts").unwrap()
|
||||
} else {
|
||||
deno_core::resolve_url_or_path(referrer).unwrap()
|
||||
|
|
|
@ -23,7 +23,6 @@ use deno_core::ModuleLoader;
|
|||
use deno_core::ModuleSpecifier;
|
||||
use deno_graph::source::Resolver;
|
||||
use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
|
||||
use deno_runtime::deno_tls::create_default_root_cert_store;
|
||||
use deno_runtime::deno_tls::rustls_pemfile;
|
||||
use deno_runtime::deno_web::BlobStore;
|
||||
use deno_runtime::permissions::Permissions;
|
||||
|
@ -224,7 +223,7 @@ pub async fn run(
|
|||
) -> Result<(), AnyError> {
|
||||
let flags = metadata_to_flags(&metadata);
|
||||
let main_module = &metadata.entrypoint;
|
||||
let ps = ProcState::build(Arc::new(flags)).await?;
|
||||
let ps = ProcState::build(flags).await?;
|
||||
let permissions = Permissions::from_options(&metadata.permissions);
|
||||
let blob_store = BlobStore::default();
|
||||
let broadcast_channel = InMemoryBroadcastChannel::default();
|
||||
|
@ -252,10 +251,7 @@ pub async fn run(
|
|||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
let mut root_cert_store = ps
|
||||
.root_cert_store
|
||||
.clone()
|
||||
.unwrap_or_else(create_default_root_cert_store);
|
||||
let mut root_cert_store = ps.root_cert_store.clone();
|
||||
|
||||
if let Some(cert) = metadata.ca_data {
|
||||
let reader = &mut BufReader::new(Cursor::new(cert));
|
||||
|
|
|
@ -7,7 +7,6 @@ use crate::cache;
|
|||
use crate::colors;
|
||||
use crate::compat;
|
||||
use crate::create_main_worker;
|
||||
use crate::emit;
|
||||
use crate::file_watcher;
|
||||
use crate::file_watcher::ResolutionResult;
|
||||
use crate::fs_util::collect_specifiers;
|
||||
|
@ -40,7 +39,6 @@ use serde::Deserialize;
|
|||
use serde::Serialize;
|
||||
use std::collections::HashSet;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::mpsc::unbounded_channel;
|
||||
use tokio::sync::mpsc::UnboundedSender;
|
||||
|
||||
|
@ -337,8 +335,8 @@ async fn check_specifiers(
|
|||
ps: &ProcState,
|
||||
permissions: Permissions,
|
||||
specifiers: Vec<ModuleSpecifier>,
|
||||
lib: emit::TypeLib,
|
||||
) -> Result<(), AnyError> {
|
||||
let lib = ps.config.ts_type_lib_window();
|
||||
ps.prepare_module_load(
|
||||
specifiers,
|
||||
false,
|
||||
|
@ -365,7 +363,11 @@ async fn bench_specifier(
|
|||
&ps,
|
||||
specifier.clone(),
|
||||
permissions,
|
||||
vec![ops::bench::init(channel.clone(), filter, ps.flags.unstable)],
|
||||
vec![ops::bench::init(
|
||||
channel.clone(),
|
||||
filter,
|
||||
ps.config.unstable(),
|
||||
)],
|
||||
Default::default(),
|
||||
);
|
||||
|
||||
|
@ -416,7 +418,7 @@ async fn bench_specifiers(
|
|||
specifiers: Vec<ModuleSpecifier>,
|
||||
options: BenchSpecifierOptions,
|
||||
) -> Result<(), AnyError> {
|
||||
let log_level = ps.flags.log_level;
|
||||
let log_level = ps.config.log_level();
|
||||
|
||||
let (sender, mut receiver) = unbounded_channel::<BenchEvent>();
|
||||
|
||||
|
@ -518,8 +520,8 @@ pub async fn run_benchmarks(
|
|||
flags: Flags,
|
||||
bench_flags: BenchFlags,
|
||||
) -> Result<(), AnyError> {
|
||||
let ps = ProcState::build(Arc::new(flags)).await?;
|
||||
let permissions = Permissions::from_options(&ps.flags.permissions_options());
|
||||
let ps = ProcState::build(flags).await?;
|
||||
let permissions = Permissions::from_options(&ps.config.permissions_options());
|
||||
let specifiers = collect_specifiers(
|
||||
bench_flags.include.unwrap_or_else(|| vec![".".to_string()]),
|
||||
&bench_flags.ignore.clone(),
|
||||
|
@ -530,15 +532,9 @@ pub async fn run_benchmarks(
|
|||
return Err(generic_error("No bench modules found"));
|
||||
}
|
||||
|
||||
let lib = if ps.flags.unstable {
|
||||
emit::TypeLib::UnstableDenoWindow
|
||||
} else {
|
||||
emit::TypeLib::DenoWindow
|
||||
};
|
||||
check_specifiers(&ps, permissions.clone(), specifiers.clone()).await?;
|
||||
|
||||
check_specifiers(&ps, permissions.clone(), specifiers.clone(), lib).await?;
|
||||
|
||||
let compat = ps.flags.compat;
|
||||
let compat = ps.config.compat();
|
||||
bench_specifiers(
|
||||
ps,
|
||||
permissions,
|
||||
|
@ -558,20 +554,13 @@ pub async fn run_benchmarks_with_watch(
|
|||
flags: Flags,
|
||||
bench_flags: BenchFlags,
|
||||
) -> Result<(), AnyError> {
|
||||
let flags = Arc::new(flags);
|
||||
let ps = ProcState::build(flags.clone()).await?;
|
||||
let permissions = Permissions::from_options(&flags.permissions_options());
|
||||
|
||||
let lib = if flags.unstable {
|
||||
emit::TypeLib::UnstableDenoWindow
|
||||
} else {
|
||||
emit::TypeLib::DenoWindow
|
||||
};
|
||||
let ps = ProcState::build(flags).await?;
|
||||
let permissions = Permissions::from_options(&ps.config.permissions_options());
|
||||
|
||||
let include = bench_flags.include.unwrap_or_else(|| vec![".".to_string()]);
|
||||
let ignore = bench_flags.ignore.clone();
|
||||
let paths_to_watch: Vec<_> = include.iter().map(PathBuf::from).collect();
|
||||
let no_check = ps.flags.type_check_mode == TypeCheckMode::None;
|
||||
let no_check = ps.config.type_check_mode() == TypeCheckMode::None;
|
||||
|
||||
let resolver = |changed: Option<Vec<PathBuf>>| {
|
||||
let mut cache = cache::FetchCacher::new(
|
||||
|
@ -586,23 +575,16 @@ pub async fn run_benchmarks_with_watch(
|
|||
|
||||
let maybe_import_map_resolver =
|
||||
ps.maybe_import_map.clone().map(ImportMapResolver::new);
|
||||
let maybe_jsx_resolver = ps.maybe_config_file.as_ref().and_then(|cf| {
|
||||
cf.to_maybe_jsx_import_source_module()
|
||||
.map(|im| JsxResolver::new(im, maybe_import_map_resolver.clone()))
|
||||
});
|
||||
let maybe_jsx_resolver = ps
|
||||
.config
|
||||
.to_maybe_jsx_import_source_module()
|
||||
.map(|im| JsxResolver::new(im, maybe_import_map_resolver.clone()));
|
||||
let maybe_locker = lockfile::as_maybe_locker(ps.lockfile.clone());
|
||||
let maybe_imports = ps
|
||||
.maybe_config_file
|
||||
.as_ref()
|
||||
.map(|cf| cf.to_maybe_imports());
|
||||
let maybe_imports_result = ps.config.to_maybe_imports();
|
||||
let files_changed = changed.is_some();
|
||||
let include = include.clone();
|
||||
let ignore = ignore.clone();
|
||||
let check_js = ps
|
||||
.maybe_config_file
|
||||
.as_ref()
|
||||
.map(|cf| cf.get_check_js())
|
||||
.unwrap_or(false);
|
||||
let check_js = ps.config.check_js();
|
||||
|
||||
async move {
|
||||
let bench_modules =
|
||||
|
@ -617,11 +599,7 @@ pub async fn run_benchmarks_with_watch(
|
|||
.map(|url| (url.clone(), ModuleKind::Esm))
|
||||
.collect()
|
||||
};
|
||||
let maybe_imports = if let Some(result) = maybe_imports {
|
||||
result?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let maybe_imports = maybe_imports_result?;
|
||||
let maybe_resolver = if maybe_jsx_resolver.is_some() {
|
||||
maybe_jsx_resolver.as_ref().map(|jr| jr.as_resolver())
|
||||
} else {
|
||||
|
@ -733,11 +711,9 @@ pub async fn run_benchmarks_with_watch(
|
|||
};
|
||||
|
||||
let operation = |modules_to_reload: Vec<(ModuleSpecifier, ModuleKind)>| {
|
||||
let flags = flags.clone();
|
||||
let filter = bench_flags.filter.clone();
|
||||
let include = include.clone();
|
||||
let ignore = ignore.clone();
|
||||
let lib = lib.clone();
|
||||
let permissions = permissions.clone();
|
||||
let ps = ps.clone();
|
||||
|
||||
|
@ -749,19 +725,14 @@ pub async fn run_benchmarks_with_watch(
|
|||
.cloned()
|
||||
.collect::<Vec<ModuleSpecifier>>();
|
||||
|
||||
check_specifiers(&ps, permissions.clone(), specifiers.clone(), lib)
|
||||
.await?;
|
||||
check_specifiers(&ps, permissions.clone(), specifiers.clone()).await?;
|
||||
|
||||
bench_specifiers(
|
||||
ps,
|
||||
permissions.clone(),
|
||||
specifiers,
|
||||
BenchSpecifierOptions {
|
||||
compat_mode: flags.compat,
|
||||
filter: filter.clone(),
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
let specifier_options = BenchSpecifierOptions {
|
||||
compat_mode: ps.config.compat(),
|
||||
filter: filter.clone(),
|
||||
};
|
||||
bench_specifiers(ps, permissions.clone(), specifiers, specifier_options)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -772,7 +743,7 @@ pub async fn run_benchmarks_with_watch(
|
|||
operation,
|
||||
file_watcher::PrintConfig {
|
||||
job_name: "Bench".to_string(),
|
||||
clear_screen: !flags.no_clear_screen,
|
||||
clear_screen: !ps.config.no_clear_screen(),
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
|
|
@ -23,7 +23,6 @@ use std::fs::File;
|
|||
use std::io::BufWriter;
|
||||
use std::io::{self, Error, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use text_lines::TextLines;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
@ -597,7 +596,7 @@ pub async fn cover_files(
|
|||
flags: Flags,
|
||||
coverage_flags: CoverageFlags,
|
||||
) -> Result<(), AnyError> {
|
||||
let ps = ProcState::build(Arc::new(flags)).await?;
|
||||
let ps = ProcState::build(flags).await?;
|
||||
|
||||
let script_coverages =
|
||||
collect_coverages(coverage_flags.files, coverage_flags.ignore)?;
|
||||
|
|
|
@ -96,7 +96,7 @@ pub async fn print_docs(
|
|||
flags: Flags,
|
||||
doc_flags: DocFlags,
|
||||
) -> Result<(), AnyError> {
|
||||
let ps = ProcState::build(Arc::new(flags)).await?;
|
||||
let ps = ProcState::build(flags).await?;
|
||||
let source_file = doc_flags
|
||||
.source_file
|
||||
.unwrap_or_else(|| "--builtin".to_string());
|
||||
|
@ -122,7 +122,7 @@ pub async fn print_docs(
|
|||
doc_parser.parse_source(
|
||||
&source_file_specifier,
|
||||
MediaType::Dts,
|
||||
get_types(ps.flags.unstable).into(),
|
||||
get_types(ps.config.unstable()).into(),
|
||||
)
|
||||
} else {
|
||||
let module_specifier = resolve_url_or_path(&source_file)?;
|
||||
|
|
|
@ -7,13 +7,11 @@
|
|||
//! the future it can be easily extended to provide
|
||||
//! the same functions as ops available in JS runtime.
|
||||
|
||||
use crate::args::Flags;
|
||||
use crate::args::FmtConfig;
|
||||
use crate::args::FmtFlags;
|
||||
use crate::args::FmtOptionsConfig;
|
||||
use crate::args::ProseWrap;
|
||||
use crate::args::RootConfig;
|
||||
use crate::colors;
|
||||
use crate::deno_dir::DenoDir;
|
||||
use crate::diff::diff;
|
||||
use crate::file_watcher;
|
||||
use crate::file_watcher::ResolutionResult;
|
||||
|
@ -45,11 +43,11 @@ use super::incremental_cache::IncrementalCache;
|
|||
|
||||
/// Format JavaScript/TypeScript files.
|
||||
pub async fn format(
|
||||
flags: &Flags,
|
||||
config: &RootConfig,
|
||||
fmt_flags: FmtFlags,
|
||||
maybe_fmt_config: Option<FmtConfig>,
|
||||
deno_dir: &DenoDir,
|
||||
) -> Result<(), AnyError> {
|
||||
let maybe_fmt_config = config.to_fmt_config()?;
|
||||
let deno_dir = config.resolve_deno_dir()?;
|
||||
let FmtFlags {
|
||||
files,
|
||||
ignore,
|
||||
|
@ -138,6 +136,7 @@ pub async fn format(
|
|||
}
|
||||
}
|
||||
};
|
||||
let deno_dir = &deno_dir;
|
||||
let operation = |(paths, fmt_options): (Vec<PathBuf>, FmtOptionsConfig)| async move {
|
||||
let incremental_cache = Arc::new(IncrementalCache::new(
|
||||
&deno_dir.fmt_incremental_cache_db_file_path(),
|
||||
|
@ -154,13 +153,13 @@ pub async fn format(
|
|||
Ok(())
|
||||
};
|
||||
|
||||
if flags.watch.is_some() {
|
||||
if config.watch_paths().is_some() {
|
||||
file_watcher::watch_func(
|
||||
resolver,
|
||||
operation,
|
||||
file_watcher::PrintConfig {
|
||||
job_name: "Fmt".to_string(),
|
||||
clear_screen: !flags.no_clear_screen,
|
||||
clear_screen: !config.no_clear_screen(),
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
|
|
@ -6,14 +6,18 @@
|
|||
//! At the moment it is only consumed using CLI but in
|
||||
//! the future it can be easily extended to provide
|
||||
//! the same functions as ops available in JS runtime.
|
||||
use crate::args::Flags;
|
||||
use crate::args::LintConfig;
|
||||
use crate::args::{Flags, LintFlags};
|
||||
use crate::args::LintFlags;
|
||||
use crate::colors;
|
||||
use crate::file_watcher;
|
||||
use crate::file_watcher::ResolutionResult;
|
||||
use crate::fmt_errors;
|
||||
use crate::fs_util::{collect_files, is_supported_ext, specifier_to_file_path};
|
||||
use crate::fs_util::collect_files;
|
||||
use crate::fs_util::is_supported_ext;
|
||||
use crate::fs_util::specifier_to_file_path;
|
||||
use crate::proc_state::ProcState;
|
||||
use crate::tools::fmt::run_parallelized;
|
||||
use crate::{colors, file_watcher};
|
||||
use deno_ast::MediaType;
|
||||
use deno_core::anyhow::anyhow;
|
||||
use deno_core::error::generic_error;
|
||||
|
@ -29,10 +33,13 @@ use log::debug;
|
|||
use log::info;
|
||||
use serde::Serialize;
|
||||
use std::fs;
|
||||
use std::io::{stdin, Read};
|
||||
use std::io::stdin;
|
||||
use std::io::Read;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use super::incremental_cache::IncrementalCache;
|
||||
|
||||
|
@ -52,7 +59,6 @@ fn create_reporter(kind: LintReporterKind) -> Box<dyn LintReporter + Send> {
|
|||
}
|
||||
|
||||
pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> {
|
||||
let flags = Arc::new(flags);
|
||||
let LintFlags {
|
||||
maybe_rules_tags,
|
||||
maybe_rules_include,
|
||||
|
@ -69,12 +75,8 @@ pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> {
|
|||
let mut include_files = args.clone();
|
||||
let mut exclude_files = ignore.clone();
|
||||
|
||||
let ps = ProcState::build(flags.clone()).await?;
|
||||
let maybe_lint_config = if let Some(config_file) = &ps.maybe_config_file {
|
||||
config_file.to_lint_config()?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let ps = ProcState::build(flags).await?;
|
||||
let maybe_lint_config = ps.config.to_lint_config()?;
|
||||
|
||||
if let Some(lint_config) = maybe_lint_config.as_ref() {
|
||||
if include_files.is_empty() {
|
||||
|
@ -200,7 +202,7 @@ pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> {
|
|||
|
||||
Ok(())
|
||||
};
|
||||
if flags.watch.is_some() {
|
||||
if ps.config.watch_paths().is_some() {
|
||||
if args.len() == 1 && args[0].to_string_lossy() == "-" {
|
||||
return Err(generic_error(
|
||||
"Lint watch on standard input is not supported.",
|
||||
|
@ -211,7 +213,7 @@ pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> {
|
|||
operation,
|
||||
file_watcher::PrintConfig {
|
||||
job_name: "Lint".to_string(),
|
||||
clear_screen: !flags.no_clear_screen,
|
||||
clear_screen: !ps.config.no_clear_screen(),
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
|
|
@ -282,7 +282,6 @@ pub fn compile_to_runtime_flags(
|
|||
no_remote: false,
|
||||
no_prompt: flags.no_prompt,
|
||||
reload: false,
|
||||
repl: false,
|
||||
seed: flags.seed,
|
||||
unstable: flags.unstable,
|
||||
v8_flags: flags.v8_flags.clone(),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::args::ConfigFile;
|
||||
use crate::args::Flags;
|
||||
use crate::args::TaskFlags;
|
||||
use crate::colors;
|
||||
|
@ -12,34 +11,6 @@ use deno_core::error::AnyError;
|
|||
use std::collections::BTreeMap;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
fn get_tasks_config(
|
||||
maybe_config_file: Option<&ConfigFile>,
|
||||
) -> Result<BTreeMap<String, String>, AnyError> {
|
||||
if let Some(config_file) = maybe_config_file {
|
||||
let maybe_tasks_config = config_file.to_tasks_config()?;
|
||||
if let Some(tasks_config) = maybe_tasks_config {
|
||||
for key in tasks_config.keys() {
|
||||
if key.is_empty() {
|
||||
bail!("Configuration file task names cannot be empty");
|
||||
} else if !key
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_alphanumeric() || matches!(c, '_' | '-' | ':'))
|
||||
{
|
||||
bail!("Configuration file task names must only contain alpha-numeric characters, colons (:), underscores (_), or dashes (-). Task: {}", key);
|
||||
} else if !key.chars().next().unwrap().is_ascii_alphabetic() {
|
||||
bail!("Configuration file task names must start with an alphabetic character. Task: {}", key);
|
||||
}
|
||||
}
|
||||
Ok(tasks_config)
|
||||
} else {
|
||||
bail!("No tasks found in configuration file")
|
||||
}
|
||||
} else {
|
||||
bail!("No config file found")
|
||||
}
|
||||
}
|
||||
|
||||
fn print_available_tasks(tasks_config: BTreeMap<String, String>) {
|
||||
eprintln!("{}", colors::green("Available tasks:"));
|
||||
|
@ -58,10 +29,9 @@ pub async fn execute_script(
|
|||
"{} deno task is unstable and may drastically change in the future",
|
||||
crate::colors::yellow("Warning"),
|
||||
);
|
||||
let flags = Arc::new(flags);
|
||||
let ps = ProcState::build(flags.clone()).await?;
|
||||
let tasks_config = get_tasks_config(ps.maybe_config_file.as_ref())?;
|
||||
let config_file_url = &ps.maybe_config_file.as_ref().unwrap().specifier;
|
||||
let ps = ProcState::build(flags).await?;
|
||||
let tasks_config = ps.config.resolve_tasks_config()?;
|
||||
let config_file_url = ps.config.maybe_config_file_specifier().unwrap();
|
||||
let config_file_path = if config_file_url.scheme() == "file" {
|
||||
config_file_url.to_file_path().unwrap()
|
||||
} else {
|
||||
|
@ -81,8 +51,9 @@ pub async fn execute_script(
|
|||
let maybe_script = tasks_config.get(&task_name);
|
||||
|
||||
if let Some(script) = maybe_script {
|
||||
let additional_args = flags
|
||||
.argv
|
||||
let additional_args = ps
|
||||
.config
|
||||
.argv()
|
||||
.iter()
|
||||
// surround all the additional arguments in double quotes
|
||||
// and santize any command substition
|
||||
|
@ -108,74 +79,3 @@ pub async fn execute_script(
|
|||
Ok(1)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use deno_ast::ModuleSpecifier;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn tasks_no_tasks() {
|
||||
run_task_error_test(r#"{}"#, "No tasks found in configuration file");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn task_name_invalid_chars() {
|
||||
run_task_error_test(
|
||||
r#"{
|
||||
"tasks": {
|
||||
"build": "deno test",
|
||||
"some%test": "deno bundle mod.ts"
|
||||
}
|
||||
}"#,
|
||||
concat!(
|
||||
"Configuration file task names must only contain alpha-numeric ",
|
||||
"characters, colons (:), underscores (_), or dashes (-). Task: some%test",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn task_name_non_alpha_starting_char() {
|
||||
run_task_error_test(
|
||||
r#"{
|
||||
"tasks": {
|
||||
"build": "deno test",
|
||||
"1test": "deno bundle mod.ts"
|
||||
}
|
||||
}"#,
|
||||
concat!(
|
||||
"Configuration file task names must start with an ",
|
||||
"alphabetic character. Task: 1test",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn task_name_empty() {
|
||||
run_task_error_test(
|
||||
r#"{
|
||||
"tasks": {
|
||||
"build": "deno test",
|
||||
"": "deno bundle mod.ts"
|
||||
}
|
||||
}"#,
|
||||
"Configuration file task names cannot be empty",
|
||||
);
|
||||
}
|
||||
|
||||
fn run_task_error_test(config_text: &str, expected_error: &str) {
|
||||
let config_dir = ModuleSpecifier::parse("file:///deno/").unwrap();
|
||||
let config_specifier = config_dir.join("tsconfig.json").unwrap();
|
||||
let config_file = ConfigFile::new(config_text, &config_specifier).unwrap();
|
||||
assert_eq!(
|
||||
get_tasks_config(Some(&config_file))
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
expected_error,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ use crate::colors;
|
|||
use crate::compat;
|
||||
use crate::create_main_worker;
|
||||
use crate::display;
|
||||
use crate::emit;
|
||||
use crate::file_fetcher::File;
|
||||
use crate::file_watcher;
|
||||
use crate::file_watcher::ResolutionResult;
|
||||
|
@ -1013,8 +1012,8 @@ pub async fn check_specifiers(
|
|||
ps: &ProcState,
|
||||
permissions: Permissions,
|
||||
specifiers: Vec<(ModuleSpecifier, TestMode)>,
|
||||
lib: emit::TypeLib,
|
||||
) -> Result<(), AnyError> {
|
||||
let lib = ps.config.ts_type_lib_window();
|
||||
let inline_files = fetch_inline_files(
|
||||
ps.clone(),
|
||||
specifiers
|
||||
|
@ -1043,7 +1042,7 @@ pub async fn check_specifiers(
|
|||
ps.prepare_module_load(
|
||||
specifiers,
|
||||
false,
|
||||
lib.clone(),
|
||||
lib,
|
||||
Permissions::allow_all(),
|
||||
permissions.clone(),
|
||||
false,
|
||||
|
@ -1082,7 +1081,7 @@ async fn test_specifiers(
|
|||
specifiers_with_mode: Vec<(ModuleSpecifier, TestMode)>,
|
||||
options: TestSpecifierOptions,
|
||||
) -> Result<(), AnyError> {
|
||||
let log_level = ps.flags.log_level;
|
||||
let log_level = ps.config.log_level();
|
||||
let specifiers_with_mode = if let Some(seed) = options.shuffle {
|
||||
let mut rng = SmallRng::seed_from_u64(seed);
|
||||
let mut specifiers_with_mode = specifiers_with_mode.clone();
|
||||
|
@ -1326,8 +1325,8 @@ pub async fn run_tests(
|
|||
flags: Flags,
|
||||
test_flags: TestFlags,
|
||||
) -> Result<(), AnyError> {
|
||||
let ps = ProcState::build(Arc::new(flags)).await?;
|
||||
let permissions = Permissions::from_options(&ps.flags.permissions_options());
|
||||
let ps = ProcState::build(flags).await?;
|
||||
let permissions = Permissions::from_options(&ps.config.permissions_options());
|
||||
let specifiers_with_mode = fetch_specifiers_with_test_mode(
|
||||
&ps,
|
||||
test_flags.include.unwrap_or_else(|| vec![".".to_string()]),
|
||||
|
@ -1340,20 +1339,14 @@ pub async fn run_tests(
|
|||
return Err(generic_error("No test modules found"));
|
||||
}
|
||||
|
||||
let lib = if ps.flags.unstable {
|
||||
emit::TypeLib::UnstableDenoWindow
|
||||
} else {
|
||||
emit::TypeLib::DenoWindow
|
||||
};
|
||||
|
||||
check_specifiers(&ps, permissions.clone(), specifiers_with_mode.clone(), lib)
|
||||
check_specifiers(&ps, permissions.clone(), specifiers_with_mode.clone())
|
||||
.await?;
|
||||
|
||||
if test_flags.no_run {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let compat = ps.flags.compat;
|
||||
let compat = ps.config.compat();
|
||||
test_specifiers(
|
||||
ps,
|
||||
permissions,
|
||||
|
@ -1376,20 +1369,13 @@ pub async fn run_tests_with_watch(
|
|||
flags: Flags,
|
||||
test_flags: TestFlags,
|
||||
) -> Result<(), AnyError> {
|
||||
let flags = Arc::new(flags);
|
||||
let ps = ProcState::build(flags.clone()).await?;
|
||||
let permissions = Permissions::from_options(&flags.permissions_options());
|
||||
|
||||
let lib = if flags.unstable {
|
||||
emit::TypeLib::UnstableDenoWindow
|
||||
} else {
|
||||
emit::TypeLib::DenoWindow
|
||||
};
|
||||
let ps = ProcState::build(flags).await?;
|
||||
let permissions = Permissions::from_options(&ps.config.permissions_options());
|
||||
|
||||
let include = test_flags.include.unwrap_or_else(|| vec![".".to_string()]);
|
||||
let ignore = test_flags.ignore.clone();
|
||||
let paths_to_watch: Vec<_> = include.iter().map(PathBuf::from).collect();
|
||||
let no_check = ps.flags.type_check_mode == TypeCheckMode::None;
|
||||
let no_check = ps.config.type_check_mode() == TypeCheckMode::None;
|
||||
|
||||
let resolver = |changed: Option<Vec<PathBuf>>| {
|
||||
let mut cache = cache::FetchCacher::new(
|
||||
|
@ -1404,23 +1390,16 @@ pub async fn run_tests_with_watch(
|
|||
|
||||
let maybe_import_map_resolver =
|
||||
ps.maybe_import_map.clone().map(ImportMapResolver::new);
|
||||
let maybe_jsx_resolver = ps.maybe_config_file.as_ref().and_then(|cf| {
|
||||
cf.to_maybe_jsx_import_source_module()
|
||||
.map(|im| JsxResolver::new(im, maybe_import_map_resolver.clone()))
|
||||
});
|
||||
let maybe_jsx_resolver = ps
|
||||
.config
|
||||
.to_maybe_jsx_import_source_module()
|
||||
.map(|im| JsxResolver::new(im, maybe_import_map_resolver.clone()));
|
||||
let maybe_locker = lockfile::as_maybe_locker(ps.lockfile.clone());
|
||||
let maybe_imports = ps
|
||||
.maybe_config_file
|
||||
.as_ref()
|
||||
.map(|cf| cf.to_maybe_imports());
|
||||
let maybe_imports_result = ps.config.to_maybe_imports();
|
||||
let files_changed = changed.is_some();
|
||||
let include = include.clone();
|
||||
let ignore = ignore.clone();
|
||||
let check_js = ps
|
||||
.maybe_config_file
|
||||
.as_ref()
|
||||
.map(|cf| cf.get_check_js())
|
||||
.unwrap_or(false);
|
||||
let check_js = ps.config.check_js();
|
||||
|
||||
async move {
|
||||
let test_modules = if test_flags.doc {
|
||||
|
@ -1438,11 +1417,7 @@ pub async fn run_tests_with_watch(
|
|||
.map(|url| (url.clone(), ModuleKind::Esm))
|
||||
.collect()
|
||||
};
|
||||
let maybe_imports = if let Some(result) = maybe_imports {
|
||||
result?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let maybe_imports = maybe_imports_result?;
|
||||
let maybe_resolver = if maybe_jsx_resolver.is_some() {
|
||||
maybe_jsx_resolver.as_ref().map(|jr| jr.as_resolver())
|
||||
} else {
|
||||
|
@ -1553,12 +1528,12 @@ pub async fn run_tests_with_watch(
|
|||
})
|
||||
};
|
||||
|
||||
let root_config = ps.config.clone();
|
||||
let operation = |modules_to_reload: Vec<(ModuleSpecifier, ModuleKind)>| {
|
||||
let flags = flags.clone();
|
||||
let root_config = root_config.clone();
|
||||
let filter = test_flags.filter.clone();
|
||||
let include = include.clone();
|
||||
let ignore = ignore.clone();
|
||||
let lib = lib.clone();
|
||||
let permissions = permissions.clone();
|
||||
let ps = ps.clone();
|
||||
|
||||
|
@ -1577,13 +1552,8 @@ pub async fn run_tests_with_watch(
|
|||
.cloned()
|
||||
.collect::<Vec<(ModuleSpecifier, TestMode)>>();
|
||||
|
||||
check_specifiers(
|
||||
&ps,
|
||||
permissions.clone(),
|
||||
specifiers_with_mode.clone(),
|
||||
lib,
|
||||
)
|
||||
.await?;
|
||||
check_specifiers(&ps, permissions.clone(), specifiers_with_mode.clone())
|
||||
.await?;
|
||||
|
||||
if test_flags.no_run {
|
||||
return Ok(());
|
||||
|
@ -1594,7 +1564,7 @@ pub async fn run_tests_with_watch(
|
|||
permissions.clone(),
|
||||
specifiers_with_mode,
|
||||
TestSpecifierOptions {
|
||||
compat_mode: flags.compat,
|
||||
compat_mode: root_config.compat(),
|
||||
concurrent_jobs: test_flags.concurrent_jobs,
|
||||
fail_fast: test_flags.fail_fast,
|
||||
filter: filter.clone(),
|
||||
|
@ -1613,7 +1583,7 @@ pub async fn run_tests_with_watch(
|
|||
operation,
|
||||
file_watcher::PrintConfig {
|
||||
job_name: "Test".to_string(),
|
||||
clear_screen: !flags.no_clear_screen,
|
||||
clear_screen: !root_config.no_clear_screen(),
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
|
21
cli/tools/vendor/mod.rs
vendored
21
cli/tools/vendor/mod.rs
vendored
|
@ -134,16 +134,17 @@ fn validate_output_dir(
|
|||
|
||||
fn maybe_update_config_file(output_dir: &Path, ps: &ProcState) -> bool {
|
||||
assert!(output_dir.is_absolute());
|
||||
let config_file = match &ps.maybe_config_file {
|
||||
let config_file_specifier = match ps.config.maybe_config_file_specifier() {
|
||||
Some(f) => f,
|
||||
None => return false,
|
||||
};
|
||||
let fmt_config = config_file
|
||||
let fmt_config = ps
|
||||
.config
|
||||
.to_fmt_config()
|
||||
.unwrap_or_default()
|
||||
.unwrap_or_default();
|
||||
let result = update_config_file(
|
||||
&config_file.specifier,
|
||||
&config_file_specifier,
|
||||
&ModuleSpecifier::from_file_path(output_dir.join("import_map.json"))
|
||||
.unwrap(),
|
||||
&fmt_config.options,
|
||||
|
@ -262,17 +263,13 @@ async fn create_graph(
|
|||
Permissions::allow_all(),
|
||||
);
|
||||
let maybe_locker = lockfile::as_maybe_locker(ps.lockfile.clone());
|
||||
let maybe_imports = if let Some(config_file) = &ps.maybe_config_file {
|
||||
config_file.to_maybe_imports()?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let maybe_imports = ps.config.to_maybe_imports()?;
|
||||
let maybe_import_map_resolver =
|
||||
ps.maybe_import_map.clone().map(ImportMapResolver::new);
|
||||
let maybe_jsx_resolver = ps.maybe_config_file.as_ref().and_then(|cf| {
|
||||
cf.to_maybe_jsx_import_source_module()
|
||||
.map(|im| JsxResolver::new(im, maybe_import_map_resolver.clone()))
|
||||
});
|
||||
let maybe_jsx_resolver = ps
|
||||
.config
|
||||
.to_maybe_jsx_import_source_module()
|
||||
.map(|im| JsxResolver::new(im, maybe_import_map_resolver.clone()));
|
||||
let maybe_resolver = if maybe_jsx_resolver.is_some() {
|
||||
maybe_jsx_resolver.as_ref().map(|jr| jr.as_resolver())
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue