mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 15:24:46 -05:00
refactor(cli/inspector): make server optional (#7656)
This makes inspector registration with the server with optional and explicit to allow for inspectors to exist without spinning up the server. As a side effect of the server being explicitly passed around it also makes it possible to bind multiple servers.
This commit is contained in:
parent
478352518d
commit
01147fab80
3 changed files with 49 additions and 49 deletions
|
@ -7,6 +7,7 @@ use crate::graph::GraphBuilder;
|
||||||
use crate::graph::TranspileOptions;
|
use crate::graph::TranspileOptions;
|
||||||
use crate::http_cache;
|
use crate::http_cache;
|
||||||
use crate::import_map::ImportMap;
|
use crate::import_map::ImportMap;
|
||||||
|
use crate::inspector::InspectorServer;
|
||||||
use crate::lockfile::Lockfile;
|
use crate::lockfile::Lockfile;
|
||||||
use crate::media_type::MediaType;
|
use crate::media_type::MediaType;
|
||||||
use crate::module_graph::ModuleGraphFile;
|
use crate::module_graph::ModuleGraphFile;
|
||||||
|
@ -49,6 +50,7 @@ pub struct GlobalState {
|
||||||
pub lockfile: Option<Mutex<Lockfile>>,
|
pub lockfile: Option<Mutex<Lockfile>>,
|
||||||
pub compiler_starts: AtomicUsize,
|
pub compiler_starts: AtomicUsize,
|
||||||
pub maybe_import_map: Option<ImportMap>,
|
pub maybe_import_map: Option<ImportMap>,
|
||||||
|
pub maybe_inspector_server: Option<Arc<InspectorServer>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlobalState {
|
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 {
|
let global_state = GlobalState {
|
||||||
dir,
|
dir,
|
||||||
permissions: Permissions::from_flags(&flags),
|
permissions: Permissions::from_flags(&flags),
|
||||||
|
@ -100,6 +108,7 @@ impl GlobalState {
|
||||||
ts_compiler,
|
ts_compiler,
|
||||||
lockfile,
|
lockfile,
|
||||||
maybe_import_map,
|
maybe_import_map,
|
||||||
|
maybe_inspector_server,
|
||||||
compiler_starts: AtomicUsize::new(0),
|
compiler_starts: AtomicUsize::new(0),
|
||||||
};
|
};
|
||||||
Ok(Arc::new(global_state))
|
Ok(Arc::new(global_state))
|
||||||
|
|
|
@ -35,55 +35,35 @@ use std::ptr;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::sync::Once;
|
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use warp::filters::ws;
|
use warp::filters::ws;
|
||||||
use warp::Filter;
|
use warp::Filter;
|
||||||
|
|
||||||
struct InspectorServer {
|
pub struct InspectorServer {
|
||||||
host: SocketAddr,
|
pub host: SocketAddr,
|
||||||
register_inspector_tx: UnboundedSender<InspectorInfo>,
|
register_inspector_tx: UnboundedSender<InspectorInfo>,
|
||||||
_thread_handle: thread::JoinHandle<()>,
|
_thread_handle: thread::JoinHandle<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InspectorServer {
|
impl InspectorServer {
|
||||||
/// Registers an Inspector instance with the inspector server. If the server
|
pub fn new(host: SocketAddr) -> Self {
|
||||||
/// 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 {
|
|
||||||
let (register_inspector_tx, register_inspector_rx) =
|
let (register_inspector_tx, register_inspector_rx) =
|
||||||
mpsc::unbounded::<InspectorInfo>();
|
mpsc::unbounded::<InspectorInfo>();
|
||||||
let thread_handle = thread::spawn(move || {
|
let thread_handle = thread::spawn(move || {
|
||||||
crate::tokio_util::run_basic(server(host, register_inspector_rx))
|
crate::tokio_util::run_basic(server(host, register_inspector_rx))
|
||||||
});
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
host,
|
host,
|
||||||
register_inspector_tx,
|
register_inspector_tx,
|
||||||
_thread_handle: thread_handle,
|
_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
|
/// Inspector information that is sent from the isolate thread to the server
|
||||||
|
@ -323,7 +303,8 @@ pub struct DenoInspector {
|
||||||
flags: RefCell<InspectorFlags>,
|
flags: RefCell<InspectorFlags>,
|
||||||
waker: Arc<InspectorWaker>,
|
waker: Arc<InspectorWaker>,
|
||||||
_canary_tx: oneshot::Sender<Never>,
|
_canary_tx: oneshot::Sender<Never>,
|
||||||
pub debugger_url: String,
|
pub server: Option<Arc<InspectorServer>>,
|
||||||
|
pub debugger_url: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for DenoInspector {
|
impl Deref for DenoInspector {
|
||||||
|
@ -393,7 +374,7 @@ impl DenoInspector {
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
isolate: &mut deno_core::JsRuntime,
|
isolate: &mut deno_core::JsRuntime,
|
||||||
host: SocketAddr,
|
server: Option<Arc<InspectorServer>>,
|
||||||
) -> Box<Self> {
|
) -> Box<Self> {
|
||||||
let context = isolate.global_context();
|
let context = isolate.global_context();
|
||||||
let scope = &mut v8::HandleScope::new(&mut **isolate);
|
let scope = &mut v8::HandleScope::new(&mut **isolate);
|
||||||
|
@ -402,14 +383,6 @@ impl DenoInspector {
|
||||||
mpsc::unbounded::<WebSocketProxy>();
|
mpsc::unbounded::<WebSocketProxy>();
|
||||||
let (canary_tx, canary_rx) = oneshot::channel::<Never>();
|
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.
|
// Create DenoInspector instance.
|
||||||
let mut self_ = new_box_with(|self_ptr| {
|
let mut self_ = new_box_with(|self_ptr| {
|
||||||
let v8_inspector_client =
|
let v8_inspector_client =
|
||||||
|
@ -421,6 +394,22 @@ impl DenoInspector {
|
||||||
let flags = InspectorFlags::new();
|
let flags = InspectorFlags::new();
|
||||||
let waker = InspectorWaker::new(scope.thread_safe_handle());
|
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 {
|
Self {
|
||||||
v8_inspector_client,
|
v8_inspector_client,
|
||||||
v8_inspector,
|
v8_inspector,
|
||||||
|
@ -428,7 +417,8 @@ impl DenoInspector {
|
||||||
flags,
|
flags,
|
||||||
waker,
|
waker,
|
||||||
_canary_tx: canary_tx,
|
_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"[..]);
|
let context_name = v8::inspector::StringView::from(&b"global context"[..]);
|
||||||
self_.context_created(context, Self::CONTEXT_GROUP_ID, context_name);
|
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
|
// Poll the session handler so we will get notified whenever there is
|
||||||
// new_incoming debugger activity.
|
// new_incoming debugger activity.
|
||||||
let _ = self_.poll_sessions(None).unwrap();
|
let _ = self_.poll_sessions(None).unwrap();
|
||||||
|
|
|
@ -155,13 +155,17 @@ impl Worker {
|
||||||
op_state.put(main_module);
|
op_state.put(main_module);
|
||||||
op_state.put(global_state.clone());
|
op_state.put(global_state.clone());
|
||||||
}
|
}
|
||||||
let inspector = {
|
|
||||||
global_state
|
let inspector = if is_internal {
|
||||||
.flags
|
None
|
||||||
.inspect
|
} else if let Some(inspector_server) = &global_state.maybe_inspector_server
|
||||||
.or(global_state.flags.inspect_brk)
|
{
|
||||||
.filter(|_| !is_internal)
|
Some(DenoInspector::new(
|
||||||
.map(|inspector_host| DenoInspector::new(&mut isolate, inspector_host))
|
&mut isolate,
|
||||||
|
Some(inspector_server.clone()),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let should_break_on_first_statement = inspector.is_some()
|
let should_break_on_first_statement = inspector.is_some()
|
||||||
|
|
Loading…
Reference in a new issue