diff --git a/cli/args/flags.rs b/cli/args/flags.rs index 5a77c8bb274c4d..9bd3a62d44ab99 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 dd8de2a6f1916a..3e61b50bdfd146 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 { + 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 027cc8fe4ec559..78f8f5b866149c 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 47be2acdfbaf6b..0eb77803b02cd9 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 d929dc666223eb..78d09f0c75b66e 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>, AnyError> { + let mut result = HashMap::>::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 { + 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 { + static SCRIPT_PATH_RE: Lazy = + 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") + ); + } }