Skip to content

Conversation

@bartlomieju
Copy link
Member

This reverts commit a45a827.

@coderabbitai
Copy link

coderabbitai bot commented Dec 1, 2025

Walkthrough

The PR replaces the in-memory InspectorSessionProxy flow with a remote IO session model. It introduces NewSessionTxMsg and RemoteInspectorSessionSend, and adds a public InspectorIoDelegate (new_session_tx, deregister_rx). JsRuntimeInspector, SessionContainer, InspectorSession, and related lifecycle/polling logic are reworked to manage Unbounded NewSessionTxMsg channels, IO session futures, and remote session pumping. core/lib.rs now exports InspectorIoDelegate and RemoteInspectorSessionSend; InspectorSessionProxy exports are removed. dcore's InspectorServer/InspectorInfo now use InspectorIoDelegate for session initiation and deregistration.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.71% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: reverting a previous commit that reverted internal inspector changes, effectively re-landing those changes.
Description check ✅ Passed The description directly relates to the changeset by identifying the specific commit being reverted, providing clear context for the revert.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 78c50be and 2be3a31.

📒 Files selected for processing (1)
  • core/inspector.rs (24 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: build-windows / windows lint
  • GitHub Check: build-linux / linux lint-deps
  • GitHub Check: build-linux / linux test-ops
  • GitHub Check: build-linux / linux coverage
  • GitHub Check: build-linux / linux test-publish
  • GitHub Check: build-linux / linux test
  • GitHub Check: build-windows / windows test
  • GitHub Check: build-linux-arm / linux-arm test
  • GitHub Check: build-macos / macos test
  • GitHub Check: build-linux / linux test-miri
  • GitHub Check: build-linux-arm / linux-arm test-miri
🔇 Additional comments (3)
core/inspector.rs (3)

62-87: LGTM on InspectorIoDelegate structure.

The design is reasonable for cross-thread session delegation. The TODO at line 78-79 acknowledges the poll_deregister_rx pattern could be improved.


420-424: Arbitrary session selection may be intentional, but verify behavior with multiple sessions.

Using .values().next() picks an arbitrary session from the HashMap. If multiple sessions exist, this could invoke break_on_next_statement on an unintended session. Confirm this is acceptable for the use case.


706-743: LGTM on InspectorSession refactor.

The addition of the id field and the updated constructor are clean. The dispatch_message correctly guards the is_dispatching_message state.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
core/inspector.rs (2)

43-48: TODO comment indicates incomplete work.

The NewSessionTxMsg type alias has a TODO to remove it. This suggests the type is meant to be temporary or refactored further. Consider addressing this before merging or creating a tracking issue.

Would you like me to open an issue to track this cleanup?


185-195: Silent failure in try_poll_sessions.

When try_borrow_mut() fails, the function silently returns without any indication. This could mask issues where sessions aren't being polled when expected. Consider adding a debug log or metric for visibility.

   pub fn try_poll_sessions(&self) {
     let Ok(mut sessions) = self.sessions.try_borrow_mut() else {
+      #[cfg(debug_assertions)]
+      eprintln!("try_poll_sessions: sessions already borrowed");
       return;
     };
     self.poll_sessions_inner(&mut sessions, None);
   }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6f869f4 and 593dd22.

📒 Files selected for processing (3)
  • core/inspector.rs (22 hunks)
  • core/lib.rs (1 hunks)
  • dcore/src/inspector_server.rs (11 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
core/lib.rs (2)
core/runtime/tests/misc.rs (1)
  • inspector (433-441)
core/runtime/jsruntime.rs (2)
  • inspector (1306-1308)
  • inspector (2472-2474)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: build-macos / macos test
  • GitHub Check: build-windows / windows lint
  • GitHub Check: build-linux-arm / linux-arm test
  • GitHub Check: build-macos / macos lint
  • GitHub Check: build-windows / windows test
  • GitHub Check: build-linux-arm / linux-arm test-miri
  • GitHub Check: build-linux / linux test-miri
  • GitHub Check: build-linux-arm / linux-arm lint
  • GitHub Check: build-linux / linux test-ops
  • GitHub Check: build-linux / linux test
  • GitHub Check: build-linux / linux lint-deps
  • GitHub Check: build-linux / linux coverage
🔇 Additional comments (11)
core/inspector.rs (5)

62-87: New InspectorIoDelegate public API looks reasonable.

The struct provides a clean interface for remote session management with new_remote_session and poll_deregister_rx. However, the TODO at line 78-79 notes that poll_deregister_rx is an antipattern and should be handled in Drop. This is a valid concern for resource cleanup.

Consider addressing the TODO about implementing proper cleanup in Drop to avoid the polling antipattern.


309-320: Initial pump and waker setup after inspector creation.

This block sets up the initial waker state and performs an initial poll. The pattern looks correct - it ensures the waker is properly registered before returning the inspector. The raw pointer manipulation for state_ptr is safe here since state is owned by the Rc which lives as long as the inspector.


419-428: TODO comment questions session selection logic.

The comment at line 419 asks "why the first random session?" - this suggests uncertainty about the correctness of selecting an arbitrary session for break_on_next_statement. If multiple local sessions exist, breaking on only one might be unexpected behavior.

Is it intentional to only break on the first session when multiple local sessions exist? This could lead to confusing debugger behavior.


590-616: pump_messages_for_remote_sessions polling loop structure.

The loop correctly handles both new session registration and pumping existing sessions. However, the TODO at line 604-606 raises a valid question about whether to fully drain the new session queue before polling existing sessions. The current behavior (immediately continuing on new session) seems reasonable for responsiveness.


653-658: Interrupt handler uses raw pointer to inspector state.

The handle_interrupt function casts a raw pointer to JsRuntimeInspectorState. This is safe as documented because the waker's lifetime is tied to JsRuntimeInspector, but it requires careful maintenance. The safety comment is appreciated.

dcore/src/inspector_server.rs (5)

93-97: Inspector registration now uses IO delegate pattern.

The change from direct session sender/receiver handling to create_io_delegate() simplifies the registration flow. The Arc<InspectorIoDelegate> is properly passed to InspectorInfo.


179-192: WebSocket session creation using new remote session API.

The session creation flow is clean - a callback closure captures outbound_tx and sends inspector messages to the websocket. The eprintln! debug message at line 182 is helpful for debugging.

The TODO at line 191 raises a valid concern about whether the inspector is properly deregistered from JsRuntime when the session ends. This ties into the session cleanup issue noted in inspector.rs.

Verify that session cleanup propagates correctly when the WebSocket disconnects. The TODO suggests this may not be fully implemented.


247-254: Deregistration polling retains inspectors until deregistered.

The poll_deregister_rx approach works but is flagged as an antipattern in the source file. The logic correctly removes inspectors from the map when their deregister signal fires.


274-291: Refactored async loop uses boxed futures.

The change from pin!() to boxed_local() for shutdown_rx_fut and accept_fut is a reasonable approach. Both patterns work, but boxed futures have a small allocation overhead. Since this is a server accept loop, the overhead is negligible.


434-458: InspectorInfo struct updated with Arc.

The struct now holds io_delegate: Arc<InspectorIoDelegate> instead of separate sender/receiver channels. This is a cleaner abstraction that encapsulates the session creation logic.

core/lib.rs (1)

89-96: Public API additions for inspector IO delegate.

The new exports InspectorIoDelegate and RemoteInspectorSessionSend are added to expose refactored inspector session management. Verify that no external consumers depend on InspectorSessionProxy before merging, as removing this export would constitute a breaking change to the public API.

Comment on lines +799 to 808
async fn pump_inspector_session_messages(
session: Rc<InspectorSession>,
mut rx: UnboundedReceiver<String>,
) {
while let Some(msg) = rx.next().await {
session.dispatch_message(msg);
}
// TODO(bartlomieju): notify that the IO has disconnected
// and the session should be dropped
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

TODO: Remote session cleanup on disconnect.

The TODO at lines 806-807 indicates that session cleanup on IO disconnect is not fully implemented. When the pump_inspector_session_messages future completes (channel closed), the session should be removed from SessionContainer.local. Currently, this appears to leak the session entry.

When the remote session's message channel closes, the session remains in SessionContainer.local but is no longer functional. This could cause:

  1. Memory leaks for long-running processes
  2. Incorrect sessions_state() reporting

Consider implementing proper cleanup:

 async fn pump_inspector_session_messages(
   session: Rc<InspectorSession>,
   mut rx: UnboundedReceiver<String>,
-) {
+) -> i32 {
   while let Some(msg) = rx.next().await {
     session.dispatch_message(msg);
   }
-  // TODO(bartlomieju): notify that the IO has disconnected
-  // and the session should be dropped
+  session.id
 }

Then handle the returned session ID in pump_messages_for_remote_sessions to remove the session from local.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In core/inspector.rs around lines 799-808, the pump_inspector_session_messages
future currently drops out when the UnboundedReceiver closes but does not remove
the session from SessionContainer.local, leaking entries and stale state; fix by
obtaining the session id (clone or call session.id()) before the message loop,
and when the rx loop ends call into the SessionContainer to remove that id from
local (acquire the same lock used elsewhere and remove by id), then change
pump_messages_for_remote_sessions to accept and handle the returned/removed
session id so the container state is consistent and the session is fully cleaned
up.

@codecov-commenter
Copy link

codecov-commenter commented Dec 1, 2025

Codecov Report

❌ Patch coverage is 42.48705% with 111 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.13%. Comparing base (0c7f83e) to head (2be3a31).
⚠️ Report is 388 commits behind head on main.

Files with missing lines Patch % Lines
core/inspector.rs 49.10% 85 Missing ⚠️
dcore/src/inspector_server.rs 0.00% 26 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1253      +/-   ##
==========================================
- Coverage   81.43%   80.13%   -1.31%     
==========================================
  Files          97      105       +8     
  Lines       23877    27570    +3693     
==========================================
+ Hits        19445    22094    +2649     
- Misses       4432     5476    +1044     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

// However it is can happen that poll_sessions() gets re-entered, e.g.
// when an interrupt request is honored while the inspector future is polled
// by the task executor. We let the caller know by returning some error.
pub fn try_poll_sessions(&self) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now segfaulting in Deno - try_borrow_mut raises:


Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000018
Exception Codes:       0x0000000000000001, 0x0000000000000018

Termination Reason:    Namespace SIGNAL, Code 11 Segmentation fault: 11
Terminating Process:   exc handler [5185]

VM Region Info: 0x18 is not in any region.  Bytes before following region: 4343693288
      REGION TYPE                    START - END         [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      UNUSED SPACE AT START
--->  
      __TEXT                      102e78000-112b30000    [252.7M] r-x/r-x SM=COW  /Users/USER/*/deno

Thread 0 Crashed:: main Dispatch queue: com.apple.main-thread
0   deno                          	       0x10b4fa8cc core::cell::RefCell$LT$T$GT$::try_borrow_mut::h1c6c30c81af95cae + 40
1   deno                          	       0x10b6da628 deno_core::inspector::JsRuntimeInspectorState::try_poll_sessions::hb4971fbdf9e5066d + 44
2   deno                          	       0x10b6dd850 deno_core::inspector::handle_interrupt::h2bc97e9d12cf0227 + 92

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
core/inspector.rs (1)

796-805: Session cleanup still needed.

The TODO at lines 803-804 about notifying when IO disconnects is already flagged in past review comments. This remains a valid concern for preventing session leaks.

🧹 Nitpick comments (4)
core/inspector.rs (4)

78-86: TODO: Consider lifecycle management for deregister_rx.

The TODO correctly identifies that polling the deregister receiver manually is an antipattern. This should ideally be handled automatically through Drop or a background task. However, since this is explicitly marked by the original author as a known design issue, it's acceptable for this PR.


419-424: Consider documenting session selection logic.

The TODO at line 419 questions why the first session is selected. If this is intentional behavior (e.g., any session can trigger the debugger), consider documenting this in a comment. If specific session selection is needed, clarify the requirements.


590-616: Consider session queue draining strategy.

The TODO at lines 604-605 raises a valid question about whether to fully drain new_io_session_rx before polling existing sessions. The current interleaved approach provides fairness. If you need to prioritize new session creation for responsiveness, consider fully draining the queue first.


669-676: Document interrupt handling logic.

The TODO at lines 669-670 suggests there's complex interaction logic that should be documented. Consider adding detailed comments explaining the interrupt request handling and state_ptr lifecycle.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 593dd22 and 78c50be.

📒 Files selected for processing (1)
  • core/inspector.rs (24 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
  • GitHub Check: build-linux / linux test
  • GitHub Check: build-linux / linux lint-deps
  • GitHub Check: build-windows / windows lint
  • GitHub Check: build-linux / linux coverage
  • GitHub Check: build-linux-arm / linux-arm test
  • GitHub Check: build-linux / linux test-miri
  • GitHub Check: build-linux / linux test-publish
  • GitHub Check: build-linux-arm / linux-arm test-miri
  • GitHub Check: build-macos / macos lint
  • GitHub Check: build-windows / windows test
  • GitHub Check: build-linux-arm / linux-arm lint
  • GitHub Check: build-macos / macos test
  • GitHub Check: build-linux / linux test-ops
🔇 Additional comments (5)
core/inspector.rs (5)

431-443: LGTM.

The single delegate constraint is properly enforced, and the initialization logic is correct.


653-658: LGTM after fixing line 316-317.

The interrupt handler correctly uses the state pointer and handles borrow failures gracefully. Once the critical pointer bug at lines 316-317 is fixed, this will be safe.


518-542: LGTM.

The session state logic correctly handles the empty case and properly checks session kinds.


570-588: LGTM.

The create_new_session method correctly manages session IDs and insertion into the local map.


478-506: LGTM.

The SessionContainer field updates properly support the new remote IO session model with appropriate channel and futures management.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants