summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/args/flags.rs498
-rw-r--r--cli/args/mod.rs19
-rw-r--r--cli/factory.rs19
-rw-r--r--cli/tests/integration/task_tests.rs56
-rw-r--r--cli/tools/task.rs152
5 files changed, 446 insertions, 298 deletions
diff --git a/cli/args/flags.rs b/cli/args/flags.rs
index 5a77c8bb2..9bd3a62d4 100644
--- a/cli/args/flags.rs
+++ b/cli/args/flags.rs
@@ -213,6 +213,14 @@ pub struct RunFlags {
}
impl RunFlags {
+ #[cfg(test)]
+ pub fn new_default(script: String) -> Self {
+ Self {
+ script,
+ watch: None,
+ }
+ }
+
pub fn is_stdin(&self) -> bool {
self.script == "-"
}
@@ -4151,10 +4159,9 @@ mod tests {
assert_eq!(
flags,
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string()
+ )),
unstable: true,
log_level: Some(Level::Error),
..Flags::default()
@@ -4206,10 +4213,9 @@ mod tests {
assert_eq!(
flags,
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string()
+ )),
reload: true,
..Flags::default()
}
@@ -4350,7 +4356,7 @@ mod tests {
hmr: false,
paths: vec![],
no_clear_screen: true,
- })
+ }),
}),
..Flags::default()
}
@@ -4365,10 +4371,9 @@ mod tests {
r.unwrap(),
Flags {
reload: true,
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string()
+ )),
allow_write: Some(vec![]),
..Flags::default()
}
@@ -4381,10 +4386,7 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "_".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default("_".to_string())),
v8_flags: svec!["--help"],
..Flags::default()
}
@@ -4399,10 +4401,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string()
+ )),
v8_flags: svec!["--expose-gc", "--gc-stats=1"],
..Flags::default()
}
@@ -4452,10 +4453,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "gist.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "gist.ts".to_string()
+ )),
argv: svec!["--title", "X"],
allow_net: Some(vec![]),
..Flags::default()
@@ -4469,10 +4469,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "gist.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "gist.ts".to_string()
+ )),
allow_all: true,
allow_net: Some(vec![]),
allow_env: Some(vec![]),
@@ -4493,10 +4492,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "gist.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "gist.ts".to_string()
+ )),
allow_read: Some(vec![]),
..Flags::default()
}
@@ -4509,10 +4507,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- watch: None,
- script: "gist.ts".to_string(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "gist.ts".to_string()
+ )),
deny_read: Some(vec![]),
..Flags::default()
}
@@ -4525,10 +4522,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "gist.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "gist.ts".to_string(),
+ )),
allow_hrtime: true,
..Flags::default()
}
@@ -4541,10 +4537,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- watch: None,
- script: "gist.ts".to_string(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "gist.ts".to_string(),
+ )),
deny_hrtime: true,
..Flags::default()
}
@@ -4568,10 +4563,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
argv: svec!["--", "-D", "--allow-net"],
allow_write: Some(vec![]),
..Flags::default()
@@ -5283,10 +5277,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
config_flag: ConfigFlag::Path("tsconfig.json".to_owned()),
..Flags::default()
}
@@ -5574,10 +5567,9 @@ mod tests {
r.unwrap(),
Flags {
allow_read: Some(vec![PathBuf::from("."), temp_dir]),
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
..Flags::default()
}
);
@@ -5599,10 +5591,9 @@ mod tests {
r.unwrap(),
Flags {
deny_read: Some(vec![PathBuf::from("."), temp_dir]),
- subcommand: DenoSubcommand::Run(RunFlags {
- watch: None,
- script: "script.ts".to_string(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
..Flags::default()
}
);
@@ -5624,10 +5615,9 @@ mod tests {
r.unwrap(),
Flags {
allow_write: Some(vec![PathBuf::from("."), temp_dir]),
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
..Flags::default()
}
);
@@ -5649,10 +5639,9 @@ mod tests {
r.unwrap(),
Flags {
deny_write: Some(vec![PathBuf::from("."), temp_dir]),
- subcommand: DenoSubcommand::Run(RunFlags {
- watch: None,
- script: "script.ts".to_string(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
..Flags::default()
}
);
@@ -5669,10 +5658,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
allow_net: Some(svec!["127.0.0.1"]),
..Flags::default()
}
@@ -5686,10 +5674,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- watch: None,
- script: "script.ts".to_string(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
deny_net: Some(svec!["127.0.0.1"]),
..Flags::default()
}
@@ -5703,10 +5690,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
allow_env: Some(svec!["HOME"]),
..Flags::default()
}
@@ -5720,10 +5706,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- watch: None,
- script: "script.ts".to_string(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
deny_env: Some(svec!["HOME"]),
..Flags::default()
}
@@ -5741,10 +5726,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
allow_env: Some(svec!["HOME", "PATH"]),
..Flags::default()
}
@@ -5758,10 +5742,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- watch: None,
- script: "script.ts".to_string(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
deny_env: Some(svec!["HOME", "PATH"]),
..Flags::default()
}
@@ -5800,10 +5783,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
allow_sys: Some(vec![]),
..Flags::default()
}
@@ -5816,10 +5798,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- watch: None,
- script: "script.ts".to_string(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
deny_sys: Some(vec![]),
..Flags::default()
}
@@ -5833,10 +5814,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
allow_sys: Some(svec!["hostname"]),
..Flags::default()
}
@@ -5850,10 +5830,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- watch: None,
- script: "script.ts".to_string(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
deny_sys: Some(svec!["hostname"]),
..Flags::default()
}
@@ -5871,10 +5850,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
allow_sys: Some(svec!["hostname", "osRelease"]),
..Flags::default()
}
@@ -5892,10 +5870,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- watch: None,
- script: "script.ts".to_string(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
deny_sys: Some(svec!["hostname", "osRelease"]),
..Flags::default()
}
@@ -6199,10 +6176,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
import_map_path: Some("import_map.json".to_owned()),
..Flags::default()
}
@@ -6281,10 +6257,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
env_file: Some(".env".to_owned()),
..Flags::default()
}
@@ -6298,10 +6273,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
env_file: Some(".another_env".to_owned()),
..Flags::default()
}
@@ -6329,10 +6303,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
seed: Some(250_u64),
v8_flags: svec!["--random-seed=250"],
..Flags::default()
@@ -6353,10 +6326,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
seed: Some(250_u64),
v8_flags: svec!["--expose-gc", "--random-seed=250"],
..Flags::default()
@@ -6449,10 +6421,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
log_level: Some(Level::Debug),
..Flags::default()
}
@@ -6465,10 +6436,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
log_level: Some(Level::Error),
..Flags::default()
}
@@ -6499,10 +6469,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
argv: svec!["--allow-read", "--allow-net"],
..Flags::default()
}
@@ -6523,10 +6492,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
location: Some(Url::parse("https://foo/").unwrap()),
allow_read: Some(vec![]),
argv: svec!["--allow-net", "-r", "--help", "--foo", "bar"],
@@ -6538,10 +6506,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
argv: svec!["foo", "bar"],
..Flags::default()
}
@@ -6550,10 +6517,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
argv: svec!["-"],
..Flags::default()
}
@@ -6564,10 +6530,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
argv: svec!["-", "foo", "bar"],
..Flags::default()
}
@@ -6580,10 +6545,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
type_check_mode: TypeCheckMode::None,
..Flags::default()
}
@@ -6597,10 +6561,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
type_check_mode: TypeCheckMode::Local,
..Flags::default()
}
@@ -6642,10 +6605,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
unsafely_ignore_certificate_errors: Some(vec![]),
..Flags::default()
}
@@ -6663,10 +6625,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
unsafely_ignore_certificate_errors: Some(svec![
"deno.land",
"localhost",
@@ -6714,10 +6675,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
no_remote: true,
..Flags::default()
}
@@ -6730,10 +6690,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
no_npm: true,
..Flags::default()
}
@@ -6747,10 +6706,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
node_modules_dir: Some(true),
..Flags::default()
}
@@ -6765,10 +6723,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
node_modules_dir: Some(false),
..Flags::default()
}
@@ -6781,10 +6738,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
vendor: Some(true),
..Flags::default()
}
@@ -6794,10 +6750,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
vendor: Some(false),
..Flags::default()
}
@@ -6810,10 +6765,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
cached_only: true,
..Flags::default()
}
@@ -6831,10 +6785,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
allow_net: Some(svec![
"deno.land",
"0.0.0.0:8000",
@@ -6860,10 +6813,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- watch: None,
- script: "script.ts".to_string(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
deny_net: Some(svec![
"deno.land",
"0.0.0.0:8000",
@@ -6889,10 +6841,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
allow_net: Some(svec![
"deno.land",
"deno.land:80",
@@ -6921,10 +6872,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- watch: None,
- script: "script.ts".to_string(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
deny_net: Some(svec![
"deno.land",
"deno.land:80",
@@ -6954,10 +6904,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
lock_write: true,
lock: Some(PathBuf::from("lock.json")),
..Flags::default()
@@ -6968,10 +6917,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
no_lock: true,
..Flags::default()
}
@@ -6987,10 +6935,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
lock_write: true,
lock: Some(PathBuf::from("./deno.lock")),
..Flags::default()
@@ -7008,10 +6955,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
lock_write: true,
lock: Some(PathBuf::from("lock.json")),
..Flags::default()
@@ -7022,10 +6968,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
lock_write: true,
..Flags::default()
}
@@ -7112,10 +7057,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
ca_data: Some(CaData::File("example.crt".to_owned())),
..Flags::default()
}
@@ -7133,10 +7077,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
enable_testing_features: true,
..Flags::default()
}
@@ -7794,10 +7737,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "foo.js".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "foo.js".to_string(),
+ )),
inspect: Some("127.0.0.1:9229".parse().unwrap()),
..Flags::default()
}
@@ -7810,10 +7752,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "foo.js".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "foo.js".to_string(),
+ )),
inspect_wait: Some("127.0.0.1:9229".parse().unwrap()),
..Flags::default()
}
@@ -7828,10 +7769,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "foo.js".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "foo.js".to_string(),
+ )),
inspect_wait: Some("127.0.0.1:3567".parse().unwrap()),
..Flags::default()
}
@@ -8329,10 +8269,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
type_check_mode: TypeCheckMode::Local,
..Flags::default()
}
@@ -8342,10 +8281,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
type_check_mode: TypeCheckMode::All,
..Flags::default()
}
@@ -8355,10 +8293,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
type_check_mode: TypeCheckMode::None,
..Flags::default()
}
@@ -8380,10 +8317,9 @@ mod tests {
assert_eq!(
r.unwrap(),
Flags {
- subcommand: DenoSubcommand::Run(RunFlags {
- script: "script.ts".to_string(),
- watch: Default::default(),
- }),
+ subcommand: DenoSubcommand::Run(RunFlags::new_default(
+ "script.ts".to_string(),
+ )),
config_flag: ConfigFlag::Disabled,
..Flags::default()
}
diff --git a/cli/args/mod.rs b/cli/args/mod.rs
index dd8de2a6f..3e61b50bd 100644
--- a/cli/args/mod.rs
+++ b/cli/args/mod.rs
@@ -1306,6 +1306,25 @@ impl CliOptions {
&self.flags.strace_ops
}
+ pub fn take_binary_npm_command_name(&self) -> Option<String> {
+ match self.sub_command() {
+ DenoSubcommand::Run(flags) => {
+ const NPM_CMD_NAME_ENV_VAR_NAME: &str = "DENO_INTERNAL_NPM_CMD_NAME";
+ match std::env::var(NPM_CMD_NAME_ENV_VAR_NAME) {
+ Ok(var) => {
+ // remove the env var so that child sub processes won't pick this up
+ std::env::remove_var(NPM_CMD_NAME_ENV_VAR_NAME);
+ Some(var)
+ }
+ Err(_) => NpmPackageReqReference::from_str(&flags.script)
+ .ok()
+ .map(|req_ref| npm_pkg_req_ref_to_binary_command(&req_ref)),
+ }
+ }
+ _ => None,
+ }
+ }
+
pub fn type_check_mode(&self) -> TypeCheckMode {
self.flags.type_check_mode
}
diff --git a/cli/factory.rs b/cli/factory.rs
index 027cc8fe4..78f8f5b86 100644
--- a/cli/factory.rs
+++ b/cli/factory.rs
@@ -1,6 +1,5 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-use crate::args::npm_pkg_req_ref_to_binary_command;
use crate::args::CliOptions;
use crate::args::DenoSubcommand;
use crate::args::Flags;
@@ -60,7 +59,6 @@ use deno_runtime::deno_node::NodeResolver;
use deno_runtime::deno_tls::RootCertStoreProvider;
use deno_runtime::deno_web::BlobStore;
use deno_runtime::inspector_server::InspectorServer;
-use deno_semver::npm::NpmPackageReqReference;
use import_map::ImportMap;
use log::warn;
use std::future::Future;
@@ -692,18 +690,11 @@ impl CliFactory {
is_inspecting: self.options.is_inspecting(),
is_npm_main: self.options.is_npm_main(),
location: self.options.location_flag().clone(),
- maybe_binary_npm_command_name: {
- let mut maybe_binary_command_name = None;
- if let DenoSubcommand::Run(flags) = self.options.sub_command() {
- if let Ok(pkg_ref) = NpmPackageReqReference::from_str(&flags.script) {
- // if the user ran a binary command, we'll need to set process.argv[0]
- // to be the name of the binary command instead of deno
- maybe_binary_command_name =
- Some(npm_pkg_req_ref_to_binary_command(&pkg_ref));
- }
- }
- maybe_binary_command_name
- },
+ // if the user ran a binary command, we'll need to set process.argv[0]
+ // to be the name of the binary command instead of deno
+ maybe_binary_npm_command_name: self
+ .options
+ .take_binary_npm_command_name(),
origin_data_folder_path: Some(self.deno_dir()?.origin_data_folder_path()),
seed: self.options.seed(),
unsafely_ignore_certificate_errors: self
diff --git a/cli/tests/integration/task_tests.rs b/cli/tests/integration/task_tests.rs
index 47be2acdf..0eb77803b 100644
--- a/cli/tests/integration/task_tests.rs
+++ b/cli/tests/integration/task_tests.rs
@@ -3,8 +3,10 @@
// Most of the tests for this are in deno_task_shell.
// These tests are intended to only test integration.
+use deno_core::serde_json::json;
use test_util::env_vars_for_npm_tests;
use test_util::TestContext;
+use test_util::TestContextBuilder;
itest!(task_no_args {
args: "task -q --config task/deno_json/deno.json",
@@ -287,3 +289,57 @@ itest!(task_deno_no_pre_post {
exit_code: 0,
envs: vec![("NO_COLOR".to_string(), "1".to_string())],
});
+
+#[test]
+fn task_byonm() {
+ let context = TestContextBuilder::for_npm().use_temp_cwd().build();
+ let temp_dir = context.temp_dir().path();
+ temp_dir.join("package.json").write_json(&json!({
+ "name": "example",
+ "scripts": {
+ "say": "cowsay 'do make say'",
+ "think": "cowthink think"
+ },
+ "dependencies": {
+ "cowsay": "*"
+ }
+ }));
+ temp_dir.join("deno.json").write_json(&json!({
+ "unstable": ["byonm"],
+ }));
+ context.run_npm("install");
+
+ context
+ .new_command()
+ .args_vec(["task", "say"])
+ .run()
+ .assert_matches_text(
+ r#"Task say cowsay 'do make say'
+ _____________
+< do make say >
+ -------------
+ \ ^__^
+ \ (oo)\_______
+ (__)\ )\/\
+ ||----w |
+ || ||
+"#,
+ );
+
+ context
+ .new_command()
+ .args_vec(["task", "think"])
+ .run()
+ .assert_matches_text(
+ r#"Task think cowthink think
+ _______
+( think )
+ -------
+ o ^__^
+ o (oo)\_______
+ (__)\ )\/\
+ ||----w |
+ || ||
+"#,
+ );
+}
diff --git a/cli/tools/task.rs b/cli/tools/task.rs
index d929dc666..78d09f0c7 100644
--- a/cli/tools/task.rs
+++ b/cli/tools/task.rs
@@ -5,6 +5,8 @@ use crate::args::Flags;
use crate::args::TaskFlags;
use crate::colors;
use crate::factory::CliFactory;
+use crate::npm::CliNpmResolver;
+use crate::npm::InnerCliNpmResolverRef;
use crate::npm::ManagedCliNpmResolver;
use crate::util::fs::canonicalize_path;
use deno_core::anyhow::bail;
@@ -18,6 +20,8 @@ use deno_task_shell::ExecuteResult;
use deno_task_shell::ShellCommand;
use deno_task_shell::ShellCommandContext;
use indexmap::IndexMap;
+use lazy_regex::Lazy;
+use regex::Regex;
use std::collections::HashMap;
use std::path::Path;
use std::path::PathBuf;
@@ -115,11 +119,15 @@ pub async fn execute_script(
output_task(&task_name, &script);
let seq_list = deno_task_shell::parser::parse(&script)
.with_context(|| format!("Error parsing script '{task_name}'."))?;
- let npx_commands = match npm_resolver.as_managed() {
- Some(npm_resolver) => {
+ let npx_commands = match npm_resolver.as_inner() {
+ InnerCliNpmResolverRef::Managed(npm_resolver) => {
resolve_npm_commands(npm_resolver, node_resolver)?
}
- None => Default::default(),
+ InnerCliNpmResolverRef::Byonm(npm_resolver) => {
+ let node_modules_dir =
+ npm_resolver.root_node_modules_path().unwrap();
+ resolve_npm_commands_from_bin_dir(node_modules_dir)?
+ }
};
let env_vars = match npm_resolver.root_node_modules_path() {
Some(dir_path) => collect_env_vars_with_node_modules_dir(dir_path),
@@ -294,6 +302,113 @@ impl ShellCommand for NpmPackageBinCommand {
}
}
+/// Runs a module in the node_modules folder.
+#[derive(Clone)]
+struct NodeModulesFileRunCommand {
+ command_name: String,
+ path: PathBuf,
+}
+
+impl ShellCommand for NodeModulesFileRunCommand {
+ fn execute(
+ &self,
+ mut context: ShellCommandContext,
+ ) -> LocalBoxFuture<'static, ExecuteResult> {
+ let mut args = vec![
+ "run".to_string(),
+ "--ext=js".to_string(),
+ "-A".to_string(),
+ self.path.to_string_lossy().to_string(),
+ ];
+ args.extend(context.args);
+ let executable_command =
+ deno_task_shell::ExecutableCommand::new("deno".to_string());
+ // set this environment variable so that the launched process knows the npm command name
+ context
+ .state
+ .apply_env_var("DENO_INTERNAL_NPM_CMD_NAME", &self.command_name);
+ executable_command.execute(ShellCommandContext { args, ..context })
+ }
+}
+
+fn resolve_npm_commands_from_bin_dir(
+ node_modules_dir: &Path,
+) -> Result<HashMap<String, Rc<dyn ShellCommand>>, AnyError> {
+ let mut result = HashMap::<String, Rc<dyn ShellCommand>>::new();
+ let bin_dir = node_modules_dir.join(".bin");
+ log::debug!("Resolving commands in '{}'.", bin_dir.display());
+ match std::fs::read_dir(&bin_dir) {
+ Ok(entries) => {
+ for entry in entries {
+ let Ok(entry) = entry else {
+ continue;
+ };
+ if let Some(command) = resolve_bin_dir_entry_command(entry) {
+ result.insert(command.command_name.clone(), Rc::new(command));
+ }
+ }
+ }
+ Err(err) => {
+ log::debug!("Failed read_dir for '{}': {:#}", bin_dir.display(), err);
+ }
+ }
+ Ok(result)
+}
+
+fn resolve_bin_dir_entry_command(
+ entry: std::fs::DirEntry,
+) -> Option<NodeModulesFileRunCommand> {
+ if entry.path().extension().is_some() {
+ return None; // only look at files without extensions (even on Windows)
+ }
+ let file_type = entry.file_type().ok()?;
+ let path = if file_type.is_file() {
+ entry.path()
+ } else if file_type.is_symlink() {
+ entry.path().canonicalize().ok()?
+ } else {
+ return None;
+ };
+ let text = std::fs::read_to_string(&path).ok()?;
+ let command_name = entry.file_name().to_string_lossy().to_string();
+ if let Some(path) = resolve_execution_path_from_npx_shim(path, &text) {
+ log::debug!(
+ "Resolved npx command '{}' to '{}'.",
+ command_name,
+ path.display()
+ );
+ Some(NodeModulesFileRunCommand { command_name, path })
+ } else {
+ log::debug!("Failed resolving npx command '{}'.", command_name);
+ None
+ }
+}
+
+/// This is not ideal, but it works ok because it allows us to bypass
+/// the shebang and execute the script directly with Deno.
+fn resolve_execution_path_from_npx_shim(
+ file_path: PathBuf,
+ text: &str,
+) -> Option<PathBuf> {
+ static SCRIPT_PATH_RE: Lazy<Regex> =
+ lazy_regex::lazy_regex!(r#""\$basedir\/([^"]+)" "\$@""#);
+
+ if text.starts_with("#!/usr/bin/env node") {
+ // launch this file itself because it's a JS file
+ Some(file_path)
+ } else {
+ // Search for...
+ // > "$basedir/../next/dist/bin/next" "$@"
+ // ...which is what it will look like on Windows
+ SCRIPT_PATH_RE
+ .captures(text)
+ .and_then(|c| c.get(1))
+ .map(|relative_path| {
+ file_path.parent().unwrap().join(relative_path.as_str())
+ })
+ }
+}
+
fn resolve_npm_commands(
npm_resolver: &ManagedCliNpmResolver,
node_resolver: &NodeResolver,
@@ -351,4 +466,35 @@ mod test {
HashMap::from([("PATH".to_string(), "/example".to_string())])
);
}
+
+ #[test]
+ fn test_resolve_execution_path_from_npx_shim() {
+ // example shim on unix
+ let unix_shim = r#"#!/usr/bin/env node
+"use strict";
+console.log('Hi!');
+"#;
+ let path = PathBuf::from("/node_modules/.bin/example");
+ assert_eq!(
+ resolve_execution_path_from_npx_shim(path.clone(), unix_shim).unwrap(),
+ path
+ );
+ // example shim on windows
+ let windows_shim = r#"#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+ *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -x "$basedir/node" ]; then
+ exec "$basedir/node" "$basedir/../example/bin/example" "$@"
+else
+ exec node "$basedir/../example/bin/example" "$@"
+fi"#;
+ assert_eq!(
+ resolve_execution_path_from_npx_shim(path.clone(), windows_shim).unwrap(),
+ path.parent().unwrap().join("../example/bin/example")
+ );
+ }
}