denoland/deno
Runtime
Active contributors: Bartek Iwańczuk, Divy Srivastava, Matt Mastracci
Purpose
The runtime/ directory is the deno_runtime crate. It assembles deno_core::JsRuntime into a usable JavaScript runtime by registering every extension in ext/, threading permissions through op state, bootstrapping the JS environment, and exposing two top-level worker types: MainWorker (for the main thread) and WebWorker (for new Worker(...) instances).
Directory layout
runtime/
├── Cargo.toml
├── lib.rs # re-exports + module declarations
├── worker.rs # 1,348 lines: MainWorker
├── web_worker.rs # 1,300 lines: WebWorker
├── worker_bootstrap.rs # BootstrapOptions threaded into JS
├── ops/ # runtime-level ops (e.g. exit hooks)
├── js/ # JS bootstrap files baked into the snapshot
├── snapshot.rs # build-time snapshot creation
├── snapshot_info.rs # runtime-side snapshot metadata
├── tokio_util.rs # current_thread runtime helper + metrics
├── fmt_errors.rs # error formatter using source maps
├── code_cache.rs # V8 bytecode cache
├── permissions.rs # thin re-export of deno_permissions
├── permissions/ # deno_permissions crate (separate workspace member)
│ ├── lib.rs # 10,921 lines: PermissionsContainer + checkers
│ ├── prompter.rs # interactive prompt
│ ├── broker.rs # external permission broker support
│ └── …
├── features/ # deno_features crate (UNSTABLE_FEATURES registry)
├── subprocess_windows/ # Windows-specific child-process plumbing
└── cpu_profiler/ # built-in CPU profiler (`--profile`)The crate is wired together by lib.rs, which re-exports each deno_* extension crate (deno_cache, deno_cron, deno_crypto, deno_fetch, …) and exposes the two Worker types plus BootstrapOptions.
Key abstractions
| Type | File | Role |
|---|---|---|
MainWorker |
runtime/worker.rs |
The runtime that hosts user code on the main thread |
WebWorker |
runtime/web_worker.rs |
The runtime backing JS Worker instances |
BootstrapOptions |
runtime/worker_bootstrap.rs |
Config bundle marshalled into JS at startup |
WorkerExecutionMode |
runtime/worker_bootstrap.rs |
Run / Test / Bench / Repl / Eval / Serve enum |
PermissionsContainer |
runtime/permissions/lib.rs |
Threaded through op state, gates every privileged op |
CodeCache |
runtime/code_cache.rs |
Persistent V8 bytecode cache for warm startup |
CpuProfiler |
runtime/cpu_profiler/ |
Built-in CPU sampling profiler, exposed via --profile |
UnconfiguredRuntime |
runtime/worker.rs |
A pre-built JsRuntime shell shared between subcommands so cold starts don't re-create the V8 isolate |
FeatureChecker |
re-export from runtime/features (deno_features) |
Centralized unstable-feature gating |
How it works
graph TD
Factory["cli/factory.rs"] -->|create_main_worker| MainWorker
BootstrapOpts["BootstrapOptions"] --> MainWorker
Perms["PermissionsContainer"] --> MainWorker
ML["ModuleLoader<br/>cli/module_loader.rs"] --> MainWorker
MainWorker --> JsRuntime["deno_core::JsRuntime<br/>libs/core"]
JsRuntime --> V8[("V8 isolate")]
MainWorker --> Exts["Extensions registered:<br/>deno_web, deno_fetch, deno_node,<br/>deno_fs, deno_net, deno_kv, …"]
Exts -->|ops| JsRuntime
Bootstrap["runtime/js/<br/>bootstrap JS"] --> JsRuntime
Snapshot["runtime/snapshot.rs<br/>baked V8 heap"] --> JsRuntime
MainWorker -->|spawn Worker| WebWorkerWorker construction
Both MainWorker::bootstrap_from_options and WebWorker::bootstrap_from_options follow the same shape:
- Take a
BootstrapOptionsplus extension state (FS provider, permissions, feature checker, blob store, code cache, etc.). - Build the list of
deno_core::Extensions by calling eachdeno_<area>::deno_<area>::init_ops_and_esm(...). This is done insideruntime/worker.rsandruntime/web_worker.rs— search fordeno_web::deno_web::init_ops_and_esmetc. - Construct a
JsRuntimeviaRuntimeOptions { extensions, ... }. - Inject the
BootstrapOptionsinto JS by calling the bootstrap entry point (defined inruntime/js/). - Return the worker, ready to load and execute modules.
Extensions
Every entry in the workspace's ext/ directory shows up in runtime/lib.rs as a pub use deno_*; and gets registered by name in worker construction. The order matters because some extensions depend on globals defined by others (e.g., deno_fetch depends on deno_web for streams). The canonical list to follow when adding a new extension is in the init_ops_and_esm chain in runtime/worker.rs.
Permissions
The runtime never runs unguarded native code. Every privileged op:
let perms = state.borrow_mut::<PermissionsContainer>();
perms.check_read(&path, "Deno.openSync()")?;The PermissionsContainer is constructed by the CLI via cli/factory.rs, populated from --allow-*/--deny-* flags, and inserted into op state at worker construction. See Permissions for the model.
Snapshots
runtime/snapshot.rs (build-time) loads every extension's JS and produces a serialized V8 heap. runtime/snapshot_info.rs exposes that snapshot at runtime so the binary starts with most globals already set up. The HMR feature flag (--features hmr) bypasses the snapshot and reads JS sources from disk at runtime; this is the mode you want when iterating on extension JS.
Code cache
runtime/code_cache.rs provides an opt-in persistent cache of V8 bytecode keyed by module URL + content hash. The CLI wires this up so subsequent runs of the same script skip re-parsing. The cache lives in DENO_DIR and is cleaned up by deno clean.
UnconfiguredRuntime
To improve cold-start for sequential deno invocations (notably deno run followed immediately by error formatting, or deno test with many test files), the runtime exposes UnconfiguredRuntime — a partially-constructed JsRuntime that can be reused across subcommands. cli/lib.rs::run_subcommand accepts an Option<UnconfiguredRuntime> and threads it into the worker constructor when present.
The error formatter
Errors that escape JS are caught by runtime/fmt_errors.rs::format_js_error, which:
- Resolves source map info (using
deno_core::source_map) - Adds colors via
deno_terminal::colors - Prints stack frames in a developer-friendly format
cli/lib.rs::main runs every subcommand result through this formatter before exiting.
Integration points
- Built by:
cli/factory.rs(and helpers incli/worker.rs/cli/lib/(thedeno_libcrate)). - Embeds: every
deno_*extension crate fromext/. - Depends on:
deno_core(libs/core) for the V8/Tokio integration;deno_permissions(runtime/permissions/) for capability gating. - Provides to JS: the
Deno.*namespace, the web platform globals,node:*modules (viadeno_node), workers, KV, cron, etc.
Entry points for modification
- Adding a new built-in JS module exposed at runtime → add it to the relevant extension under
ext/, then make sureruntime/lib.rsre-exports the extension andruntime/worker.rsregisters it. - Changing how workers are constructed (e.g., new bootstrap option) → update
runtime/worker_bootstrap.rs::BootstrapOptions, thread the new field throughMainWorker::bootstrap_from_optionsand theruntime/js/bootstrap script. - Tweaking error formatting →
runtime/fmt_errors.rs. - Code cache / snapshot behavior →
runtime/code_cache.rs,runtime/snapshot.rs,cli/snapshot/.
Key source files
| File | Purpose |
|---|---|
runtime/lib.rs |
Re-exports every extension; declares pub mod worker, pub mod web_worker, etc. |
runtime/worker.rs |
MainWorker: extension registration, bootstrap, event loop, error formatting hooks |
runtime/web_worker.rs |
WebWorker for the JS Worker constructor; smaller surface than MainWorker |
runtime/worker_bootstrap.rs |
BootstrapOptions, WorkerExecutionMode, WorkerLogLevel |
runtime/snapshot.rs |
Build-time V8 snapshot creation |
runtime/snapshot_info.rs |
Runtime-side snapshot metadata |
runtime/code_cache.rs |
Persistent V8 bytecode cache |
runtime/cpu_profiler/ |
CPU sampling profiler |
runtime/fmt_errors.rs |
JS error → human-readable formatter |
runtime/tokio_util.rs |
create_and_run_current_thread_with_maybe_metrics helper |
runtime/permissions/lib.rs |
deno_permissions crate — see Permissions |
runtime/features/ |
deno_features crate — UNSTABLE_FEATURES registry |
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.