1
0
Fork 0
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:
Casper Beyer 2020-09-25 16:24:51 +08:00 committed by GitHub
parent 478352518d
commit 01147fab80
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 49 deletions

View file

@ -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))

View file

@ -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();

View file

@ -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()