diff --git a/cli/global_state.rs b/cli/global_state.rs index 2a8ebb440f..a4b467edd3 100644 --- a/cli/global_state.rs +++ b/cli/global_state.rs @@ -7,6 +7,7 @@ use crate::graph::GraphBuilder; use crate::graph::TranspileOptions; use crate::http_cache; use crate::import_map::ImportMap; +use crate::inspector::InspectorServer; use crate::lockfile::Lockfile; use crate::media_type::MediaType; use crate::module_graph::ModuleGraphFile; @@ -49,6 +50,7 @@ pub struct GlobalState { pub lockfile: Option<Mutex<Lockfile>>, pub compiler_starts: AtomicUsize, pub maybe_import_map: Option<ImportMap>, + pub maybe_inspector_server: Option<Arc<InspectorServer>>, } impl GlobalState { @@ -92,6 +94,12 @@ impl GlobalState { } }; + let maybe_inspect_host = flags.inspect.or(flags.inspect_brk); + let maybe_inspector_server = match maybe_inspect_host { + Some(host) => Some(Arc::new(InspectorServer::new(host))), + None => None, + }; + let global_state = GlobalState { dir, permissions: Permissions::from_flags(&flags), @@ -100,6 +108,7 @@ impl GlobalState { ts_compiler, lockfile, maybe_import_map, + maybe_inspector_server, compiler_starts: AtomicUsize::new(0), }; Ok(Arc::new(global_state)) diff --git a/cli/inspector.rs b/cli/inspector.rs index 11d9a8ba0f..e4c0085ef8 100644 --- a/cli/inspector.rs +++ b/cli/inspector.rs @@ -35,55 +35,35 @@ use std::ptr; use std::ptr::NonNull; use std::sync::Arc; use std::sync::Mutex; -use std::sync::Once; use std::thread; use uuid::Uuid; use warp::filters::ws; use warp::Filter; -struct InspectorServer { - host: SocketAddr, +pub struct InspectorServer { + pub host: SocketAddr, register_inspector_tx: UnboundedSender<InspectorInfo>, _thread_handle: thread::JoinHandle<()>, } impl InspectorServer { - /// Registers an Inspector instance with the inspector server. If the server - /// is not running yet, it'll be started first. - pub fn register_inspector(info: InspectorInfo) { - let self_ = Self::global(&info.host); - self_.register_inspector_tx.unbounded_send(info).unwrap(); - } - - /// Returns the global InspectorServer instance. If the server is not yet - /// running, this function starts it. - fn global(host: &SocketAddr) -> &'static InspectorServer { - let instance = unsafe { - static mut INSTANCE: Option<InspectorServer> = None; - static INIT: Once = Once::new(); - INIT.call_once(|| { - INSTANCE.replace(Self::new(*host)); - }); - INSTANCE.as_ref().unwrap() - }; - // We only start a single server, so all inspectors must bind to the same - // host:port combination. - assert_eq!(host, &instance.host); - instance - } - - fn new(host: SocketAddr) -> Self { + pub fn new(host: SocketAddr) -> Self { let (register_inspector_tx, register_inspector_rx) = mpsc::unbounded::<InspectorInfo>(); let thread_handle = thread::spawn(move || { crate::tokio_util::run_basic(server(host, register_inspector_rx)) }); + Self { host, register_inspector_tx, _thread_handle: thread_handle, } } + + fn register_inspector(&self, info: InspectorInfo) { + self.register_inspector_tx.unbounded_send(info).unwrap(); + } } /// Inspector information that is sent from the isolate thread to the server @@ -323,7 +303,8 @@ pub struct DenoInspector { flags: RefCell<InspectorFlags>, waker: Arc<InspectorWaker>, _canary_tx: oneshot::Sender<Never>, - pub debugger_url: String, + pub server: Option<Arc<InspectorServer>>, + pub debugger_url: Option<String>, } impl Deref for DenoInspector { @@ -393,7 +374,7 @@ impl DenoInspector { pub fn new( isolate: &mut deno_core::JsRuntime, - host: SocketAddr, + server: Option<Arc<InspectorServer>>, ) -> Box<Self> { let context = isolate.global_context(); let scope = &mut v8::HandleScope::new(&mut **isolate); @@ -402,14 +383,6 @@ impl DenoInspector { mpsc::unbounded::<WebSocketProxy>(); let (canary_tx, canary_rx) = oneshot::channel::<Never>(); - let info = InspectorInfo { - host, - uuid: Uuid::new_v4(), - thread_name: thread::current().name().map(|n| n.to_owned()), - new_websocket_tx, - canary_rx, - }; - // Create DenoInspector instance. let mut self_ = new_box_with(|self_ptr| { let v8_inspector_client = @@ -421,6 +394,22 @@ impl DenoInspector { let flags = InspectorFlags::new(); let waker = InspectorWaker::new(scope.thread_safe_handle()); + let debugger_url = if let Some(server) = server.clone() { + let info = InspectorInfo { + host: server.host, + uuid: Uuid::new_v4(), + thread_name: thread::current().name().map(|n| n.to_owned()), + new_websocket_tx, + canary_rx, + }; + + let debugger_url = info.get_websocket_debugger_url(); + server.register_inspector(info); + Some(debugger_url) + } else { + None + }; + Self { v8_inspector_client, v8_inspector, @@ -428,7 +417,8 @@ impl DenoInspector { flags, waker, _canary_tx: canary_tx, - debugger_url: info.get_websocket_debugger_url(), + server, + debugger_url, } }); @@ -437,9 +427,6 @@ impl DenoInspector { let context_name = v8::inspector::StringView::from(&b"global context"[..]); self_.context_created(context, Self::CONTEXT_GROUP_ID, context_name); - // Register this inspector with the server thread. - InspectorServer::register_inspector(info); - // Poll the session handler so we will get notified whenever there is // new_incoming debugger activity. let _ = self_.poll_sessions(None).unwrap(); diff --git a/cli/worker.rs b/cli/worker.rs index 98418d4faa..821c51a338 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -155,13 +155,17 @@ impl Worker { op_state.put(main_module); op_state.put(global_state.clone()); } - let inspector = { - global_state - .flags - .inspect - .or(global_state.flags.inspect_brk) - .filter(|_| !is_internal) - .map(|inspector_host| DenoInspector::new(&mut isolate, inspector_host)) + + let inspector = if is_internal { + None + } else if let Some(inspector_server) = &global_state.maybe_inspector_server + { + Some(DenoInspector::new( + &mut isolate, + Some(inspector_server.clone()), + )) + } else { + None }; let should_break_on_first_statement = inspector.is_some()