Skip to content

Commit

Permalink
feat: Add RuntimeOptions::wait_for_inspector_disconnect_callback (den…
Browse files Browse the repository at this point in the history
…oland#387)

This commit adds
"RuntimeOptions::wait_for_inspector_disconnect_callback"
that allows to pass a callback that will be called when the event loop
runs out of work, but there are active, non-blocking inspector sessions - that is
sessions from "Chrome DevTools". This allows to print a message notifying user
that the program has finished, but is waiting for DevTools to disconnect to
exit the process.
  • Loading branch information
bartlomieju authored Dec 19, 2023
1 parent a283806 commit a575dc5
Showing 1 changed file with 27 additions and 1 deletion.
28 changes: 27 additions & 1 deletion core/runtime/jsruntime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ use std::task::Poll;
use std::task::Waker;
use v8::Isolate;

pub type WaitForInspectorDisconnectCallback = Box<dyn Fn()>;
const STATE_DATA_OFFSET: u32 = 0;

pub enum Snapshot {
Expand Down Expand Up @@ -345,6 +346,8 @@ pub struct JsRuntimeState {
pub(crate) op_state: Rc<RefCell<OpState>>,
pub(crate) shared_array_buffer_store: Option<SharedArrayBufferStore>,
pub(crate) compiled_wasm_module_store: Option<CompiledWasmModuleStore>,
wait_for_inspector_disconnect_callback:
Option<WaitForInspectorDisconnectCallback>,
/// The error that was passed to a `reportUnhandledException` call.
/// It will be retrieved by `exception_to_err_result` and used as an error
/// instead of any other exceptions.
Expand Down Expand Up @@ -487,6 +490,15 @@ pub struct RuntimeOptions {
/// is used. The default callback returns value of
/// `RuntimeOptions::module_loader::resolve()` call.
pub import_meta_resolve_callback: Option<ImportMetaResolveCallback>,

/// A callback that is called when the event loop has no more work to do,
/// but there are active, non-blocking inspector session (eg. Chrome
/// DevTools inspector is connected). The embedder can use this callback
/// to eg. print a message notifying user about program finished running.
/// This callback can be called multiple times, eg. after the program finishes
/// more work can be scheduled from the DevTools.
pub wait_for_inspector_disconnect_callback:
Option<WaitForInspectorDisconnectCallback>,
}

impl RuntimeOptions {
Expand Down Expand Up @@ -647,6 +659,8 @@ impl JsRuntime {
source_map_cache: Default::default(),
shared_array_buffer_store: options.shared_array_buffer_store,
compiled_wasm_module_store: options.compiled_wasm_module_store,
wait_for_inspector_disconnect_callback: options
.wait_for_inspector_disconnect_callback,
op_state: op_state.clone(),
// Some fields are initialized later after isolate is created
inspector: None.into(),
Expand Down Expand Up @@ -887,6 +901,18 @@ impl JsRuntime {
self.inner.state.inspector()
}

#[inline]
pub fn wait_for_inspector_disconnect(&mut self) {
if let Some(callback) = self
.inner
.state
.wait_for_inspector_disconnect_callback
.as_ref()
{
callback();
}
}

/// Returns the extensions that this runtime is using (including internal ones).
pub fn extensions(&self) -> &Vec<Extension> {
&self.extensions
Expand Down Expand Up @@ -1683,7 +1709,7 @@ impl JsRuntime {
if !has_blocking_sessions {
let context = self.main_context();
inspector.borrow_mut().context_destroyed(scope, context);
println!("Program finished. Waiting for inspector to disconnect to exit the process...");
self.wait_for_inspector_disconnect();
}

return Poll::Pending;
Expand Down

0 comments on commit a575dc5

Please sign in to comment.