summaryrefslogtreecommitdiff
path: root/core/runtime.rs
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2021-05-26 21:07:12 +0200
committerGitHub <noreply@github.com>2021-05-26 21:07:12 +0200
commite5beb800c94099852964d482a32a13f5c29ec147 (patch)
tree1ad89cc15efa84efe690e05b18d5827e1983dbca /core/runtime.rs
parente9edd7e14d9d78f03c5f2e67fcc44e4dbaab8f2c (diff)
refactor: move JsRuntimeInspector to deno_core (#10763)
This commit moves implementation of "JsRuntimeInspector" to "deno_core" crate. To achieve that following changes were made: * "Worker" and "WebWorker" no longer own instance of "JsRuntimeInspector", instead it is now owned by "deno_core::JsRuntime". * Consequently polling of inspector is no longer done in "Worker"/"WebWorker", instead it's done in "deno_core::JsRuntime::poll_event_loop". * "deno_core::JsRuntime::poll_event_loop" and "deno_core::JsRuntime::run_event_loop", now accept "wait_for_inspector" boolean that tells if event loop should still be "pending" if there are active inspector sessions - this change fixes the problem that inspector disconnects from the frontend and process exits once the code has stopped executing.
Diffstat (limited to 'core/runtime.rs')
-rw-r--r--core/runtime.rs59
1 files changed, 51 insertions, 8 deletions
diff --git a/core/runtime.rs b/core/runtime.rs
index 0dbca0ae3..428add8e3 100644
--- a/core/runtime.rs
+++ b/core/runtime.rs
@@ -8,6 +8,7 @@ use crate::error::generic_error;
use crate::error::AnyError;
use crate::error::ErrWithV8Handle;
use crate::error::JsError;
+use crate::inspector::JsRuntimeInspector;
use crate::module_specifier::ModuleSpecifier;
use crate::modules::ModuleId;
use crate::modules::ModuleLoadId;
@@ -23,6 +24,7 @@ use crate::OpState;
use crate::PromiseId;
use futures::channel::mpsc;
use futures::future::poll_fn;
+use futures::future::FutureExt;
use futures::stream::FuturesUnordered;
use futures::stream::StreamExt;
use futures::task::AtomicWaker;
@@ -75,6 +77,7 @@ pub struct JsRuntime {
// This is an Option<OwnedIsolate> instead of just OwnedIsolate to workaround
// an safety issue with SnapshotCreator. See JsRuntime::drop.
v8_isolate: Option<v8::OwnedIsolate>,
+ inspector: Option<Box<JsRuntimeInspector>>,
snapshot_creator: Option<v8::SnapshotCreator>,
has_snapshotted: bool,
allocations: IsolateAllocations,
@@ -113,6 +116,10 @@ pub(crate) struct JsRuntimeState {
impl Drop for JsRuntime {
fn drop(&mut self) {
+ // The Isolate object must outlive the Inspector object, but this is
+ // currently not enforced by the type system.
+ self.inspector.take();
+
if let Some(creator) = self.snapshot_creator.take() {
// TODO(ry): in rusty_v8, `SnapShotCreator::get_owned_isolate()` returns
// a `struct OwnedIsolate` which is not actually owned, hence the need
@@ -198,6 +205,9 @@ pub struct RuntimeOptions {
/// V8 platform instance to use. Used when Deno initializes V8
/// (which it only does once), otherwise it's silenty dropped.
pub v8_platform: Option<v8::UniquePtr<v8::Platform>>,
+
+ /// Create a V8 inspector and attach to the runtime.
+ pub attach_inspector: bool,
}
impl JsRuntime {
@@ -258,6 +268,14 @@ impl JsRuntime {
(isolate, None)
};
+ let maybe_inspector = if options.attach_inspector {
+ let inspector =
+ JsRuntimeInspector::new(&mut isolate, global_context.clone());
+ Some(inspector)
+ } else {
+ None
+ };
+
let loader = options
.module_loader
.unwrap_or_else(|| Rc::new(NoopModuleLoader));
@@ -298,6 +316,7 @@ impl JsRuntime {
let mut js_runtime = Self {
v8_isolate: Some(isolate),
+ inspector: maybe_inspector,
snapshot_creator: maybe_snapshot_creator,
has_snapshotted: false,
allocations: IsolateAllocations::default(),
@@ -328,6 +347,10 @@ impl JsRuntime {
self.v8_isolate.as_mut().unwrap()
}
+ pub fn inspector(&mut self) -> Option<&mut Box<JsRuntimeInspector>> {
+ self.inspector.as_mut()
+ }
+
pub fn handle_scope(&mut self) -> v8::HandleScope {
let context = self.global_context();
v8::HandleScope::with_context(self.v8_isolate(), context)
@@ -568,15 +591,26 @@ impl JsRuntime {
/// This future resolves when:
/// - there are no more pending dynamic imports
/// - there are no more pending ops
- pub async fn run_event_loop(&mut self) -> Result<(), AnyError> {
- poll_fn(|cx| self.poll_event_loop(cx)).await
+ /// - there are no more active inspector sessions (only if `wait_for_inspector` is set to true)
+ pub async fn run_event_loop(
+ &mut self,
+ wait_for_inspector: bool,
+ ) -> Result<(), AnyError> {
+ poll_fn(|cx| self.poll_event_loop(cx, wait_for_inspector)).await
}
/// Runs a single tick of event loop
+ ///
+ /// If `wait_for_inspector` is set to true event loop
+ /// will return `Poll::Pending` if there are active inspector sessions.
pub fn poll_event_loop(
&mut self,
cx: &mut Context,
+ wait_for_inspector: bool,
) -> Poll<Result<(), AnyError>> {
+ // We always poll the inspector if it exists.
+ let _ = self.inspector().map(|i| i.poll_unpin(cx));
+
let state_rc = Self::state(self.v8_isolate());
let module_map_rc = Self::module_map(self.v8_isolate());
{
@@ -617,12 +651,21 @@ impl JsRuntime {
let has_pending_dyn_module_evaluation =
!state.pending_dyn_mod_evaluate.is_empty();
let has_pending_module_evaluation = state.pending_mod_evaluate.is_some();
+ let inspector_has_active_sessions = self
+ .inspector
+ .as_ref()
+ .map(|i| i.has_active_sessions())
+ .unwrap_or(false);
if !has_pending_ops
&& !has_pending_dyn_imports
&& !has_pending_dyn_module_evaluation
&& !has_pending_module_evaluation
{
+ if wait_for_inspector && inspector_has_active_sessions {
+ return Poll::Pending;
+ }
+
return Poll::Ready(Ok(()));
}
@@ -1562,7 +1605,7 @@ pub mod tests {
"#,
)
.unwrap();
- if let Poll::Ready(Err(_)) = runtime.poll_event_loop(&mut cx) {
+ if let Poll::Ready(Err(_)) = runtime.poll_event_loop(&mut cx, false) {
unreachable!();
}
});
@@ -1588,7 +1631,7 @@ pub mod tests {
include_str!("encode_decode_test.js"),
)
.unwrap();
- if let Poll::Ready(Err(_)) = runtime.poll_event_loop(&mut cx) {
+ if let Poll::Ready(Err(_)) = runtime.poll_event_loop(&mut cx, false) {
unreachable!();
}
});
@@ -1604,7 +1647,7 @@ pub mod tests {
include_str!("serialize_deserialize_test.js"),
)
.unwrap();
- if let Poll::Ready(Err(_)) = runtime.poll_event_loop(&mut cx) {
+ if let Poll::Ready(Err(_)) = runtime.poll_event_loop(&mut cx, false) {
unreachable!();
}
});
@@ -1637,7 +1680,7 @@ pub mod tests {
include_str!("error_builder_test.js"),
)
.unwrap();
- if let Poll::Ready(Err(_)) = runtime.poll_event_loop(&mut cx) {
+ if let Poll::Ready(Err(_)) = runtime.poll_event_loop(&mut cx, false) {
unreachable!();
}
});
@@ -1817,7 +1860,7 @@ pub mod tests {
.unwrap();
runtime.mod_evaluate(module_id);
- futures::executor::block_on(runtime.run_event_loop()).unwrap();
+ futures::executor::block_on(runtime.run_event_loop(false)).unwrap();
let _snapshot = runtime.snapshot();
}
@@ -1896,7 +1939,7 @@ main();
at async error_async_stack.js:4:5
at async error_async_stack.js:10:5"#;
- match runtime.poll_event_loop(cx) {
+ match runtime.poll_event_loop(cx, false) {
Poll::Ready(Err(e)) => {
assert_eq!(e.to_string(), expected_error);
}