diff options
Diffstat (limited to 'cli')
-rw-r--r-- | cli/args/flags.rs | 59 | ||||
-rw-r--r-- | cli/args/mod.rs | 14 | ||||
-rw-r--r-- | cli/standalone.rs | 1 | ||||
-rw-r--r-- | cli/tests/inspector_tests.rs | 56 | ||||
-rw-r--r-- | cli/tests/testdata/inspector/inspect_wait.js | 2 | ||||
-rw-r--r-- | cli/worker.rs | 5 |
6 files changed, 132 insertions, 5 deletions
diff --git a/cli/args/flags.rs b/cli/args/flags.rs index c60bc0d99..ac2b7a062 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -312,6 +312,7 @@ pub struct Flags { pub ignore: Vec<PathBuf>, pub import_map_path: Option<String>, pub inspect_brk: Option<SocketAddr>, + pub inspect_wait: Option<SocketAddr>, pub inspect: Option<SocketAddr>, pub location: Option<Url>, pub lock_write: bool, @@ -1482,6 +1483,7 @@ fn run_subcommand<'a>() -> Command<'a> { .arg( watch_arg(true) .conflicts_with("inspect") + .conflicts_with("inspect-wait") .conflicts_with("inspect-brk"), ) .arg(no_clear_screen_arg()) @@ -1622,6 +1624,7 @@ fn test_subcommand<'a>() -> Command<'a> { .takes_value(true) .value_name("DIR") .conflicts_with("inspect") + .conflicts_with("inspect-wait") .conflicts_with("inspect-brk") .help("UNSTABLE: Collect coverage profile data into DIR"), ) @@ -1964,7 +1967,20 @@ fn inspect_args(app: Command) -> Command { .long("inspect-brk") .value_name("HOST:PORT") .help( - "Activate inspector on host:port and break at start of user script", + "Activate inspector on host:port, wait for debugger to connect and break at the start of user script", + ) + .min_values(0) + .max_values(1) + .require_equals(true) + .takes_value(true) + .validator(inspect_arg_validate), + ) + .arg( + Arg::new("inspect-wait") + .long("inspect-wait") + .value_name("HOST:PORT") + .help( + "Activate inspector on host:port and wait for debugger to connect before running user code", ) .min_values(0) .max_values(1) @@ -3040,6 +3056,15 @@ fn inspect_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) { } else { None }; + flags.inspect_wait = if matches.is_present("inspect-wait") { + if let Some(host) = matches.value_of("inspect-wait") { + Some(host.parse().unwrap()) + } else { + Some(default()) + } + } else { + None + }; } fn import_map_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) { @@ -5876,6 +5901,38 @@ mod tests { } #[test] + fn inspect_wait() { + let r = flags_from_vec(svec!["deno", "run", "--inspect-wait", "foo.js"]); + assert_eq!( + r.unwrap(), + Flags { + subcommand: DenoSubcommand::Run(RunFlags { + script: "foo.js".to_string(), + }), + inspect_wait: Some("127.0.0.1:9229".parse().unwrap()), + ..Flags::default() + } + ); + + let r = flags_from_vec(svec![ + "deno", + "run", + "--inspect-wait=127.0.0.1:3567", + "foo.js" + ]); + assert_eq!( + r.unwrap(), + Flags { + subcommand: DenoSubcommand::Run(RunFlags { + script: "foo.js".to_string(), + }), + inspect_wait: Some("127.0.0.1:3567".parse().unwrap()), + ..Flags::default() + } + ); + } + + #[test] fn compile() { let r = flags_from_vec(svec![ "deno", diff --git a/cli/args/mod.rs b/cli/args/mod.rs index ebe71c7fa..de5725a48 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -341,7 +341,11 @@ impl CliOptions { } pub fn resolve_inspector_server(&self) -> Option<InspectorServer> { - let maybe_inspect_host = self.flags.inspect.or(self.flags.inspect_brk); + let maybe_inspect_host = self + .flags + .inspect + .or(self.flags.inspect_brk) + .or(self.flags.inspect_wait); maybe_inspect_host .map(|host| InspectorServer::new(host, version::get_user_agent())) } @@ -466,13 +470,19 @@ impl CliOptions { /// If the --inspect or --inspect-brk flags are used. pub fn is_inspecting(&self) -> bool { - self.flags.inspect.is_some() || self.flags.inspect_brk.is_some() + self.flags.inspect.is_some() + || self.flags.inspect_brk.is_some() + || self.flags.inspect_wait.is_some() } pub fn inspect_brk(&self) -> Option<SocketAddr> { self.flags.inspect_brk } + pub fn inspect_wait(&self) -> Option<SocketAddr> { + self.flags.inspect_wait + } + pub fn log_level(&self) -> Option<log::Level> { self.flags.log_level } diff --git a/cli/standalone.rs b/cli/standalone.rs index 2742f9bbd..d4bf8edb3 100644 --- a/cli/standalone.rs +++ b/cli/standalone.rs @@ -299,6 +299,7 @@ pub async fn run( web_worker_pre_execute_module_cb: web_worker_cb, maybe_inspector_server: None, should_break_on_first_statement: false, + should_wait_for_inspector_session: false, module_loader, npm_resolver: None, // not currently supported get_error_class_fn: Some(&get_error_class_name), diff --git a/cli/tests/inspector_tests.rs b/cli/tests/inspector_tests.rs index 0cf8cc3bb..7044469e4 100644 --- a/cli/tests/inspector_tests.rs +++ b/cli/tests/inspector_tests.rs @@ -13,6 +13,7 @@ use deno_runtime::deno_websocket::tokio_tungstenite::tungstenite; use std::io::BufRead; use std::process::Child; use test_util as util; +use test_util::TempDir; use tokio::net::TcpStream; use util::http_server; @@ -1319,4 +1320,59 @@ mod inspector { assert_eq!(tester.child.wait().unwrap().code(), Some(1)); } + + #[tokio::test] + async fn inspector_wait() { + let script = util::testdata_path().join("inspector/inspect_wait.js"); + let temp_dir = TempDir::new(); + + let child = util::deno_cmd() + .current_dir(temp_dir.path()) + .arg("run") + .arg("--quiet") + .arg("-A") + .arg(inspect_flag_with_unique_port("--inspect-wait")) + .arg(script) + .stdout(std::process::Stdio::piped()) + .stderr(std::process::Stdio::piped()) + .spawn() + .unwrap(); + + tokio::time::sleep(tokio::time::Duration::from_millis(300)).await; + assert!(!temp_dir.path().join("hello.txt").exists()); + + let mut tester = InspectorTester::create(child, ignore_script_parsed).await; + + tester.assert_stderr_for_inspect_brk(); + tester + .send_many(&[ + json!({"id":1,"method":"Runtime.enable"}), + json!({"id":2,"method":"Debugger.enable"}), + ]) + .await; + tester.assert_received_messages( + &[ + r#"{"id":1,"result":{}}"#, + r#"{"id":2,"result":{"debuggerId":"#, + ], + &[ + r#"{"method":"Runtime.executionContextCreated","params":{"context":{"id":1,"#, + ], + ) + .await; + // TODO(bartlomieju): ideally this shouldn't be needed, but currently there's + // no way to express that in inspector code. Most clients always send this + // message anyway. + tester + .send(json!({"id":3,"method":"Runtime.runIfWaitingForDebugger"})) + .await; + tester + .assert_received_messages(&[r#"{"id":3,"result":{}}"#], &[]) + .await; + assert_eq!(&tester.stderr_line(), "Debugger session started."); + tokio::time::sleep(tokio::time::Duration::from_millis(300)).await; + assert_eq!(&tester.stderr_line(), "did run"); + assert!(temp_dir.path().join("hello.txt").exists()); + tester.child.kill().unwrap(); + } } diff --git a/cli/tests/testdata/inspector/inspect_wait.js b/cli/tests/testdata/inspector/inspect_wait.js new file mode 100644 index 000000000..e2b10199c --- /dev/null +++ b/cli/tests/testdata/inspector/inspect_wait.js @@ -0,0 +1,2 @@ +Deno.writeTextFileSync("./hello.txt", "hello world"); +console.error("did run"); diff --git a/cli/worker.rs b/cli/worker.rs index 27cefc1b8..03d0728e6 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -472,7 +472,6 @@ async fn create_main_worker_internal( let module_loader = CliModuleLoader::new(ps.clone()); let maybe_inspector_server = ps.maybe_inspector_server.clone(); - let should_break_on_first_statement = ps.options.inspect_brk().is_some(); let create_web_worker_cb = create_web_worker_callback(ps.clone(), stdio.clone()); @@ -533,7 +532,8 @@ async fn create_main_worker_internal( web_worker_preload_module_cb, web_worker_pre_execute_module_cb, maybe_inspector_server, - should_break_on_first_statement, + should_break_on_first_statement: ps.options.inspect_brk().is_some(), + should_wait_for_inspector_session: ps.options.inspect_wait().is_some(), module_loader, npm_resolver: Some(Rc::new(ps.npm_resolver.clone())), get_error_class_fn: Some(&errors::get_error_class_name), @@ -755,6 +755,7 @@ mod tests { create_web_worker_cb: Arc::new(|_| unreachable!()), maybe_inspector_server: None, should_break_on_first_statement: false, + should_wait_for_inspector_session: false, module_loader: Rc::new(FsModuleLoader), npm_resolver: None, get_error_class_fn: None, |