Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Errors, Cancellation, Resources, and Shutdown

ReliabilityFailure across two runtimesRevision 89f33cb

Errors cross an intentional mapping boundary

An op commonly returns Result<R, E> where E implements Deno’s JavaScript error classification contract. The generated/runtime mapping chooses the JavaScript error class, message, and stack behavior. A filesystem error is not merely formatted text; callers should receive a useful JavaScript exception.

The runtime also distinguishes larger failure scopes:

  • one op rejects one promise;
  • an unhandled promise rejection follows language policy;
  • module evaluation can fail;
  • a worker can report a terminal error to its host;
  • an isolate/runtime failure can end the process-level operation.

Permission denial is an ordinary operation failure

Filesystem and network ops check permission immediately before capability use. For TCP connection, Deno checks the requested hostname and then checks resolved IP candidates as well. This prevents a name-resolution path from bypassing network policy.

Cancellation is cooperative and cross-layer

For readTextFile({ signal }):

  1. JavaScript creates a CancelHandle resource.
  2. Rust retrieves it before the relevant await.
  3. or_cancel observes either operation completion or cancellation.
  4. Closing the resource signals the pending operation.
  5. Rust removes the temporary resource on every exit path.
  6. JavaScript removes its listener in finally.

Cancellation does not preempt arbitrary Rust instructions. It is observed at a future boundary designed to handle it.

Resource close is stronger than map removal

Removing rid → resource stops future JavaScript lookup. It may not destroy the resource immediately because pending ops can hold cloned Rcs. The Resource trait’s close method lets a type cancel outstanding work as part of closure.

TcpStreamResource explicitly cancels read/write operations. The source even documents a subtle method-resolution failure that once made close call the trait’s no-op default instead of the concrete cancellation behavior. This is a good production lesson: cleanup paths deserve focused tests because code that looks like ownership release may not yet release the operating-system resource.

Event-loop completion is a liveness proof

The runtime tracks pending ops, refed ops, timers, module evaluation, dynamic imports, background tasks, promise events, external operations, and live native handles. Returning Ready(Ok(())) means none of the work that should keep the program alive remains.

That is stronger than “the queue was empty during this poll.”

Worker shutdown closes admission and wakes ownership

A Web Worker has a control path and termination waker. Its event-loop poll first checks termination, registers for later termination, and delegates ordinary progress to JsRuntime. The host receives structured close or terminal-error events.

The general pattern is:

record stop intent → wake blocked event loop → stop admitting work
→ cancel/close owned resources → report terminal outcome

Reliable async systems represent shutdown as an ownership protocol, not merely as a boolean checked occasionally.