# Data flow — denoland/deno

> Canonical page: https://codevetter.com/unpack/deno/data-flow

# Data flow — denoland/deno

Scanned commit 461f32ec6174d88b7e43654a054d46d67ae2fdab (2026-09-21). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Input boundaries are argv (parsed into `Flags` by the const-table parser), environment variables and `.env` files, config files (`deno.json`/`package.json`) discovered through the workspace factory, and remote sources fetched over HTTP from JSR and npm registries. `CliFactory` owns the service graph; `ModuleGraphBuilder` builds a `deno_graph::ModuleGraph` from roots, `TypeChecker` optionally validates it against a TSC-backed cache, and `CliEmitter` transpiles TypeScript to JavaScript. At runtime, `CliModuleLoader::load` serves module source out of the prepared graph (or delegates to JS load hooks, or to an eszip), and V8 executes it. Every side-effecting op re-enters Rust through `PermissionsContainer`, which is the single state owner for capability decisions. Output boundaries are stdout/stderr (via `deno_print`/`DrawThread`), the DENO_DIR SQLite and HTTP caches, the lockfile, OpenTelemetry exporters, and for `compile`, a written executable.
- argv → `Flags` happens in `resolve_flags_and_init`, which special-cases the `COMPLETE` env var for shell completions, distinguishes `--version` from `-V` before parsing, and only then calls `flags_from_vec_with_initial_cwd`. — [cli/lib.rs#L967-1000](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/cli/lib.rs#L967-L1000)
- `.env` files are loaded into the process environment before any service construction: `load_env_variables_from_env_files(&cwd, files, flags.log_level)` runs right after flag parsing, and `WatchEnvTracker::snapshot()` captures pre-load state when `--watch` is active. — [cli/lib.rs#L1000-1017](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/cli/lib.rs#L1000-L1017) [libs/dotenv](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/libs/dotenv)
- Unstable feature configuration is merged from three sources in order: CLI flags, `flags.unstable_config.fill_with_env(&sys)`, and the `DENO_COMPAT` env var which force-enables node compat; `DENO_CONDITIONS` similarly seeds `flags.node_conditions`. — [cli/lib.rs#L1053-1070](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/cli/lib.rs#L1053-L1070)
- Module loading is two-phase: `ModuleLoadPreparer::prepare_module_load` builds the graph with npm resolution (`build_graph_roots_with_npm_resolution`), validates roots, runs `TypeChecker::check` only when `type_check_mode().is_true()` and the graph wasn't already checked, then writes the lockfile *after* type checking because checking can discover `@types/node`. — [cli/module_loader.rs#L193-300](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/cli/module_loader.rs#L193-L300)
- `CliModuleLoader::load` has three source paths in priority order: an eszip loader when `maybe_eszip_loader` is set, the JS module-hook bridge (`hook_registry.push_load`) for async non-CJS loads, and otherwise the prepared graph; it records every specifier into `loaded_files` for watch-mode invalidation. — [cli/module_loader.rs#L1428-1520](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/cli/module_loader.rs#L1428-L1520)
- The load-hook bridge deliberately skips CJS modules because `Module._load` already runs `executeLoadHookChain` synchronously — going through both would invoke user hooks twice. — [cli/module_loader.rs#L1445-1463](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/cli/module_loader.rs#L1445-L1463)
- Remote source fetching flows through `CliFileFetcher`, which takes a `FetchPermissionsOptionRef` per call; `deploy` explicitly passes `AllowAll` plus `CacheSetting::RespectHeaders` so jsr.io's `cache-control: max-age=60` is honoured instead of pinning the first cached copy forever. — [cli/tools/deploy.rs#L59-76](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/cli/tools/deploy.rs#L59-L76) [cli/file_fetcher.rs](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/cli/file_fetcher.rs) [cli/factory.rs#L553-572](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/cli/factory.rs#L553-L572)
- npm resolution mode determines the read-permission checker: `create_module_loader_factory` picks `NpmRegistryReadPermissionCheckerMode::Byonm`, `::Local(node_modules_dir)`, or `::Global(npm_cache_root)` before constructing `CliModuleLoaderFactory`. — [cli/factory.rs#L1233-1255](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/cli/factory.rs#L1233-L1255)
- The root permission set is derived once from config+flags: `CliFactory::root_permissions_container` builds `Permissions::from_options(desc_parser, cli_options.permissions_options()?)` and wraps it in a `PermissionsContainer` that all workers clone from. — [cli/factory.rs#L1191-1206](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/cli/factory.rs#L1191-L1206) [runtime/permissions/lib.rs#L4132](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/runtime/permissions/lib.rs#L4132)
- Worker construction pre-installs npm packages: `create_custom_worker` collects `NpmPackageReqReference`s from the main module plus preload/require modules and calls `npm_installer.add_package_reqs` with `PackageCaching::Only` under the Lazy strategy or `PackageCaching::All` otherwise. — [cli/worker.rs#L596-640](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/cli/worker.rs#L596-L640)
- For an `npm:` main module, the specifier is rewritten to a resolved bin entrypoint via `resolve_npm_binary_entrypoint`, and the lockfile is flushed with `write_if_changed()` so the next run can reuse the resolution. — [cli/worker.rs#L641-668](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/cli/worker.rs#L641-L668)
- Bootstrap data crosses the Rust→JS boundary as a positional array: `bootstrapMainRuntime(runtimeOptions)` destructures indices 0–19 (denoVersion, location, unstableFeatures, hasNodeModulesDir, argv0, nodeDebug, mode, servePort, serveHost, otelConfig, standalone, nodeClusterUniqueId, …) and then removes the bootstrap object from the global scope. — [runtime/js/99_main.js#L936-1060](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/runtime/js/99_main.js#L936-L1060)
- Telemetry is initialised before any subcommand runs: `deno_telemetry::init(&sys, otel_runtime_config(), otel_config)` is called from `resolve_flags_and_init`, and failure paths report through `deno_telemetry::report_event("boot_failure" | "uncaught_exception", e)` in `run_script`. — [cli/lib.rs#L1077-1084](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/cli/lib.rs#L1077-L1084) [cli/tools/run/mod.rs#L229-245](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/cli/tools/run/mod.rs#L229-L245)
- Permission decisions can be teed to an audit sink: `DENO_AUDIT_PERMISSIONS=otel` routes each access through `deno_telemetry::handle_log` with `deno.permission.{type,value,stack}` key-values, and any other value is treated as a file path opened with `File::create`. — [cli/lib.rs#L1100-1130](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/cli/lib.rs#L1100-L1130)
- `deno run -` reads stdin fully into memory and injects it as a synthetic file via `file_fetcher.insert_memory_files(File { url: main_module, … })` so the type checker and graph builder can see it as a normal module. — [cli/tools/run/mod.rs#L249-290](https://github.com/denoland/deno/blob/461f32ec6174d88b7e43654a054d46d67ae2fdab/cli/tools/run/mod.rs#L249-L290)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
